Merge "Adding hlist module to mediawiki"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 19 Nov 2013 11:17:47 +0000 (11:17 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 19 Nov 2013 11:17:47 +0000 (11:17 +0000)
646 files changed:
.gitignore
CREDITS
RELEASE-NOTES-1.22
RELEASE-NOTES-1.23
docs/README
docs/hooks.txt
docs/maintenance.txt
docs/memcached.txt
extensions/README
includes/ArrayUtils.php [deleted file]
includes/Article.php
includes/AutoLoader.php
includes/CallableUpdate.php [deleted file]
includes/Cdb.php [deleted file]
includes/Cdb_PHP.php [deleted file]
includes/ChangeTags.php
includes/ConfEditor.php [deleted file]
includes/DataUpdate.php [deleted file]
includes/DefaultSettings.php
includes/DeferredUpdates.php [deleted file]
includes/EditPage.php
includes/Exception.php
includes/FormOptions.php
includes/GlobalFunctions.php
includes/HashRing.php [deleted file]
includes/Hooks.php
includes/IP.php [deleted file]
includes/ImagePage.php
includes/Init.php
includes/LinksUpdate.php [deleted file]
includes/MWCryptRand.php [deleted file]
includes/MWFunction.php [deleted file]
includes/MappedIterator.php [deleted file]
includes/OutputPage.php
includes/PageQueryPage.php
includes/ProxyTools.php
includes/Sanitizer.php
includes/ScopedCallback.php [deleted file]
includes/ScopedPHPTimeout.php [deleted file]
includes/SiteStats.php
includes/Skin.php
includes/SkinTemplate.php
includes/SpecialPage.php
includes/SpecialPageFactory.php
includes/SqlDataUpdate.php [deleted file]
includes/Status.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/WebRequest.php
includes/Wiki.php
includes/WikiFilePage.php
includes/WikiPage.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 [changed mode: 0755->0644]
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/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/ContentHandler.php
includes/content/TextContent.php
includes/db/Database.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/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/filebackend/FileBackendStore.php
includes/filebackend/FileOp.php
includes/filebackend/SwiftFileBackend.php
includes/filerepo/ForeignAPIRepo.php [changed mode: 0755->0644]
includes/filerepo/file/ForeignAPIFile.php [changed mode: 0755->0644]
includes/installer/DatabaseInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/MysqlUpdater.php
includes/installer/PostgresUpdater.php
includes/installer/WebInstaller.php
includes/installer/WebInstallerOutput.php
includes/installer/WebInstallerPage.php
includes/job/JobQueueFederated.php
includes/job/JobQueueRedis.php
includes/job/aggregator/JobQueueAggregatorRedis.php
includes/libs/ScopedPHPTimeout.php [new file with mode: 0644]
includes/libs/XmlTypeCheck.php [new file with mode: 0644]
includes/logging/LogEntry.php
includes/media/Bitmap.php
includes/media/FormatMetadata.php [changed mode: 0755->0644]
includes/media/MediaHandler.php [changed mode: 0755->0644]
includes/parser/CacheTime.php
includes/parser/CoreParserFunctions.php
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserOptions.php
includes/profiler/ProfilerSimpleUDP.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/search/SearchUpdate.php [deleted file]
includes/specials/SpecialAllpages.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialConfirmemail.php
includes/specials/SpecialEditWatchlist.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListredirects.php
includes/specials/SpecialLog.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRevisiondelete.php
includes/specials/SpecialSearch.php
includes/specials/SpecialUpload.php
includes/specials/SpecialUploadStash.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialWatchlist.php
includes/upload/UploadBase.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]
languages/Language.php
languages/LanguageConverter.php
languages/Names.php
languages/messages/MessagesAce.php
languages/messages/MessagesAeb.php
languages/messages/MessagesAf.php
languages/messages/MessagesAln.php
languages/messages/MessagesAm.php
languages/messages/MessagesAn.php
languages/messages/MessagesAng.php
languages/messages/MessagesAr.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/MessagesBjn.php
languages/messages/MessagesBn.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/MessagesCy.php
languages/messages/MessagesDa.php
languages/messages/MessagesDe.php
languages/messages/MessagesDiq.php
languages/messages/MessagesDsb.php
languages/messages/MessagesDtp.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/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/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/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/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/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/MessagesUg_arab.php
languages/messages/MessagesUk.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
maintenance/archives/patch-val_ip.sql [deleted file]
maintenance/archives/patch-validate.sql [deleted file]
maintenance/backup.inc
maintenance/backupTextPass.inc
maintenance/cleanupUploadStash.php
maintenance/copyFileBackend.php
maintenance/doMaintenance.php
maintenance/dumpIterator.php
maintenance/eval.php
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/moveBatch.php
maintenance/postgres/mediawiki_mysql2postgres.pl
maintenance/purgeChangedFiles.php
maintenance/rebuildLocalisationCache.php
maintenance/rebuildrecentchanges.php
maintenance/runScript.php [new file with mode: 0644]
maintenance/tables.sql
maintenance/update.php
resources/Resources.php
resources/jquery/jquery.placeholder.js
resources/jquery/jquery.spinner.js
resources/mediawiki.action/mediawiki.action.edit.js
resources/mediawiki.page/mediawiki.page.watch.ajax.js
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.inspect.js
resources/mediawiki/mediawiki.jqueryMsg.js
resources/mediawiki/mediawiki.js
resources/mediawiki/mediawiki.user.js
resources/mediawiki/mediawiki.util.js
skins/common/commonElements.css
skins/common/protect.js
skins/common/upload.js
skins/common/wikibits.js
skins/vector/screen.less
skins/vector/styles-beta.less
skins/vector/styles.less
tests/TestsAutoLoader.php
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/ArticleTablesTest.php
tests/phpunit/includes/CdbTest.php [deleted file]
tests/phpunit/includes/ExceptionTest.php [new file with mode: 0644]
tests/phpunit/includes/FormOptionsTest.php
tests/phpunit/includes/GlobalFunctions/GlobalTest.php
tests/phpunit/includes/GlobalFunctions/wfExpandUrlTest.php
tests/phpunit/includes/HashRingTest.php [deleted file]
tests/phpunit/includes/IPTest.php [deleted file]
tests/phpunit/includes/RecentChangeTest.php [deleted file]
tests/phpunit/includes/SpecialPageTest.php [new file with mode: 0644]
tests/phpunit/includes/StringUtilsTest.php [deleted file]
tests/phpunit/includes/TemplateCategoriesTest.php
tests/phpunit/includes/UIDGeneratorTest.php [deleted file]
tests/phpunit/includes/WebRequestTest.php
tests/phpunit/includes/ZipDirectoryReaderTest.php [deleted file]
tests/phpunit/includes/api/ApiBaseTest.php [new file with mode: 0644]
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/ApiTest.php [deleted file]
tests/phpunit/includes/api/ApiTokensTest.php [new file with mode: 0644]
tests/phpunit/includes/api/format/ApiFormatWddxTest.php
tests/phpunit/includes/changes/RecentChangeTest.php [new file with mode: 0644]
tests/phpunit/includes/content/WikitextContentHandlerTest.php
tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
tests/phpunit/includes/db/DatabaseSqliteTest.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/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/LanguageTest.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/structure/AutoLoaderTest.php
tests/phpunit/structure/ResourcesTest.php
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
thumb.php

index 7d1a309..9c0c3b6 100644 (file)
@@ -41,7 +41,6 @@ sftp-config.json
 
 # Building & testing
 node_modules/
-.sass-cache/
 
 # Composer
 /vendor
diff --git a/CREDITS b/CREDITS
index 23636ae..01505b0 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -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
index 25d5c42..333696b 100644 (file)
@@ -67,6 +67,8 @@ production.
 * 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.
@@ -253,13 +255,16 @@ 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
@@ -348,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
@@ -420,15 +427,6 @@ changes to languages because of Bugzilla reports.
 * (bug 46751) Made Buryat (Russia) (буряад) (bxr) fallback to Russian.
 
 === Other changes in 1.22 ===
-* 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.
 * BREAKING CHANGE: Implementation of MediaWiki's JS and JSON value encoding
   has changed:
 ** MediaWiki no longer supports PHP installations in which the native JSON
@@ -533,6 +531,9 @@ changes to languages because of Bugzilla reports.
   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 ==
 
index c9b56b9..e8af684 100644 (file)
@@ -9,6 +9,18 @@ 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.
@@ -18,14 +30,34 @@ production.
   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.
 
 === 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 19415) action=render no longer shows section edit links. This affects
+  behavior of several other features where (bogus) section edit links will
+  disappear, such as file description pages loaded via $wgUseInstantCommons or
+  pages transcluded cross-wiki via $wgEnableScaryTranscluding.
+* (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.
 
 === API changes in 1.23 ===
+* (bug 54884) action=parse&prop=categories now indicates hidden and missing
+  categories.
 
 === Languages updated in 1.23===
 
@@ -34,7 +66,18 @@ regularly. Below only new and removed languages are listed, as well as
 changes to languages because of Bugzilla reports.
 
 === Other changes in 1.23 ===
-* The global variable $wgArticle has been removed after a lengthy deprecation
+* 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.
 
 == Compatibility ==
 
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 96a72df..30b9b72 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
@@ -1213,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
@@ -1534,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
@@ -1761,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
@@ -1847,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.
@@ -1855,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
 
@@ -1893,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
@@ -2376,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
 
@@ -2843,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
diff --git a/includes/ArrayUtils.php b/includes/ArrayUtils.php
deleted file mode 100644 (file)
index 97a56e1..0000000
+++ /dev/null
@@ -1,68 +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 $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;
-       }
-}
index 928fda0..854f7f1 100644 (file)
@@ -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();
                }
@@ -1472,6 +1478,7 @@ class Article implements Page {
         */
        public function render() {
                $this->getContext()->getOutput()->setArticleBodyOnly( true );
+               $this->getContext()->getOutput()->enableSectionEditLinks( false );
                $this->view();
        }
 
index dbba500..cd634c2 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,7 +387,6 @@ $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',
@@ -448,9 +394,6 @@ $wgAutoloadLocalClasses = array(
        '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 +406,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 +488,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',
+       '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/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',
 
@@ -708,6 +680,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 +841,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 +885,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',
 
@@ -1067,6 +1042,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 +1113,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,7 +1141,7 @@ $wgAutoloadLocalClasses = array(
 );
 
 class AutoLoader {
-       static $autoloadLocalClassesLower = null;
+       static protected $autoloadLocalClassesLower = null;
 
        /**
         * autoload - take a class name and attempt to load it
@@ -1159,6 +1164,8 @@ 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] ) ) {
@@ -1171,7 +1178,6 @@ class AutoLoader {
                         * and we are plagued with several legacy uses created by MediaWiki < 1.5, see
                         * https://wikitech.wikimedia.org/wiki/Text_storage_data
                         */
-                       $filename = false;
                        $lowerClass = strtolower( $className );
 
                        if ( self::$autoloadLocalClassesLower === null ) {
@@ -1218,6 +1224,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' ) );
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 7ec641d..3c734c4 100644 (file)
@@ -193,10 +193,9 @@ class ChangeTags {
                        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', "ct_$join_cond=$join_cond"
+               );
 
                if ( $wgUseTagFilter && $filter_tag ) {
                        // Somebody wants to filter on a tag.
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';
-       }
-}
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 ebae110..d428910 100644 (file)
@@ -2285,7 +2285,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();
 
@@ -4895,10 +4897,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();
 
@@ -5011,7 +5032,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';
 
diff --git a/includes/DeferredUpdates.php b/includes/DeferredUpdates.php
deleted file mode 100644 (file)
index c385f13..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 ) {
-                                       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();
-       }
-}
index 530e267..be350cb 100644 (file)
@@ -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;
@@ -2937,7 +2953,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" ) );
@@ -3155,6 +3171,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();
@@ -3165,8 +3185,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() );
@@ -3195,7 +3214,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>";
                                }
                        }
 
index ac98564..008be15 100644 (file)
@@ -779,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.
@@ -788,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 );
        }
 
        /**
@@ -826,7 +906,13 @@ class MWExceptionHandler {
                        } else {
                                wfDebugLog( 'exception', $log );
                        }
+
+                       $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK );
+                       if ( $json !== false ) {
+                               wfDebugLog( 'exception-json', $json, false );
+                       }
                }
+
        }
 
 }
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 ef0ec2c..688300a 100644 (file)
@@ -495,18 +495,19 @@ function wfAppendQuery( $url, $query ) {
  *    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;
+       } else {
+               $serverUrl = $wgServer;
+               if ( $defaultProto === PROTO_CURRENT ) {
+                       $defaultProto = $wgRequest->getProtocol() . '://';
+               }
        }
-       if ( $defaultProto === PROTO_CURRENT ) {
-               $defaultProto = WebRequest::detectProtocol() . '://';
-       }
+
 
        // Analyze $serverUrl to obtain its protocol
        $bits = wfParseUrl( $serverUrl );
@@ -1008,7 +1009,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
@@ -1018,14 +1024,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 );
 }
 
 /**
@@ -2470,12 +2490,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' );
 }
 
 /**
@@ -2836,6 +2856,15 @@ function wfShellExec( $cmd, &$retval = null, $environ = array(),
        if ( $useLogPipe ) {
                $desc[3] = array( 'pipe', 'w' );
        }
+
+       # 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' );
+       }
+
        $pipes = null;
        $proc = proc_open( $cmd, $desc, $pipes );
        if ( !$proc ) {
@@ -3305,18 +3334,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.
@@ -3423,19 +3440,6 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
        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
  */
@@ -3825,21 +3829,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.
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 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 );
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 cf05ee2..d6b8a03 100644 (file)
@@ -350,15 +350,33 @@ 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
+                                               // 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] );
@@ -367,6 +385,7 @@ class ImagePage extends Article {
                                                        }
                                                }
                                        }
+                                       $otherSizes = array_unique( $otherSizes );
                                        $msgsmall = '';
                                        $sizeLinkBigImagePreview = $this->makeSizeLink( $params, $width, $height );
                                        if ( $sizeLinkBigImagePreview ) {
index 64431f0..dd5e2d7 100644 (file)
@@ -48,7 +48,7 @@ class MWInit {
         * @return bool
         */
        static function isHipHop() {
-               return defined( 'HPHP_VERSION' );
+               return wfIsHHVM();
        }
 
        /**
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 7f0454f..5ffb802 100644 (file)
@@ -256,10 +256,15 @@ class OutputPage extends ContextSource {
        private $mTarget = null;
 
        /**
-        * @var bool: Whether output should contain table of contents
+        * @var bool: Whether parser output should contain table of contents
         */
        private $mEnableTOC = true;
 
+       /**
+        * @var bool: Whether parser output should contain section edit links
+        */
+       private $mEnableSectionEditLinks = true;
+
        /**
         * Constructor for OutputPage. This should not be called directly.
         * Instead a new RequestContext should be created and it will implicitly create
@@ -1612,6 +1617,7 @@ class OutputPage extends ContextSource {
        function addParserOutput( &$parserOutput ) {
                $this->addParserOutputNoText( $parserOutput );
                $parserOutput->setTOCEnabled( $this->mEnableTOC );
+               $parserOutput->setEditSectionTokens( $this->mEnableSectionEditLinks );
                $text = $parserOutput->getText();
                wfRunHooks( 'OutputPageBeforeHTML', array( &$this, &$text ) );
                $this->addHTML( $text );
@@ -2980,9 +2986,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() );
@@ -3059,6 +3067,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
@@ -3670,4 +3681,21 @@ $templates
        public function isTOCEnabled() {
                return $this->mEnableTOC;
        }
+
+       /**
+        * Enables/disables section edit links, doesn't override __NOEDITSECTION__
+        * @param bool $flag
+        * @since 1.23
+        */
+       public function enableSectionEditLinks( $flag = true ) {
+               $this->mEnableSectionEditLinks = $flag;
+       }
+
+       /**
+        * @return bool
+        * @since 1.23
+        */
+       public function sectionEditLinksEnabled() {
+               return $this->mEnableSectionEditLinks;
+       }
 }
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 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 4dbc9dd..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 */';
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 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 170e96f..a71bafc 100644 (file)
@@ -1559,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 1e7ce13..0990584 100644 (file)
@@ -159,7 +159,7 @@ class SkinTemplate extends Skin {
                                        $language_urls[] = array(
                                                'href' => $languageLinkTitle->getFullURL(),
                                                'text' => $ilLangName,
-                                               'title' => wfMessage( 'tooltip-iwiki', $languageLinkTitle->getText(), $ilLangLocalName )->escaped(),
+                                               'title' => wfMessage( 'interlanguage-link-title', $languageLinkTitle->getText(), $ilLangLocalName )->text(),
                                                'class' => $class,
                                                'lang' => wfBCP47( $ilInterwikiCode ),
                                                'hreflang' => wfBCP47( $ilInterwikiCode ),
@@ -217,15 +217,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 +228,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 +545,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 +741,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;
        }
index a6195fc..20571d7 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 );
        }
 
        /**
index 11edc8a..1ede0c1 100644 (file)
@@ -108,7 +108,7 @@ class SpecialPageFactory {
                'Log'                       => 'SpecialLog',
                'Watchlist'                 => 'SpecialWatchlist',
                'Newpages'                  => 'SpecialNewpages',
-               'Recentchanges'             => 'SpecialRecentchanges',
+               'Recentchanges'             => 'SpecialRecentChanges',
                'Recentchangeslinked'       => 'SpecialRecentchangeslinked',
                'Tags'                      => 'SpecialTags',
 
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 836c24a..dc0bae0 100644 (file)
@@ -83,7 +83,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;
        }
@@ -94,7 +94,7 @@ class Status {
         *
         * @return Boolean
         */
-       function isGood() {
+       public function isGood() {
                return $this->ok && !$this->errors;
        }
 
@@ -103,7 +103,7 @@ class Status {
         *
         * @return Boolean
         */
-       function isOK() {
+       public function isOK() {
                return $this->ok;
        }
 
@@ -112,7 +112,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',
@@ -126,7 +126,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',
@@ -140,7 +140,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',
@@ -152,7 +152,7 @@ class Status {
        /**
         * Sanitize the callback parameter on wakeup, to avoid arbitrary execution.
         */
-       function __wakeup() {
+       public function __wakeup() {
                $this->cleanCallback = false;
        }
 
@@ -179,7 +179,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',
@@ -219,7 +219,7 @@ class Status {
         * @param string $longContext a long enclosing context message name, for a list
         * @return Message
         */
-       function getMessage( $shortContext = false, $longContext = false ) {
+       public function getMessage( $shortContext = false, $longContext = false ) {
                if ( count( $this->errors ) == 0 ) {
                        if ( $this->ok ) {
                                $this->fatal( 'internalerror_info',
@@ -239,7 +239,7 @@ class Status {
                                $s = wfMessage( $longContext, $wrapper );
                        }
                } else {
-                       $msgs =  $this->getErrorMessageArray( $this->errors );
+                       $msgs = $this->getErrorMessageArray( $this->errors );
                        $msgCount = count( $msgs );
 
                        if ( $shortContext ) {
@@ -316,7 +316,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 ) {
@@ -332,7 +332,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" );
        }
 
@@ -342,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 getWarningsArray() {
+       public function getWarningsArray() {
                return $this->getStatusArray( "warning" );
        }
 
@@ -398,7 +398,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;
@@ -418,7 +418,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 ) {
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..4b8a141 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
@@ -3110,6 +3111,7 @@ class Title {
                $this->mLatestID = false;
                $this->mContentModel = false;
                $this->mEstimateRevisions = null;
+               $this->mPageLanguage = false;
        }
 
        /**
@@ -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 c86b966..224626b 100644 (file)
@@ -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();
+                       }
                }
        }
 
index 8ab10b2..6157f78 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();
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 b17cb9e..536ce12 100644 (file)
@@ -50,6 +50,12 @@ class WebRequest {
         */
        private $ip;
 
+       /**
+        * Cached URL protocol
+        * @var string
+        */
+       private $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
@@ -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 a690176..50bba7b 100644 (file)
@@ -540,7 +540,7 @@ class MediaWiki {
                                        && $this->context->getUser()->requiresHTTPS()
                                )
                        ) &&
-                       $request->detectProtocol() == 'http'
+                       $request->getProtocol() == 'http'
                ) {
                        $oldUrl = $request->getFullRequestURL();
                        $redirUrl = str_replace( 'http://', 'https://', $oldUrl );
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 6d2d80c..6c2c6ad 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;
        }
 
@@ -2747,6 +2761,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 );
 
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..e492bd4 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 stdObject $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..47fb687 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 '';
        }
 
@@ -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,8 +528,8 @@ abstract class ApiBase extends ContextSource {
 
                                $msg .= sprintf( "  %-19s - %s\n", $this->encodeParamName( $paramName ), $desc );
                        }
-                       return $msg;
 
+                       return $msg;
                } else {
                        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();
        }
 
@@ -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
@@ -1458,7 +1913,8 @@ abstract class ApiBase extends ContextSource {
        }
 
        /**
-        * 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..1049b49 100644 (file)
@@ -65,8 +65,11 @@ 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' );
+                       $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 );
                }
@@ -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..4e1c871 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,6 +379,7 @@ class ApiEditPage extends ApiBase {
                        if ( count( $r ) ) {
                                $r['result'] = 'Failure';
                                $apiResult->addValue( null, $this->getModuleName(), $r );
+
                                return;
                        } else {
                                $this->dieUsageMsg( 'hookaborted' );
@@ -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..27037cb 100644 (file)
@@ -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,
@@ -107,6 +107,7 @@ class ApiFeedContributions extends ApiBase {
                                $comments
                        );
                }
+
                return null;
        }
 
@@ -142,12 +143,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..15dc73b 100644 (file)
@@ -43,6 +43,7 @@ class ApiFormatJson extends ApiFormatBase {
                if ( $params['callback'] ) {
                        return 'text/javascript';
                }
+
                return 'application/json';
        }
 
@@ -80,8 +81,10 @@ 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.',
                );
        }
 
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 13e58b8..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;
@@ -255,24 +258,39 @@ 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'
+                       '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' => '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' => '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 c11f16c..c3ada1f 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 ) {
@@ -191,7 +194,7 @@ class ApiMain extends ApiBase {
                $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 +273,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 +282,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 +342,7 @@ class ApiMain extends ApiBase {
                if ( $printer === null ) {
                        $this->dieUsage( "Unrecognized format: {$format}", 'unknown_format' );
                }
+
                return $printer;
        }
 
@@ -456,6 +462,7 @@ class ApiMain extends ApiBase {
                } else {
                        $origins = explode( ' ', $originHeader );
                }
+
                if ( !in_array( $originParam, $origins ) ) {
                        // origin parameter set but incorrect
                        // Send a 403 response
@@ -463,13 +470,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;
        }
 
@@ -478,7 +494,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 ) {
@@ -489,9 +506,11 @@ class ApiMain extends ApiBase {
                                                return false;
                                        }
                                }
+
                                return true;
                        }
                }
+
                return false;
        }
 
@@ -510,6 +529,7 @@ class ApiMain extends ApiBase {
                        array( '.*?', '.' ),
                        $wildcard
                );
+
                return "/https?:\/\/$wildcard/";
        }
 
@@ -524,6 +544,7 @@ class ApiMain extends ApiBase {
 
                if ( $this->mCacheMode == 'private' ) {
                        $response->header( 'Cache-Control: private' );
+
                        return;
                }
 
@@ -535,6 +556,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
@@ -542,6 +564,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
                }
@@ -565,6 +588,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;
                }
 
@@ -638,7 +662,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
@@ -715,11 +742,14 @@ class ApiMain extends ApiBase {
                        if ( !isset( $moduleParams['token'] ) ) {
                                $this->dieUsageMsg( array( 'missingparam', 'token' ) );
                        } else {
-                               if ( !$this->getUser()->matchEditToken( $moduleParams['token'], $salt, $this->getContext()->getRequest() ) ) {
+                               if ( !$this->getUser()
+                                       ->matchEditToken( $moduleParams['token'], $salt, $this->getContext()->getRequest() )
+                               ) {
                                        $this->dieUsageMsg( 'sessionfailure' );
                                }
                        }
                }
+
                return $module;
        }
 
@@ -746,9 +776,11 @@ class ApiMain extends ApiBase {
                                } else {
                                        $this->dieUsage( "Waiting for a database server: $lag seconds lagged", 'maxlag' );
                                }
+
                                return false;
                        }
                }
+
                return true;
        }
 
@@ -759,8 +791,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() ) {
@@ -843,7 +875,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();
@@ -877,10 +909,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 );
        }
 
@@ -896,6 +930,7 @@ class ApiMain extends ApiBase {
         */
        public function getVal( $name, $default = null ) {
                $this->mParamsUsed[$name] = true;
+
                return $this->getRequest()->getVal( $name, $default );
        }
 
@@ -905,6 +940,7 @@ class ApiMain extends ApiBase {
         */
        public function getCheck( $name ) {
                $this->mParamsUsed[$name] = true;
+
                return $this->getRequest()->getCheck( $name );
        }
 
@@ -917,6 +953,7 @@ class ApiMain extends ApiBase {
         */
        public function getUpload( $name ) {
                $this->mParamsUsed[$name] = true;
+
                return $this->getRequest()->getUpload( $name );
        }
 
@@ -1034,13 +1071,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.',
                        ),
                );
        }
@@ -1054,14 +1095,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.',
@@ -1074,13 +1115,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',
                        '',
                        '',
                        '',
@@ -1109,11 +1152,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/'
@@ -1150,6 +1194,7 @@ class ApiMain extends ApiBase {
                if ( $wgAPICacheHelpTimeout > 0 ) {
                        $wgMemc->set( $key, $retval, $wgAPICacheHelpTimeout );
                }
+
                return $retval;
        }
 
@@ -1180,7 +1225,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";
@@ -1201,7 +1246,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 ) {
@@ -1234,6 +1280,7 @@ class ApiMain extends ApiBase {
         */
        public function getShowVersions() {
                wfDeprecated( __METHOD__, '1.21' );
+
                return false;
        }
 
@@ -1336,6 +1383,7 @@ class UsageException extends MWException {
                if ( is_array( $this->mExtraData ) ) {
                        $result = array_merge( $result, $this->mExtraData );
                }
+
                return $result;
        }
 
index 100392b..407e089 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;
        }
 
index c18036c..5d5d1b7 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'] ) {
@@ -167,6 +171,7 @@ class ApiMove extends ApiBase {
                                $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..433b743 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] );
        }
 
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..3ce5da2 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;
        }
 
@@ -425,6 +439,7 @@ class ApiParse extends ApiBase {
                        if ( $getWikitext ) {
                                $this->content = $page->getContent( Revision::RAW );
                        }
+
                        return $pout;
                }
        }
@@ -439,6 +454,7 @@ class ApiParse extends ApiBase {
                        $this->dieUsage( "Sections are not supported by " . $what, 'nosuchsection' );
                        $section = false;
                }
+
                return $section;
        }
 
@@ -456,29 +472,60 @@ 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
         */
@@ -491,7 +538,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 +573,7 @@ class ApiParse extends ApiBase {
                                $result[] = $entry;
                        }
                }
+
                return $result;
        }
 
@@ -544,6 +593,7 @@ class ApiParse extends ApiBase {
                                $result[] = $entry;
                        }
                }
+
                return $result;
        }
 
@@ -555,6 +605,7 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $entry, $content );
                        $result[] = $entry;
                }
+
                return $result;
        }
 
@@ -566,6 +617,7 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $entry, $value );
                        $result[] = $entry;
                }
+
                return $result;
        }
 
@@ -577,6 +629,7 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $entry, $link );
                        $result[] = $entry;
                }
+
                return $result;
        }
 
@@ -602,7 +655,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 +699,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',
@@ -707,9 +762,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 +776,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 +802,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..79a3b05 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..cfc2244 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() );
@@ -553,6 +593,7 @@ abstract class ApiQueryBase extends ApiBase {
                        array( 'invalidtitle', 'title' ),
                        array( 'invalidtitle', 'key' ),
                ) );
+
                return $errors;
        }
 }
@@ -587,6 +628,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..148c4dd 100644 (file)
@@ -86,16 +86,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->localRepo->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]]',
                );
        }
 
old mode 100755 (executable)
new mode 100644 (file)
index 81c9faf..86cba83
@@ -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';
                }
@@ -53,6 +54,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        'version' => $params['metadataversion'],
                        'language' => $params['extmetadatalanguage'],
                        'multilang' => $params['extmetadatamultilang'],
+                       'extmetadatafilter' => $params['extmetadatafilter'],
                );
 
                $pageIds = $this->getPageSet()->getAllTitlesByNamespace();
@@ -175,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',
@@ -267,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;
                }
 
@@ -278,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']})" );
                        }
                }
 
@@ -304,7 +310,7 @@ 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|array $metadataOpts Options for metadata fetching.
+        * @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
@@ -319,6 +325,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                'version' => $metadataOpts ?: 'latest',
                                'language' => $wgContLang,
                                'multilang' => false,
+                               'extmetadatafilter' => array(),
                        );
                }
                $version = $metadataOpts['version'];
@@ -389,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
@@ -448,6 +456,11 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        $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;
                }
 
@@ -505,6 +518,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        }
                }
                $result->setIndexedTagName( $retval, 'metadata' );
+
                return $retval;
        }
 
@@ -521,11 +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,
@@ -565,6 +581,10 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                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',
@@ -599,18 +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',
-                       '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',
+                       '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',
                );
        }
 
@@ -634,24 +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" ),
-                       '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.',
-                       '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',
                );
        }
@@ -773,6 +807,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                )
                        ),
                );
+
                return array_diff_key( $props, array_flip( $filter ) );
        }
 
@@ -786,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" ),
@@ -796,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 fae3377..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..50a3352 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;
        }
 
@@ -80,8 +81,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
 
                if ( $rc ) {
                        if ( ( $wgUser->useRCPatrol() && $rc->getAttribute( 'rc_type' ) == RC_EDIT ) ||
-                               ( $wgUser->useNPPatrol() && $rc->getAttribute( 'rc_type' ) == RC_NEW ) )
-                       {
+                               ( $wgUser->useNPPatrol() && $rc->getAttribute( 'rc_type' ) == RC_NEW )
+                       {
                                $validTokenUser = true;
                        }
                } else {
@@ -96,11 +97,11 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        if ( is_null( $cachedPatrolToken ) ) {
                                $cachedPatrolToken = $wgUser->getEditToken( 'patrol' );
                        }
+
                        return $cachedPatrolToken;
                } else {
                        return false;
                }
-
        }
 
        /**
@@ -155,7 +156,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 +188,23 @@ 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 +219,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 +271,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 +286,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 +302,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 +339,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 +359,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 +491,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 +555,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        foreach ( $type as $t ) {
                                $retval[] = $this->parseRCType( $t );
                        }
+
                        return $retval;
                }
                switch ( $type ) {
@@ -545,6 +585,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        // formatComment() calls wfMessage() among other things
                        return 'anon-public-user-private';
                }
+
                return 'public';
        }
 
@@ -610,7 +651,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                        'redirect',
                                        '!redirect',
                                        'patrolled',
-                                       '!patrolled'
+                                       '!patrolled',
+                                       'unpatrolled'
                                )
                        ),
                        'limit' => array(
@@ -636,6 +678,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 +698,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 +784,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                                'redirect' => 'boolean'
                        ),
                        'patrolled' => array(
-                               'patrolled' => 'boolean'
+                               'patrolled' => 'boolean',
+                               'unpatrolled' => 'boolean'
                        ),
                        'loginfo' => array(
                                'logid' => array(
@@ -781,7 +825,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 ac9e85a..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();
@@ -280,6 +278,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $this->getResult()->setIndexedTagName( $data, 'ns' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -303,6 +302,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                sort( $data );
 
                $this->getResult()->setIndexedTagName( $data, 'ns' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -318,6 +318,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        }
                }
                $this->getResult()->setIndexedTagName( $data, 'specialpage' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -334,6 +335,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = $arr;
                }
                $this->getResult()->setIndexedTagName( $data, 'magicword' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -361,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];
                        }
@@ -377,6 +381,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $this->getResult()->setIndexedTagName( $data, 'iw' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -386,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();
@@ -408,6 +416,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
                $result = $this->getResult();
                $result->setIndexedTagName( $data, 'db' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -448,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 );
@@ -474,6 +482,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $result->setIndexedTagName( $data, 'group' );
+
                return $result->addValue( 'query', $property, $data );
        }
 
@@ -485,6 +494,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = array( 'ext' => $ext );
                }
                $this->getResult()->setIndexedTagName( $data, 'fe' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -519,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 );
        }
 
@@ -564,6 +575,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = $lang;
                }
                $this->getResult()->setIndexedTagName( $data, 'lang' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -583,6 +595,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                        $data[] = $skin;
                }
                $this->getResult()->setIndexedTagName( $data, 'skin' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -591,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 );
        }
 
@@ -599,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 );
        }
 
@@ -613,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 );
        }
 
@@ -637,6 +654,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                }
 
                $this->getResult()->setIndexedTagName( $data, 'hook' );
+
                return $this->getResult()->addValue( 'query', $property, $data );
        }
 
@@ -685,6 +703,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
        public function getParamDescription() {
                $p = $this->getModulePrefix();
+
                return array(
                        'prop' => array(
                                'Which sysinfo properties to get:',
@@ -694,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',
@@ -713,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..f22140a 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;
@@ -312,7 +314,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..01e0f6e 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;
                }
 
@@ -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'] ) {
@@ -729,16 +753,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 +779,6 @@ class ApiUpload extends ApiBase {
                );
 
                return $params;
-
        }
 
        public function getResultProperties() {
@@ -837,7 +863,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..dcd8191 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,6 +150,7 @@ class BacklinkCache {
                if ( !isset( $this->db ) ) {
                        $this->db = wfGetDB( DB_SLAVE );
                }
+
                return $this->db;
        }
 
@@ -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,18 +196,32 @@ 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 ) {
                                // The full results fit within the limit, so cache them
@@ -214,6 +232,7 @@ class BacklinkCache {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $res;
        }
 
@@ -280,13 +299,13 @@ class BacklinkCache {
                        case 'imagelinks':
                                $conds = array(
                                        'il_to' => $this->title->getDBkey(),
-                                       'page_id=il_from'
+                                       "page_id={$prefix}_from"
                                );
                                break;
                        case 'categorylinks':
                                $conds = array(
                                        'cl_to' => $this->title->getDBkey(),
-                                       'page_id=cl_from',
+                                       "page_id={$prefix}_from"
                                );
                                break;
                        default:
@@ -316,11 +335,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 +358,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 +389,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 +400,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 +416,7 @@ class BacklinkCache {
                if ( is_array( $memcValue ) ) {
                        $cacheEntry = $memcValue;
                        wfDebug( __METHOD__ . ": got from memcached $memcKey\n" );
+
                        return $cacheEntry['batches'];
                }
 
@@ -396,7 +427,7 @@ 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'];
@@ -420,6 +451,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..d33f3f6 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() );
@@ -165,10 +170,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 +269,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 4147424..0000000
+++ /dev/null
@@ -1,71 +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
-        */
-       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..7bb41ac 100644 (file)
@@ -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..0d706c0 100644 (file)
@@ -51,6 +51,7 @@ class LinkCache {
                        return self::$instance;
                }
                self::$instance = new LinkCache;
+
                return self::$instance;
        }
 
@@ -122,21 +123,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 +222,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 +269,7 @@ class LinkCache {
                }
 
                wfProfileOut( __METHOD__ );
+
                return $id;
        }
 
index c5a153a..7d029bc 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
@@ -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;
@@ -1187,6 +1208,7 @@ class LCStore_CDB implements LCStore {
                        if ( $value === false ) {
                                return null;
                        }
+
                        return unserialize( $value );
                }
        }
@@ -1227,6 +1249,7 @@ class LCStore_CDB implements LCStore {
                if ( strval( $code ) === '' || strpos( $code, '/' ) !== false ) {
                        throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
                }
+
                return "{$this->directory}/l10n_cache-$code.cdb";
        }
 }
@@ -1234,38 +1257,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 +1329,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 +1342,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 );
        }
 
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..2e4c1e9 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?
index bf800c4..aa3519b 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 class ChangesList extends ContextSource {
-
        /**
         * @var Skin
         */
@@ -49,19 +48,6 @@ 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
@@ -75,6 +61,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;
@@ -118,6 +105,7 @@ class ChangesList extends ContextSource {
                                ? self::flag( $flag )
                                : $nothing;
                }
+
                return $f;
        }
 
@@ -153,8 +141,8 @@ 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>';
        }
 
@@ -169,6 +157,7 @@ class ChangesList extends ContextSource {
                $this->lastdate = '';
                $this->rclistOpen = false;
                $this->getOutput()->addModuleStyles( 'mediawiki.special.changeslist' );
+
                return '';
        }
 
@@ -326,7 +315,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 +357,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 +383,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 +403,7 @@ class ChangesList extends ContextSource {
                $formatter->setContext( $this->getContext() );
                $formatter->setShowUserToolLinks( true );
                $mark = $this->getLanguage()->getDirMark();
+
                return $formatter->getActionText() . " $mark" . $formatter->getComment();
        }
 
@@ -418,11 +415,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 '';
        }
 
@@ -448,8 +447,10 @@ class ChangesList extends ContextSource {
                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 '';
@@ -501,12 +502,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 +534,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 +547,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..4837525 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).
         *
@@ -56,13 +58,18 @@ class EnhancedChangesList extends ChangesList {
                wfProfileIn( __METHOD__ );
 
                # Create a specialised object
-               $rc = RCCacheEntry::newFromParent( $baseRC );
+               $cacheEntry = RCCacheEntry::newFromParent( $baseRC );
 
-               $curIdEq = array( 'curid' => $rc->mAttribs['rc_cur_id'] );
+               $curIdEq = array( 'curid' => $cacheEntry->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(
+                       $cacheEntry->mAttribs['rc_timestamp'],
+                       $this->getUser()
+               );
+
                $ret = '';
+
                if ( $date != $this->lastdate ) {
                        # Process current cache
                        $ret = $this->recentChangesBlock();
@@ -72,52 +79,56 @@ class EnhancedChangesList extends ChangesList {
                }
 
                # 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 {
@@ -443,11 +467,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 +479,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 +532,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 +543,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 +582,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 +610,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 +662,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 +690,4 @@ class EnhancedChangesList extends ChangesList {
        public function endRecentChangesList() {
                return $this->recentChangesBlock() . parent::endRecentChangesList();
        }
-
 }
index a7fe934..bcdb33e 100644 (file)
@@ -116,15 +116,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..3fa5c32 100644 (file)
@@ -30,6 +30,7 @@ class RCCacheEntry extends RecentChange {
                $rc2 = new RCCacheEntry;
                $rc2->mAttribs = $rc->mAttribs;
                $rc2->mExtra = $rc->mExtra;
+
                return $rc2;
        }
 }
index 282890f..a6920f6 100644 (file)
@@ -26,7 +26,6 @@
  * 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
@@ -101,6 +100,7 @@ class RecentChange {
        public static function newFromRow( $row ) {
                $rc = new RecentChange;
                $rc->loadFromRow( $row );
+
                return $rc;
        }
 
@@ -115,6 +115,7 @@ class RecentChange {
                $rc->loadFromCurRow( $row );
                $rc->notificationtimestamp = false;
                $rc->numberofWatchingusers = false;
+
                return $rc;
        }
 
@@ -155,7 +156,6 @@ class RecentChange {
                return array(
                        'rc_id',
                        'rc_timestamp',
-                       'rc_cur_time',
                        'rc_user',
                        'rc_user_text',
                        'rc_namespace',
@@ -205,6 +205,7 @@ class RecentChange {
                if ( $this->mTitle === false ) {
                        $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
                }
+
                return $this->mTitle;
        }
 
@@ -221,6 +222,7 @@ class RecentChange {
                                $this->mPerformer = User::newFromName( $this->mAttribs['rc_user_text'], false );
                        }
                }
+
                return $this->mPerformer;
        }
 
@@ -254,7 +256,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
@@ -383,6 +384,7 @@ class RecentChange {
         */
        public static function cleanupForIRC( $text ) {
                wfDeprecated( __METHOD__, '1.22' );
+
                return IRCColourfulRCFeedFormatter::cleanupForIRC( $text );
        }
 
@@ -403,13 +405,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()
@@ -430,7 +434,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 ) {
@@ -445,6 +451,7 @@ class RecentChange {
                // Log this patrol event
                PatrolLog::record( $this, $auto, $user );
                wfRunHooks( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
+
                return array();
        }
 
@@ -467,6 +474,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();
        }
 
@@ -494,40 +502,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_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_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;
        }
 
@@ -554,30 +562,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_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_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(
@@ -588,6 +595,7 @@ class RecentChange {
                        'pageStatus' => 'created'
                );
                $rc->save();
+
                return $rc;
        }
 
@@ -607,9 +615,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;
@@ -617,6 +626,7 @@ class RecentChange {
                $rc = self::newLogEntry( $timestamp, $title, $user, $actionComment, $ip, $type, $action,
                        $target, $logComment, $params, $newId, $actionCommentIRC );
                $rc->save();
+
                return true;
        }
 
@@ -664,39 +674,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_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_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;
        }
 
@@ -714,14 +724,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,
@@ -783,6 +792,7 @@ class RecentChange {
                } else {
                        $trail = '';
                }
+
                return $trail;
        }
 
@@ -803,6 +813,7 @@ class RecentChange {
                if ( $old === null || $new === null ) {
                        return '';
                }
+
                return ChangesList::showCharacterDifference( $old, $new );
        }
 
@@ -817,7 +828,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 );
@@ -833,7 +844,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();
@@ -841,6 +853,7 @@ class RecentChange {
                                $ip = '';
                        }
                }
+
                return $ip;
        }
 
@@ -855,6 +868,7 @@ class RecentChange {
         */
        public static function isInRCLifespan( $timestamp, $tolerance = 0 ) {
                global $wgRCMaxAge;
+
                return wfTimestamp( TS_UNIX, $timestamp ) > time() - $tolerance - $wgRCMaxAge;
        }
 }
index ef71b18..eb30a1d 100644 (file)
@@ -283,11 +283,39 @@ 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;
+       }
 }
 
 /**
  * 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,6 +326,7 @@ class RedisConnRef {
        protected $conn;
 
        protected $server; // string
+       protected $lastError; // string
 
        /**
         * @param $pool RedisConnectionPool
@@ -310,8 +339,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 +382,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,9 +405,11 @@ 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;
        }
 
index 2a92e23..ede4306 100644 (file)
@@ -350,10 +350,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 );
@@ -907,6 +909,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() );
index f66dacd..87ebc9f 100644 (file)
@@ -156,14 +156,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,7 +178,7 @@ 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 ) );
index 9ffe665..e2c59ed 100644 (file)
@@ -243,7 +243,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 +255,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 +288,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 +398,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;
        }
 
        /**
@@ -667,28 +693,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;
@@ -785,15 +820,16 @@ 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;
                }
@@ -1008,9 +1044,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 +1059,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" );
                        }
@@ -2040,6 +2079,29 @@ 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
         *
@@ -3186,6 +3248,66 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                }
        }
 
+       /**
+        * 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.
+        *
+        * 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.
+        *
+        * @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.
@@ -3197,12 +3319,19 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * 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 +3360,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();
        }
 
        /**
@@ -3257,6 +3390,11 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         *        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 +3414,6 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                if ( $this->mTrxDoneWrites ) {
                        Profiler::instance()->transactionWritingOut( $this->mServer, $this->mDBname );
                }
-               $this->mTrxDoneWrites = false;
                $this->runOnTransactionIdleCallbacks();
        }
 
@@ -3308,10 +3445,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 +3497,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.
index 956bb69..1314b12 100644 (file)
@@ -80,6 +80,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
         */
index 49579b6..5be460f 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();
@@ -113,9 +114,9 @@ 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 ) ) {
@@ -137,6 +138,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
@@ -996,6 +1005,55 @@ 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 ) );
+       }
+
 }
 
 
index 7761abe..5b2e11d 100644 (file)
@@ -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
         */
index fbaa4da..6b4113e 100644 (file)
@@ -196,12 +196,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 ) );
        }
 
@@ -1339,6 +1354,13 @@ 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';
        }
index e564a16..4688000 100644 (file)
@@ -370,7 +370,14 @@ 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 ) {
@@ -1424,6 +1431,13 @@ 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';
        }
index 4a51226..84f1bcf 100644 (file)
@@ -39,23 +39,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 );
+                               }
                        }
                }
        }
@@ -803,6 +810,9 @@ 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 +828,13 @@ 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
diff --git a/includes/deferred/CallableUpdate.php b/includes/deferred/CallableUpdate.php
new file mode 100644 (file)
index 0000000..6eb5541
--- /dev/null
@@ -0,0 +1,30 @@
+<?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/deferred/DataUpdate.php b/includes/deferred/DataUpdate.php
new file mode 100644 (file)
index 0000000..7b9ac28
--- /dev/null
@@ -0,0 +1,126 @@
+<?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..c385f13
--- /dev/null
@@ -0,0 +1,129 @@
+<?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 ) {
+                                       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..4147424
--- /dev/null
@@ -0,0 +1,71 @@
+<?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
+        */
+       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..fdd0e3c
--- /dev/null
@@ -0,0 +1,892 @@
+<?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/deferred/SearchUpdate.php b/includes/deferred/SearchUpdate.php
new file mode 100644 (file)
index 0000000..82a413e
--- /dev/null
@@ -0,0 +1,185 @@
+<?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;
+       }
+}
diff --git a/includes/deferred/SiteStatsUpdate.php b/includes/deferred/SiteStatsUpdate.php
new file mode 100644 (file)
index 0000000..09ff87d
--- /dev/null
@@ -0,0 +1,245 @@
+<?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 {
+       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 );
+                       }
+               }
+       }
+}
+
diff --git a/includes/deferred/SqlDataUpdate.php b/includes/deferred/SqlDataUpdate.php
new file mode 100644 (file)
index 0000000..51188d8
--- /dev/null
@@ -0,0 +1,152 @@
+<?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__
+               );
+       }
+
+}
diff --git a/includes/deferred/SquidUpdate.php b/includes/deferred/SquidUpdate.php
new file mode 100644 (file)
index 0000000..71afeba
--- /dev/null
@@ -0,0 +1,300 @@
+<?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;
+       }
+}
diff --git a/includes/deferred/ViewCountUpdate.php b/includes/deferred/ViewCountUpdate.php
new file mode 100644 (file)
index 0000000..22a4649
--- /dev/null
@@ -0,0 +1,105 @@
+<?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' );
+       }
+}
diff --git a/includes/diff/ArrayDiffFormatter.php b/includes/diff/ArrayDiffFormatter.php
new file mode 100644 (file)
index 0000000..7da6905
--- /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..53e80c4 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 );
-       }
+       public abstract function reverse();
 
        /**
         * @return int
@@ -59,8 +57,8 @@ class _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp_Copy extends _DiffOp {
-       var $type = 'copy';
+class DiffOp_Copy 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 DiffOp_Copy
         */
        function reverse() {
-               return new _DiffOp_Copy( $this->closing, $this->orig );
+               return new DiffOp_Copy( $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 DiffOp_Delete extends DiffOp {
+       public $type = 'delete';
 
        function __construct( $lines ) {
                $this->orig = $lines;
@@ -92,10 +90,10 @@ class _DiffOp_Delete extends _DiffOp {
        }
 
        /**
-        * @return _DiffOp_Add
+        * @return DiffOp_Add
         */
        function reverse() {
-               return new _DiffOp_Add( $this->orig );
+               return new DiffOp_Add( $this->orig );
        }
 }
 
@@ -104,8 +102,8 @@ class _DiffOp_Delete extends _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp_Add extends _DiffOp {
-       var $type = 'add';
+class DiffOp_Add extends DiffOp {
+       public $type = 'add';
 
        function __construct( $lines ) {
                $this->closing = $lines;
@@ -113,10 +111,10 @@ class _DiffOp_Add extends _DiffOp {
        }
 
        /**
-        * @return _DiffOp_Delete
+        * @return DiffOp_Delete
         */
        function reverse() {
-               return new _DiffOp_Delete( $this->closing );
+               return new DiffOp_Delete( $this->closing );
        }
 }
 
@@ -125,8 +123,8 @@ class _DiffOp_Add extends _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffOp_Change extends _DiffOp {
-       var $type = 'change';
+class DiffOp_Change 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 DiffOp_Change
         */
        function reverse() {
-               return new _DiffOp_Change( $this->closing, $this->orig );
+               return new DiffOp_Change( $this->closing, $this->orig );
        }
 }
 
@@ -165,7 +163,7 @@ class _DiffOp_Change extends _DiffOp {
  * @private
  * @ingroup DifferenceEngine
  */
-class _DiffEngine {
+class DiffEngine {
 
        const MAX_XREF_LENGTH = 10000;
 
@@ -187,11 +185,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 );
@@ -211,7 +209,7 @@ class _DiffEngine {
                                ++$yi;
                        }
                        if ( $copy ) {
-                               $edits[] = new _DiffOp_Copy( $copy );
+                               $edits[] = new DiffOp_Copy( $copy );
                        }
 
                        // Find deletes & adds.
@@ -226,11 +224,11 @@ class _DiffEngine {
                        }
 
                        if ( $delete && $add ) {
-                               $edits[] = new _DiffOp_Change( $delete, $add );
+                               $edits[] = new DiffOp_Change( $delete, $add );
                        } elseif ( $delete ) {
-                               $edits[] = new _DiffOp_Delete( $delete );
+                               $edits[] = new DiffOp_Delete( $delete );
                        } elseif ( $add ) {
-                               $edits[] = new _DiffOp_Add( $add );
+                               $edits[] = new DiffOp_Add( $add );
                        }
                }
                wfProfileOut( __METHOD__ );
@@ -241,7 +239,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 +280,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 +302,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 +312,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 +343,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 ) {
@@ -389,7 +387,7 @@ class _DiffEngine {
                                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];
                                                break;
@@ -404,7 +402,7 @@ 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];
                                        }
@@ -428,7 +426,7 @@ 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;
@@ -470,7 +468,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;
@@ -491,7 +489,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 +506,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 +525,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;
@@ -654,7 +652,7 @@ class _DiffEngine {
  * @ingroup DifferenceEngine
  */
 class Diff {
-       var $edits;
+       public $edits;
 
        /**
         * Constructor.
@@ -665,9 +663,9 @@ class Diff {
         * @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);
+               // $this->check($from_lines, $to_lines);
        }
 
        /**
@@ -683,6 +681,7 @@ class Diff {
        function reverse() {
                $rev = $this;
                $rev->edits = array();
+               /** @var DiffOp $edit */
                foreach ( $this->edits as $edit ) {
                        $rev->edits[] = $edit->reverse();
                }
@@ -765,7 +764,7 @@ class Diff {
         * @param $from_lines
         * @param $to_lines
         */
-       function _check( $from_lines, $to_lines ) {
+       private 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 );
@@ -852,363 +851,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 HWLDF_WordAccumulator {
+       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 +914,20 @@ 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,8 +946,8 @@ 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 );
@@ -1261,7 +958,7 @@ class WordLevelDiff extends MappedDiff {
         * @param $lines
         * @return array
         */
-       function _split( $lines ) {
+       private function split( $lines ) {
                wfProfileIn( __METHOD__ );
 
                $words = array();
@@ -1300,9 +997,9 @@ class WordLevelDiff extends MappedDiff {
        /**
         * @return array
         */
-       function orig() {
+       public function orig() {
                wfProfileIn( __METHOD__ );
-               $orig = new _HWLDF_WordAccumulator;
+               $orig = new HWLDF_WordAccumulator;
 
                foreach ( $this->edits as $edit ) {
                        if ( $edit->type == 'copy' ) {
@@ -1319,9 +1016,9 @@ class WordLevelDiff extends MappedDiff {
        /**
         * @return array
         */
-       function closing() {
+       public function closing() {
                wfProfileIn( __METHOD__ );
-               $closing = new _HWLDF_WordAccumulator;
+               $closing = new HWLDF_WordAccumulator;
 
                foreach ( $this->edits as $edit ) {
                        if ( $edit->type == 'copy' ) {
@@ -1335,161 +1032,3 @@ class WordLevelDiff extends MappedDiff {
                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__ );
-       }
-}
diff --git a/includes/diff/DiffFormatter.php b/includes/diff/DiffFormatter.php
new file mode 100644 (file)
index 0000000..78ac77f
--- /dev/null
@@ -0,0 +1,225 @@
+<?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 {
+       /**
+        * 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;
+
+       /**
+        * 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();
+
+               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->endDiff();
+               wfProfileOut( __METHOD__ );
+               return $end;
+       }
+
+       /**
+        * @param $xbeg
+        * @param $xlen
+        * @param $ybeg
+        * @param $ylen
+        * @param $edits
+        */
+       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 39f8a47..cf78ce0 100644 (file)
@@ -83,7 +83,7 @@ class DifferenceEngine extends ContextSource {
         * 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|int either 'prev' or 'next'. Default: 0.
+        * @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
@@ -230,7 +230,6 @@ class DifferenceEngine extends ContextSource {
                }
 
                $rollback = '';
-               $undoLink = '';
 
                $query = array();
                # Carry over 'diffonly' param via navigation links
@@ -599,7 +598,8 @@ class DifferenceEngine extends ContextSource {
         *
         * @param string|bool $otitle Header for old text or false
         * @param string|bool $ntitle Header for new text or false
-        * @param string $notice
+        * @param string $notice HTML between diff header and body
+        *
         * @return bool
         */
        function showDiff( $otitle, $ntitle, $notice = '' ) {
@@ -867,6 +867,9 @@ class DifferenceEngine extends ContextSource {
        /**
         * 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" ) {
@@ -879,16 +882,20 @@ class DifferenceEngine extends ContextSource {
                        $data[] = wfHostname();
                }
                $data[] = wfTimestamp( TS_DB );
-               return "<!-- diff generator: " .
-               implode( " ",
-               array_map(
+               return "<!-- diff generator: "
+                       . implode( " ",
+                               array_map(
                                        "htmlspecialchars",
-               $data ) ) .
-                       " -->\n";
+                               $data )
+                       )
+                       . " -->\n";
        }
 
        /**
         * Replace line numbers with the text in the user's language
+        *
+        * @param String $text
+        *
         * @return mixed
         */
        function localiseLineNumbers( $text ) {
@@ -1008,6 +1015,12 @@ 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 = '' ) {
diff --git a/includes/diff/TableDiffFormatter.php b/includes/diff/TableDiffFormatter.php
new file mode 100644 (file)
index 0000000..0ce17df
--- /dev/null
@@ -0,0 +1,183 @@
+<?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..d489538
--- /dev/null
@@ -0,0 +1,68 @@
+<?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 {
+       protected $leadingContextLines = 2;
+       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 29089c9..eaa653d 100644 (file)
@@ -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"
 
        /**
@@ -606,11 +606,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 );
@@ -673,11 +671,9 @@ 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;
        }
@@ -782,11 +778,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
index fe83308..3c5b7b2 100644 (file)
@@ -63,45 +63,28 @@ abstract class FileOp {
         */
        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 );
                }
        }
 
+
        /**
         * Normalize a string if it is a valid storage path
         *
@@ -308,10 +291,10 @@ abstract class FileOp {
        /**
         * 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() );
        }
 
        /**
@@ -459,8 +442,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 ) {
@@ -511,8 +497,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 ) {
@@ -573,8 +562,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 ) {
@@ -639,8 +631,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 ) {
@@ -715,7 +710,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 ) {
@@ -760,7 +755,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 ) {
index db090a9..1787d66 100644 (file)
@@ -759,8 +759,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 +774,21 @@ 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
         *
@@ -916,10 +931,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 string|null $after Resolved container relative path to list items after
         * @param integer $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 +1006,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 string|null $after Resolved container relative path of file to list items after
         * @param integer $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 +1022,33 @@ class SwiftFileBackend extends FileBackendStore {
                try {
                        $container = $this->getContainer( $fullCont );
                        $prefix = ( $dir == '' ) ? null : "{$dir}/";
+                       $objects = array(); // 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 +1061,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
+        * @return void
+        */
+       public function loadListingStatInternal( $path, array $val ) {
+               $this->cheapCache->set( $path, 'stat', $val );
        }
 
        protected function doGetFileSha1base36( array $params ) {
@@ -1556,7 +1574,7 @@ 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
@@ -1684,7 +1702,13 @@ 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;
        }
 
        /**
old mode 100755 (executable)
new mode 100644 (file)
index 07cc03b..e64c88a
@@ -177,7 +177,7 @@ class ForeignAPIRepo extends FileRepo {
         * @return string
         */
        function fetchImageQuery( $query ) {
-               global $wgMemc, $wgLanguageCode;
+               global $wgLanguageCode;
 
                $query = array_merge( $query,
                        array(
old mode 100755 (executable)
new mode 100644 (file)
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 e56c7a9..41cbf50 100644 (file)
@@ -77,7 +77,7 @@ abstract class DatabaseUpdater {
        /**
         * File handle for SQL output.
         *
-        * @var Filehandle
+        * @var resource
         */
        protected $fileHandle = null;
 
@@ -96,9 +96,9 @@ abstract class DatabaseUpdater {
        /**
         * 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;
@@ -204,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.
@@ -388,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;
@@ -423,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 ) {
@@ -450,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 );
@@ -470,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 ) {
@@ -489,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 );
@@ -519,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 ) {
@@ -584,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();
 
@@ -605,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 ) {
@@ -624,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 ) {
@@ -656,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 ) ) {
@@ -679,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 ) ) {
@@ -704,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 ) ) {
@@ -729,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 ) ) {
@@ -752,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 ) ) {
@@ -778,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
@@ -830,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 ) ) {
@@ -860,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 ) ) {
index 2f45005..e6b0fd3 100644 (file)
@@ -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 ) {
index fb675d7..0f4faec 100644 (file)
@@ -250,9 +250,10 @@ 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 ) ) {
@@ -270,10 +271,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 ) ) {
@@ -698,7 +699,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 32e7510..cea4d78 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' ),
index e23edf5..b37e6b3 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;
@@ -336,7 +336,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 +396,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 +429,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 +447,7 @@ class WebInstaller extends Installer {
        /**
         * Get a WebInstallerPage by name.
         *
-        * @param $pageName String
+        * @param string $pageName
         * @return WebInstallerPage
         */
        public function getPageByName( $pageName ) {
@@ -454,7 +459,7 @@ class WebInstaller extends Installer {
        /**
         * Get a session variable.
         *
-        * @param $name String
+        * @param string $name
         * @param $default
         * @return null
         */
@@ -468,8 +473,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 +528,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 +568,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 +635,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 +646,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 +657,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 +696,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 +708,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 +720,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 +736,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 +769,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 +816,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 +865,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 +894,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 +945,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 +1011,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 +1032,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 +1097,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 f2dc37f..6178e5b 100644 (file)
@@ -294,9 +294,8 @@ class WebInstallerOutput {
 
        public function outputFooter() {
                if ( $this->useShortHeader ) {
-?>
-</body></html>
-<?php
+                       echo Html::closeElement( 'body' ) . Html::closeElement( 'html' );
+
                        return;
                }
 ?>
@@ -317,9 +316,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 d3ce164..36f4959 100644 (file)
@@ -56,6 +56,8 @@ class JobQueueFederated extends JobQueue {
        /** @var BagOStuff */
        protected $cache;
 
+       protected $maxPartitionsTry;  // integer; maximum number of partitions to try
+
        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,6 +74,10 @@ 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
         */
        protected function __construct( array $params ) {
@@ -82,6 +88,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 +103,10 @@ class JobQueueFederated extends JobQueue {
                }
                // Get the config to pass to merge into each partition queue config
                $baseConfig = $params;
-               foreach ( array( 'class', 'sectionsByWiki',
+               foreach ( array( 'class', 'sectionsByWiki', 'maxPartitionsTry',
                        'partitionsBySection', 'configByPartition', 'partitionsNoPush' ) as $o )
                {
-                       unset( $baseConfig[$o] );
+                       unset( $baseConfig[$o] ); // partition queue doesn't care about this
                }
                // Get the partition queue objects
                foreach ( $this->partitionMap as $partition => $w ) {
@@ -194,16 +203,17 @@ class JobQueueFederated extends JobQueue {
        }
 
        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;
        }
index 378e175..67bb5a4 100644 (file)
@@ -70,7 +70,7 @@ class JobQueueRedis extends JobQueue {
        /**
         * @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.
index c6a799d..f1922a3 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 ) {
@@ -63,9 +67,6 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                }
        }
 
-       /**
-        * @see JobQueueAggregator::doNotifyQueueNonEmpty()
-        */
        protected function doNotifyQueueNonEmpty( $wiki, $type ) {
                $conn = $this->getConnection();
                if ( !$conn ) {
@@ -80,9 +81,6 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                }
        }
 
-       /**
-        * @see JobQueueAggregator::doAllGetReadyWikiQueues()
-        */
        protected function doGetAllReadyWikiQueues() {
                $conn = $this->getConnection();
                if ( !$conn ) {
@@ -130,9 +128,6 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
                }
        }
 
-       /**
-        * @see JobQueueAggregator::doPurge()
-        */
        protected function doPurge() {
                $conn = $this->getConnection();
                if ( !$conn ) {
@@ -150,11 +145,18 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
        /**
         * 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 +165,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 );
        }
 
        /**
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 b2a8e50..a1cb3a7 100644 (file)
@@ -498,16 +498,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 +520,7 @@ class ManualLogEntry extends LogEntryBase {
                                $ip = $user->getName();
                        }
                }
-               $rc = RecentChange::newLogEntry(
+               return RecentChange::newLogEntry(
                        $this->getTimestamp(),
                        $logpage,
                        $user,
@@ -539,6 +535,21 @@ class ManualLogEntry extends LogEntryBase {
                        $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' );
                }
index e2444a1..43ba117 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;
old mode 100755 (executable)
new mode 100644 (file)
index b34ad65..91c4c9a
@@ -1563,11 +1563,13 @@ class FormatMetadata extends ContextSource {
 
                $common = $file->getCommonMetaArray();
 
-               foreach ( $common as $key => $value ) {
-                       $fileMetadata[$key] = array(
-                               'value' => $value,
-                               'source' => 'file-metadata',
-                       );
+               if ( $common !== false ) {
+                       foreach ( $common as $key => $value ) {
+                               $fileMetadata[$key] = array(
+                                       'value' => $value,
+                                       'source' => 'file-metadata',
+                               );
+                       }
                }
 
                wfProfileOut( __METHOD__ );
old mode 100755 (executable)
new mode 100644 (file)
index 8190a8a..a4203b0 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.
index 4b6eeca..44c7458 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 );
@@ -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 6e9e06e..2df3160 100644 (file)
@@ -541,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" ) )
@@ -5762,8 +5762,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..e12f32d 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 ) ) {
index 0a1f3b1..418ab12 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 6380efc..91acd11 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();
@@ -451,7 +452,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 +528,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 +705,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 +738,11 @@ class ResourceLoader {
                        $blobs = array();
                }
 
+
+               foreach ( $missing as $name ) {
+                       $states[$name] = 'missing';
+               }
+
                // Generate output
                $isRaw = false;
                foreach ( $modules as $name => $module ) {
@@ -838,8 +847,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 +857,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 );
                        }
                }
 
index 9ed181e..7b85001 100644 (file)
@@ -745,6 +745,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
         */
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..d02886f 100644 (file)
@@ -75,7 +75,7 @@ class SpecialChangeEmail extends UnlistedSpecialPage {
                $user = $this->getUser();
                $request = $this->getRequest();
 
-               if ( !$request->wasPosted() && !$user->isLoggedIn() ) {
+               if ( !$user->isLoggedIn() ) {
                        $this->error( 'changeemail-no-info' );
 
                        return;
index 3828b1c..6757990 100644 (file)
@@ -90,19 +90,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 501552e..ca2daaf 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;
@@ -95,10 +96,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 +635,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;
index 5b0c56e..ed6e2a4 100644 (file)
@@ -73,14 +73,17 @@ class LinkSearchPage extends QueryPage {
                        // For protocols without '//' like 'mailto:'
                        $protocol = substr( $target2, 0, $pr_cl + 1 );
                        $target2 = substr( $target2, $pr_cl + 1 );
-               } elseif ( $protocol == '' && $target2 != '' ) {
+               } elseif ( $target2 != '' ) {
                        // default
                        $protocol = 'http://';
                }
                if ( $protocol != '' && !in_array( $protocol, $protocols_list ) ) {
-                       // unsupported protocol, show original search request
+                       // Unsupported protocol, show original search request
                        $target2 = $target;
-                       $protocol = '';
+                       // Since links with unsupported protocols don't end up in
+                       // externallinks, assume $protocol is actually part of a link
+                       // containing ':' or '//' and default to http as above.
+                       $protocol = 'http://';
                }
 
                $out->addWikiMsg(
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 51e7450..23203ea 100644 (file)
@@ -685,7 +685,6 @@ class SpecialRecentChanges extends IncludableSpecialPage {
        /**
         * Creates the choose namespace selection
         *
-        * @todo Uses radio buttons (HASHAR)
         * @param FormOptions $opts
         * @return string
         */
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..dd32656 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!
@@ -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
@@ -738,7 +739,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 +1095,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 09facf4..0700c49 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
         */
@@ -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 5ac3e65..9764c9f 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,7 +219,7 @@ class LoginForm extends SpecialPage {
                        return;
                }
 
-               $status = $this->addNewaccountInternal();
+               $status = $this->addNewAccountInternal();
                if ( !$status->isGood() ) {
                        $error = $status->getMessage();
                        $this->mainLoginForm( $error->toString() );
@@ -865,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() );
@@ -882,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 );
 
@@ -1196,7 +1200,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..62c33a2 100644 (file)
@@ -60,32 +60,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;
                }
@@ -211,10 +211,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',
index 2260241..b162de2 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' );
        }
 
        /**
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..0995aed
--- /dev/null
@@ -0,0 +1,160 @@
+<?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
+ */
+class CdbException extends MWException {}
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 dc87bc8..2038bac 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; }
@@ -3324,11 +3325,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;
                        }
                }
@@ -3811,6 +3814,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 );
@@ -4478,7 +4482,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..d4c38af 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
@@ -1103,6 +1103,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
index 3848a0b..0bf96d4 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
        '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
        '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 0d2ec3d..e62d025 100644 (file)
@@ -13,6 +13,8 @@
  * @author Ezagren
  * @author Fadli Idris
  * @author Meno25
+ * @author Rachmat.Wahidi
+ * @author Sayed Muddasir
  * @author Si Gam Acèh
  */
 
@@ -158,67 +160,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 +234,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 +246,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 +258,7 @@ $messages = array(
 'feb' => 'Duwa',
 'mar' => 'Lhèë',
 'apr' => 'Peuët',
-'may' => 'Limong',
+'may' => 'Limöng',
 'jun' => 'Nam',
 'jul' => 'Tujôh',
 'aug' => 'Lapan',
@@ -278,7 +280,7 @@ $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"',
@@ -286,15 +288,15 @@ $messages = array(
 '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 +304,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 +346,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' => 'Seuneumat 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',
+'views' => 'Seuneudeuih',
 'toolbox' => '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',
+'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',
+'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' => 'navigasi',
+'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,11 +423,11 @@ $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"',
@@ -435,7 +437,7 @@ $1",
 '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 +453,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 +477,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 +537,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 +588,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 +744,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:'''",
+'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 +898,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 +929,181 @@ 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:',
+'prefsnologin' => 'Hana tamöng lom',
+'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-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|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' => 'Seutot neuubah 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 neuubah yôh <strong>$2</strong> (geupeudeuh trôh ‘an <strong>$1</strong> neuubah).',
-'rclistfrom' => 'Peuleumah neuubah paléng barô yôh $1 kön',
+'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 +1111,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 +1217,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 +1232,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 +1240,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 +1279,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',
@@ -966,13 +1380,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 +1407,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,13 +1434,13 @@ 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' => 'Peudeuh beuneuri atra ureuëng ban dapeuta mantöng',
 'sp-contributions-newbies-sub' => 'Keu ureuëng nguy barô',
@@ -1033,36 +1449,36 @@ Droëneuh jeuët neugantoë tingkat lindông keu ôn nyoë, tapi nyan hana peung
 '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]]''':",
+'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' => 'ôn peupinah',
+'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 seuneumat 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 +1497,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 +1512,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 +1527,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 neupubuët, pat keu mita 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 meuhubông keunoë',
-'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 keu 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' => 'Seuneumat 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,13 +1631,40 @@ 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' => "Peudeuh neuubah meukaw'èt",
 'watchlisttools-edit' => 'Peudeuh ngön andam dapeuta keunalön',
@@ -1233,21 +1680,53 @@ 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..ef541ee 100644 (file)
@@ -1324,7 +1324,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 271ba5c..c90bd21 100644 (file)
@@ -2876,7 +2876,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 +3042,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 */',
@@ -3635,7 +3636,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',
@@ -3822,7 +3823,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]].',
index 332eda3..5b4e097 100644 (file)
@@ -1558,7 +1558,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..e6af0f5 100644 (file)
@@ -1945,7 +1945,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 +2397,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' => 'ሁሉ',
index 71ddec7..1e232c6 100644 (file)
@@ -2515,7 +2515,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:',
@@ -3223,7 +3223,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',
@@ -3400,7 +3400,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. 
 
index 322dd28..996b3c3 100644 (file)
@@ -12,6 +12,7 @@
  * @author Gott wisst
  * @author JJohnson
  * @author Omnipaedista
+ * @author Shirayuki
  * @author Spacebirdy
  * @author Tsepelcory
  * @author Wōdenhelm
@@ -907,7 +908,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 +1218,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 6679715..d4c86ac 100644 (file)
@@ -936,7 +936,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|استخدم|استخدمي}} النموذج بالأسفل لتسجيل الدخول بحساب آخر.',
@@ -1013,7 +1013,7 @@ $2',
 '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' => 'أكد عنوان بريدك الإلكتروني',
@@ -1464,8 +1464,8 @@ $2
 'revdelete-hide-user' => 'أخف اسم/آيبي المستخدم',
 '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' => 'السبب:',
@@ -3193,7 +3193,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' => 'رشح حسب حالة التخصيص:',
@@ -4010,7 +4010,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' => 'الكل',
@@ -4289,7 +4289,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|ميدياويكي]].',
index 51884d4..4d58115 100644 (file)
@@ -903,7 +903,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 3c31b1f..9f237a4 100644 (file)
@@ -2457,7 +2457,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 a7d03e9..41042ec 100644 (file)
@@ -2558,7 +2558,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' => 'فلتره بحالة التهيئه:',
@@ -3107,7 +3107,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 b56ee1a..338243b 100644 (file)
@@ -2834,7 +2834,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' => 'স্বনিৰ্বাচন অৱস্থাৰে পৰিস্ৰাৱন কৰক:',
@@ -3588,7 +3588,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' => 'সকলো',
@@ -3777,7 +3777,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 -ৰ চুক্তিসমূহৰ অন্তৰ্গত ইয়াক পুনৰ বিতৰণ কৰিব পাৰিব অথবা সলনি কৰিব পাৰিব; হয়তো অনুজ্ঞাপত্ৰৰ সংস্কৰণ ২ 
index 671c716..a5e2251 100644 (file)
@@ -522,7 +522,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}}.
@@ -602,8 +602,8 @@ Pa evitar abusos, namái s'unviará un corréu de reaniciu cada {{PLURAL:$1|hora
 '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',
@@ -1048,18 +1048,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:',
@@ -2769,7 +2769,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:',
@@ -2996,6 +2996,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',
@@ -3080,7 +3081,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',
@@ -3552,7 +3553,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',
@@ -3652,6 +3653,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 →',
@@ -3739,7 +3743,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]].',
@@ -3758,7 +3762,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:',
index 3259115..aeb394a 100644 (file)
@@ -1810,7 +1810,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 +2192,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 a39894c..444b0d0 100644 (file)
@@ -809,8 +809,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:',
@@ -2117,7 +2117,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ı',
@@ -2736,7 +2736,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ı',
@@ -2836,7 +2836,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',
index e9423fb..b5b0aa1 100644 (file)
@@ -2692,7 +2692,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 +3442,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 +3625,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 گنل عمومی لیسانسی اساسی‌له یئنی‌دن داغیدیب یوخسا دَییشه بیلرسینیز؛ یا لیسانسین ۲-نجی نوسخه‌سی، یا دا (اؤز سئچدیگینیزله) هر هانکی سونراکی نوسخه‌سی.
index 61c065a..3fd762c 100644 (file)
@@ -2820,7 +2820,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' => 'Үҙгәртеү торошо буйынса һайлау:',
@@ -3580,7 +3580,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' => 'бөтә',
@@ -3765,7 +3765,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]] үҫешенә өлөш индергәндәре өсөн киләһе ҡатнашыусыларға рәхмәт әйтәбеҙ.',
index 1277b9a..b19c37c 100644 (file)
@@ -1425,7 +1425,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 +1567,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 +1653,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
index 22094fb..0aa48cb 100644 (file)
@@ -2209,7 +2209,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' => 'فیلتر گون حالت دلواهی',
@@ -2789,7 +2789,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' => 'کل',
index cfca8e6..58dda28 100644 (file)
@@ -555,7 +555,7 @@ 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}}.
@@ -630,9 +630,9 @@ Tangarig malikayan an abuso, saro sanang e-surat sa pagliliwat kan sekretong pan
 '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.
@@ -1060,20 +1060,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:',
@@ -2766,7 +2766,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:',
@@ -2933,6 +2933,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 */',
@@ -2981,6 +2982,7 @@ Giboha na '''DAE''' paglaogan digde!",
 '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',
@@ -3533,7 +3535,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',
@@ -3717,7 +3719,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]].',
index 85dab07..e53174b 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' => 'Варыянты',
@@ -417,7 +418,7 @@ $1',
 # General errors
 'error' => 'Памылка',
 'databaseerror' => 'Памылка базы дадзеных',
-'laggedslavemode' => 'Увага: Старонка можа не ўтрымліваць апошніх зменаў.',
+'laggedslavemode' => 'Увага: Старонка можа не ўтрымліваць апошніх змен.',
 'readonly' => 'База звестак заблакаваная',
 'enterlockreason' => 'Упішыце прычыну зачынення, а таксама меркаваны час адчынення',
 'readonlytext' => 'База даных не прыймае новых старонак і іншых змяненняў, таму што яна зараз зачынена, відаць, дзеля абслугоўвання, пасля чаго будзе вернута да нармальнай працы.
@@ -456,12 +457,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 +471,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 +488,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 +735,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 +769,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 +894,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 +1049,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 +1094,11 @@ $1",
 'searchdisabled' => 'Функцыя пошуку {{SITENAME}} не працуе. Тымчасова можна шукаць з дапамогай Google. Заўважце, што тамтэйшыя індэксы зместу {{SITENAME}} могуць не быць актуальнымі.',
 
 # Preferences page
-'preferences' => 'Настаўленні',
-'mypreferences' => 'Настáўленні',
+'preferences' => 'Настройкі',
+'mypreferences' => 'Настройкі',
 'prefs-edits' => 'Колькасць правак:',
 'prefsnologin' => 'Не ўвайшлі',
-'prefsnologintext' => 'Ð\9dалежÑ\8bÑ\86Ñ\8c <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} Ñ\83вайÑ\81Ñ\86Ñ\96 Ñ\9e Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83]</span>, ÐºÐ°Ð± Ð¼Ñ\8fнÑ\8fÑ\86Ñ\8c Ñ\81вае Ð½Ð°Ñ\81Ñ\82аÑ\9eленні.',
+'prefsnologintext' => 'Ð\9dеабÑ\85одна <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} Ñ\83вайÑ\81Ñ\86Ñ\96 Ñ\9e Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83]</span>, ÐºÐ°Ð± Ð¼Ñ\8fнÑ\8fÑ\86Ñ\8c Ñ\81вае Ð½Ð°Ñ\81Ñ\82Ñ\80ойкі.',
 'changepassword' => 'Пароль',
 'prefs-skin' => 'Вокладка',
 'skin-preview' => 'перадпаказ',
@@ -1107,7 +1108,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 +1134,7 @@ $1",
 'recentchangesdays-max' => '(найбольш $1 {{PLURAL:$1|дзень|дзён}})',
 'recentchangescount' => 'Прадвызначаная колькасць правак дзеля паказу:',
 'prefs-help-recentchangescount' => 'Гэта ўключае ў сябе апошнія змены, гісторыі старонак, журналы.',
-'savedprefs' => 'Настáўленні замацаваныя.',
+'savedprefs' => 'Настройкі замацаваныя.',
 'timezonelegend' => 'Часавы пояс:',
 'localtime' => 'Мясцовы час:',
 'timezoneuseserverdefault' => 'Карыстацца настаўленнямі серверу ($1)',
@@ -1160,7 +1161,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 +1175,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 +1192,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 +1359,7 @@ $1",
 'action-sendemail' => 'адпраўка электронных пісем',
 
 # Recent changes
-'nchanges' => '$1 {{PLURAL:$1|змена|змены|зменаў}}',
+'nchanges' => '$1 {{PLURAL:$1|змена|змены|змен}}',
 'recentchanges' => 'Апошнія змены',
 'recentchanges-legend' => 'Магчымасці паказу',
 'recentchanges-summary' => 'Гэта апошнія мены на пляцоўцы {{SITENAME}}.',
@@ -1376,7 +1377,7 @@ $1",
 'rcshowhideanons' => '$1 ананімных удзельнікаў',
 'rcshowhidepatr' => '$1 ухваленых правак',
 'rcshowhidemine' => '$1 ўласных правак',
-'rclinks' => 'Паказаць апошнія $1 зменаў за мінулыя $2 дзён<br />$3',
+'rclinks' => 'Паказаць апошнія $1 змен за мінулыя $2 дзён<br />$3',
 'diff' => 'розн.',
 'hist' => 'гіст.',
 'hide' => 'без уліку',
@@ -1962,19 +1963,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 +1987,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 +2093,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 +2106,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 +2212,7 @@ $1',
 'contributions-title' => 'Уклад удзельніка $1',
 'mycontris' => 'Уклад',
 'contribsub2' => 'Для $1 ($2)',
-'nocontribs' => 'Не знойдзена зменаў, адпаведных зададзеным параметрам.',
+'nocontribs' => 'Не знойдзена змен, адпаведных зададзеным параметрам.',
 'uctop' => '(апошн.)',
 'month' => 'Ад месяцу (і раней):',
 'year' => 'Ад году (і раней):',
@@ -2286,7 +2287,7 @@ $1',
 'ipbhidename' => 'Не паказваць імя ўдзельніка ў гісторыях правак і ў спісах',
 'ipbwatchuser' => 'Назіраць уласную і размоўную старонкі гэтага ўдзельніка',
 'ipb-disableusertalk' => 'Забараніць гэтаму ўдзельніку рэдагаваць сваю старонку размоў падчас блакіроўкі',
-'ipb-change-block' => 'Змяніць настаўленні блакавання ўдзельніка',
+'ipb-change-block' => 'Змяніць настройкі блакіравання ўдзельніка',
 'ipb-confirm' => 'Пацвердзіць блакіроўку',
 'badipaddress' => 'Недапушчальны адрас IP',
 'blockipsuccesssub' => 'Паспяховае блакаванне',
@@ -2327,7 +2328,7 @@ $1',
 'noautoblockblock' => 'аўтаблок не дазволены',
 'createaccountblock' => 'стварэнне рахунку заблакавана',
 'emailblock' => 'эл.пошта заблакавана',
-'blocklist-nousertalk' => 'не мае дазволу правіць уласную старонку размоваў',
+'blocklist-nousertalk' => 'не мае дазволу правіць уласную старонку размоў',
 'ipblocklist-empty' => 'Спіс блокаў зараз пусты.',
 'ipblocklist-no-results' => 'Няма блокаў на такі адрас IP або на такое імя ўдзельніка.',
 'blocklink' => 'заблакаваць',
@@ -2341,7 +2342,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 +2357,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 +2378,9 @@ $1',
 # Developer tools
 'lockdb' => 'Замкнуць базу дадзеных',
 'unlockdb' => 'Адмыкнуць базу дадзеных',
-'lockdbtext' => 'Зачыненне базы даных прыпыніць для ўсіх удзельнікаў магчымасць правіць старонкі, настаўленні, спісы назіранага, і, наогул, рабіць усё, дзеля чаго патрабуецца доступ да базы даных.
-Калі ласка, пацвердзіце свой намер зрабіць менавіта гэта, і што вы адчыніце базу даных па сканчэнні абслугоўвання.',
-'unlockdbtext' => 'Адчыненне базы даных верне ўсім удзельнікам магчымасць правіць старонкі, настаўленні, спісы назіранага, і, наогул, рабіць усё, дзеля чаго патрабуецца доступ да базы даных.
+'lockdbtext' => 'Зачыненне базы даных прыпыніць для ўсіх удзельнікаў магчымасць правіць старонкі, настройкі, спісы назірання, а таксама ажыццяўляць іншыя дзеянні, для якіх патрэбен доступ да базы даных.
+Калі ласка, пацвердзіце свой намер зрабіць менавіта гэта, і што вы адчыніце базу даных па заканчэнні абслугоўвання.',
+'unlockdbtext' => 'Адчыненне базы даных верне ўсім удзельнікам магчымасць правіць старонкі, настройкі, спісы назірання, і, наогул, рабіць усё, дзеля чаго патрабуецца доступ да базы даных.
 Калі ласка, пацвердзіце свой намер зрабіць менавіта гэта.',
 'lockconfirm' => 'Так, сапраўды жадаю зачыніць базу даных.',
 'unlockconfirm' => 'Так, сапраўды жадаю адмыкнуць базу дадзеных.',
@@ -2603,9 +2604,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 +2615,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 +2623,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 +2660,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 +3208,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 +3293,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 +3334,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 +3377,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 гэтага пагаднення або, на ваш выбар, навейшая версія (выпуск) пагаднення.
 
@@ -3444,7 +3445,7 @@ MediaWiki распаўсюджваецца, спадзеючыся на прыд
 'tags-description-header' => 'Поўнае апісанне значэння',
 'tags-hitcount-header' => 'Пазначаных правак',
 'tags-edit' => 'правіць',
-'tags-hitcount' => '$1 {{PLURAL:$1|змена|змены|зменаў}}',
+'tags-hitcount' => '$1 {{PLURAL:$1|змена|змены|змен}}',
 
 # Special:ComparePages
 'comparepages' => 'Параўнанне старонак',
index 54097af..db35f2c 100644 (file)
@@ -2928,7 +2928,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' => 'Фільтар па стане зьменаў:',
@@ -3695,7 +3695,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' => 'усё',
@@ -3886,7 +3886,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]].',
index f25f067..dfa161b 100644 (file)
@@ -690,7 +690,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 +757,8 @@ $2',
 'acct_creation_throttle_hit' => 'През последното денонощие, през този IP-адрес посетители на това уики са създали {{PLURAL:$1|1 сметка |$1 сметки}}, което е максималният допустим брой за този период.
 В резултат, към момента не могат да създават повече потребителски сметки през този IP-адрес.',
 'emailauthenticated' => 'Адресът на електронната ви поща беше потвърден на $2 в $3.',
-'emailnotauthenticated' => 'Адресът на електронната ви поща <strong>не е потвърден</strong>. Няма да получавате писма за никоя от следните възможности.',
+'emailnotauthenticated' => 'Адресът на електронната ви поща все още не е потвърден.
+Няма да получавате писма за никоя от следните възможности.',
 'noemailprefs' => 'За да работят тези функционалности, трябва да посочите адрес на електронна поща в своите настройки.',
 'emailconfirmlink' => 'Потвърждаване на адреса за електронна поща',
 'invalidemailaddress' => 'Въведеният адрес не може да бъде приет, тъй като не съответства на формата на адрес за електронна поща. Въведете коректен адрес или оставете полето празно.',
@@ -771,7 +772,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 +1038,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 +1170,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,6 +1323,7 @@ $1",
 'powersearch-togglenone' => 'Никои',
 'search-external' => 'Външно търсене',
 'searchdisabled' => 'Търсенето в {{SITENAME}} е временно изключено. Междувременно можете да търсите чрез Google. Обърнете внимание, че съхранените при тях страници най-вероятно са остарели.',
+'search-error' => 'Възникна грешка при търсене: $1',
 
 # Preferences page
 'preferences' => 'Настройки',
@@ -1458,7 +1460,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' => 'Групи, които не можете да променяте',
 
@@ -1943,6 +1945,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“ няма пренасочвания.',
@@ -2743,7 +2750,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' => 'Филтриране по ниво на персонализация:',
@@ -3022,7 +3029,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 пиксела',
@@ -3443,7 +3450,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' => 'всички',
@@ -3530,6 +3537,9 @@ $5
 'confirm-unwatch-button' => 'Потвърждаване',
 'confirm-unwatch-top' => 'Премахване на страницата от списъка ви за наблюдение?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '„$1“',
+
 # Multipage image navigation
 'imgmultipageprev' => '← предишна страница',
 'imgmultipagenext' => 'следваща страница →',
@@ -3613,7 +3623,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]].',
@@ -3754,9 +3764,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' => '(никакви)',
index fe44b3a..9faf935 100644 (file)
@@ -2655,7 +2655,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 +3369,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 +3558,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.
index f62a548..4166c2f 100644 (file)
@@ -526,7 +526,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 +587,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 +713,7 @@ $2
 'headline_tip' => '২য় স্তরের শিরোনাম',
 'nowiki_sample' => 'অ-ফরম্যাটকৃত টেক্সট এখানে প্রবিষ্ট করুন',
 'nowiki_tip' => 'উইকি ফরম্যাটিং উপেক্ষা করা হোক',
+'image_sample' => 'উদাহরণ.jpg',
 'image_tip' => 'গ্রথিত ফাইল',
 'media_tip' => 'ফাইল সংযোগ',
 'sig_tip' => 'সময় ও তারিখসহ আপনার স্বাক্ষর',
@@ -1025,15 +1027,15 @@ $3-এর দেয়া কারণ হল ''$2''",
 * ভুল ব্যক্তিগত তথ্য
 *:  ''বাসার ঠিকানা এবং ফোন নম্বর, সোসাল সিকিউরিটি নম্বর, ইত্যাদি।''",
 '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' => 'দà§\83শà§\8dযমান',
+'revdelete-radio-unset' => 'লà§\81à¦\95ানà§\8b',
 'revdelete-suppress' => 'সব প্রশাসক ও অন্যান্যদের কাছ থেকে উপাত্ত লুকিয়ে রাখা হোক।',
 'revdelete-unsuppress' => 'সংশোধন পুনঃস্থাপনের উপর সীমাবদ্ধতা দূর করো',
 'revdelete-log' => 'কারণ:',
@@ -2714,7 +2716,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,7 +2903,7 @@ $2',
 'spam_reverting' => '$1-এর প্রতি কোন সংযোগ নেই, এমন সর্বশেষ সংস্করণে ফেরত নেওয়া হচ্ছে।',
 'spam_blanking' => '$1-এর প্রতি সংযোগ অন্তর্ভুক্ত আছে এমন সমস্ত সংশোধন খালি করা হচ্ছে',
 'spam_deleting' => '$1-এর প্রতি সংযোগ অন্তর্ভুক্ত আছে এমন সমস্ত সংশোধন অপসারণ করা হচ্ছে',
-'simpleantispam-label' => "এন্টি-স্প্যাম যাচাই।
+'simpleantispam-label' => "এন্টি স্প্যাম যাচাই।
 এটা পূরণ করবেন '''না'''!",
 
 # Info page
@@ -3468,7 +3470,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' => 'সবগুলো',
@@ -3691,7 +3693,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|মিডিয়াউইকি]] সফটওয়্যারে অবদানের জন্য আমরা এই ব্যক্তিকে স্বীকৃতি দিতে চাই।',
@@ -3710,7 +3712,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' => 'মান:',
index 8025ce8..2722af4 100644 (file)
@@ -1449,7 +1449,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 +1586,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 9191af5..f56bb23 100644 (file)
@@ -187,12 +187,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 +398,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',
@@ -633,7 +633,7 @@ 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ñ]]',
 'createacct-join' => 'Skrivit ho titouroù amañ dindan.',
@@ -700,7 +700,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 +878,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 +1128,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' => 'Hewel',
+'revdelete-radio-unset' => 'Kuzhet',
 'revdelete-suppress' => 'Diverkañ roadennoù ar verourien hag ar re all',
 'revdelete-unsuppress' => 'Lemel ar strishadurioù war ar stummoù assavet',
 'revdelete-log' => 'Abeg :',
@@ -2821,7 +2820,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ù",
@@ -3590,7 +3589,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',
@@ -3793,7 +3792,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]].',
@@ -3924,14 +3923,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',
@@ -3944,9 +3943,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',
index 2c35622..df2cc2d 100644 (file)
@@ -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',
@@ -730,9 +730,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 +792,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 +1235,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:',
@@ -1679,6 +1681,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',
@@ -2925,7 +2928,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:',
@@ -3696,7 +3699,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',
@@ -3938,7 +3941,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.
@@ -4014,6 +4017,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',
index 7032fe0..7ec86fa 100644 (file)
@@ -373,11 +373,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 +407,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ó',
@@ -539,6 +539,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',
@@ -581,7 +582,7 @@ 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.",
@@ -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}}.
@@ -1155,15 +1156,15 @@ Els altres administradors de {{SITENAME}} encara podran accedir al contingut ama
 * Informació personal inapropiada
 *: ''adreces personals, números de telèfon, números de la seguretat social, 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' => 'Visible',
+'revdelete-radio-unset' => 'Oculta',
 'revdelete-suppress' => 'Suprimeix també les dades dels administradors',
 'revdelete-unsuppress' => 'Suprimir les restriccions de les revisions restaurades',
 'revdelete-log' => 'Motiu:',
@@ -2841,7 +2842,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ó:",
@@ -3036,7 +3037,7 @@ 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ó anti-spam.
+'simpleantispam-label' => "Comprovació antispam.
 '''NO''' ho ompliu!",
 
 # Info page
@@ -3051,6 +3052,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',
@@ -3603,7 +3605,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',
@@ -3791,7 +3793,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]]',
@@ -3810,7 +3812,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:',
index 7c96e25..42cb98b 100644 (file)
@@ -437,7 +437,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' => '敆下底輸底汝其信息。',
@@ -1179,7 +1179,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 +1257,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 7850b31..2fbd188 100644 (file)
@@ -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-showtoolbar' => 'Гайта лакхара гӀирсан дакъа нисйеш аттон оц тадар чохь (JavaScript)',
+'tog-editondblclick' => 'Нисйе агӀонаш шозза тӀетаӀийча (JavaScript)',
 'tog-editsection' => 'Гайта хьажораг «нисйе» аьлла хӀора агӀона',
-'tog-editsectiononrightclick' => 'Нисде дакъа шозза бакъехьар дахка тlетаlийча оцу кортан (JavaScript)',
+'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,10 +343,10 @@ $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-oldsig' => 'Ð\9aаÑ\80аÑ\80а ÐºÑ\83Ñ\8cгÑ\82аÓ\80орна:',
 'tog-fancysig' => 'Шен вики-къастаман куьгтаӀдар (ша шех хьажораг йоцуш)',
 'tog-uselivepreview' => 'Лелайа чехка хьалха хьажа (JavaScript, муха ю хьажарна)',
 'tog-forceeditsummary' => 'Дага даийта, нагахь нисйарх лаьцна чохь язйина яцахь',
@@ -550,7 +550,7 @@ $messages = array(
 'redirectedfrom' => '(ДӀасахьажийна кху $1)',
 'redirectpagesub' => 'АгӀо-дӀасахьажайар',
 'lastmodifiedat' => 'ХӀокху агӀон тӀаьххьаралера хийцам: $2, $1.',
-'viewcount' => 'ХӀокху агӀонга хьойсина $1 {{PLURAL:$1|за|за|за}}.',
+'viewcount' => 'ХӀокху агӀонга хьойсина $1 {{PLURAL:$1|за}}.',
 'protectedpage' => 'ГӀароллийца йолу агӀо',
 'jumpto' => 'Дехьа гӀо:',
 'jumptonavigation' => 'Навигаци',
@@ -615,7 +615,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екхочучехь яц',
@@ -651,6 +651,9 @@ $1',
 # General errors
 'error' => 'Гlалат',
 'databaseerror' => 'Гlалат хаамийн бухера',
+'databaseerror-query' => 'Дехар: $1',
+'databaseerror-function' => 'Функци: $1',
+'databaseerror-error' => 'ГӀалат: $1',
 'laggedslavemode' => 'Тергам бе: агӀона чохь керла йаьхинарш ца хила мега.',
 'readonly' => 'Блоктоьхна дӀайаздар хаамийн бухе',
 'enterlockreason' => 'Билгал де блоктохаран бахьна а и чекх йолу хан а.',
@@ -702,6 +705,8 @@ $1',
 'customjsprotected' => 'Хьан бакъо яц хӀара JavaScript-агӀо тая, иза кхечу декъашхочун гӀерс болу дера.',
 'mycustomcssprotected' => 'Хьан бакъо яц хӀара CSS агӀо тая.',
 'mycustomjsprotected' => 'Хьан бакъо яц JavaScript агӀо тая.',
+'myprivateinfoprotected' => 'Хьайн долара хаамна хийцам ба хьа йиш яц',
+'mypreferencesprotected' => 'Хьай гӀирс нисбан хьа бакъо яц.',
 'exception-nologin' => 'Ахьа хӀой вовзийтина/йовзийтина вац/яц',
 
 # Virus scanner
@@ -716,6 +721,7 @@ $1',
 'yourname' => 'Декъашхочун цӀе:',
 'userlogin-yourname' => 'Декъашхочун цӀе',
 'userlogin-yourname-ph' => 'Язъе декъашхочун цӀе',
+'createacct-another-username-ph' => 'Язъе декъашхочун цӀе',
 'yourpassword' => 'Пароль:',
 'userlogin-yourpassword' => 'Пароль',
 'userlogin-yourpassword-ph' => 'Язъе хьай пароль',
@@ -751,17 +757,20 @@ $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|яззам|яззамаш}}',
@@ -790,6 +799,8 @@ $1',
 'noemailcreate' => 'Ахьа нийса электронни почтан адрес дӀаяздан деза',
 'passwordsent' => 'Керла пароль декъашхочун $1 электронни адрес тӀе дӀахьажина. Дехар до, керла пароль еъча юху системин чугӀо.',
 'blocked-mailpassword' => 'Хьан IP-адрес ца тадарш дан магийна дац, цуьндела пароль меттахӀотош йолу функци блоктоьхна ю.',
+'throttled-mailpassword' => 'Пароль дага йоуьйту функци {{PLURAL:$1|тӀехьара $1 сахьтехь}} лелина.
+Зулам цахилийта $1 {{PLURAL:$1|сахьтан чохь}} цӀа бен функци лело йиш яц.',
 'mailerror' => 'Кехат дохьуьйтуш гӀалат ду: $1',
 'emailauthenticated' => 'Хьан почтан адрес бакъдина $2 $3.',
 'accountcreated' => 'Декъашхочун дӀаяздар кхоьллина',
@@ -1275,7 +1286,7 @@ $1',
 'right-nominornewtalk' => 'агӀонашкахь къезиг нисдарш цахиларо хуьлуьйту керла хаамийн хӀоттам',
 'right-apihighlimits' => 'API-дехарш кхочушдан кӀезиг дихкар',
 'right-writeapi' => 'дӀаяздеш лелойо API',
-'right-delete' => 'агӀош дӀаяхар',
+'right-delete' => 'агӀонаш дӀаяхар',
 'right-bigdelete' => 'еха хийцаман истори йолу агӀонаш дӀаяхар',
 'right-deletelogentry' => 'тептар чура билгала дӀаяздарш дӀадахар а меттахӀиттадар а.',
 'right-deleterevision' => 'агӀонийн билгала версеш дӀаяхар а меттахӀиттаяр а',
@@ -1401,6 +1412,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]]»',
@@ -1412,6 +1427,7 @@ $1',
 'upload-description' => 'Файлах лаьцна',
 'upload-options' => 'Чуякхаран параметраш',
 'watchthisupload' => 'Латайе хӀара файл тергаме могӀам юкъахь',
+'filewasdeleted' => 'Иштта цӀе йолуш файл хьалха чуяьккхина хила, амма дӀаяьккхина. Дехар до, юху чуяккхале $1 хьажа.',
 'filename-prefix-blacklist' => '#<!-- битийша хlара могlа ша мабарра --> <pre>
 # Бухасиз шолгlа:
 #  * Массо, саболчунтlийра йуьлалуш ерш «#» хуьлу хетаме дерг (могlа чекх балац)
@@ -1440,7 +1456,7 @@ PICT # тайп тайпан
 Декъашхо къастичи, цун керла файлаш гойту.',
 'listfiles_search_for' => 'Лаха хIуман цIарца:',
 'imgfile' => 'файл',
-'listfiles' => 'Файлийн Ð¼Ð¾Ð³Ó\80ам',
+'listfiles' => 'ФайлаÑ\88',
 'listfiles_date' => 'Терахь',
 'listfiles_name' => 'Файлан цӀе',
 'listfiles_user' => 'Декъашхо',
@@ -1481,6 +1497,7 @@ PICT # тайп тайпан
 'filerevert-success' => "Юхаерзина файл '''[[Media:$1|$1]]''' оцу [$4 верси $3, $2].",
 
 # File deletion
+'filedelete' => '$1 — дӀаяккхар',
 'filedelete-legend' => 'ДӀаяккха файл',
 'filedelete-intro' => "Хьо файл '''[[Media:$1|$1]]''' дӀаяккха гӀерта цунна массо истори цхьан.",
 'filedelete-comment' => 'Бахьан:',
@@ -1688,6 +1705,8 @@ PICT # тайп тайпан
 'emailuser' => 'Декъашхочун хааман кехат',
 'emailuser-title-target' => 'Декъашхочунга кехат яздар',
 'emailuser-title-notarget' => 'Декъашхочунга кехат яздар',
+'emailpagetext' => 'ХӀокху агӀона гӀоьнца йиш ю {{GENDER:$1|декъашхочун}} электронан почте хаам бахьийта.
+Хьоьга жоп лур ду ахьа [[Special:Preferences|хьайн гӀирса чу]] дӀаяздина долу адрес тӀе.',
 'defemailsubject' => 'Хаам {{grammar:genitive|{{SITENAME}}}} чура бу',
 'emailusername' => 'Декъашхочун цӀе:',
 'emailusernamesubmit' => 'ДӀадахьийта',
@@ -1695,6 +1714,8 @@ PICT # тайп тайпан
 'emailfrom' => 'Хьаьнгара',
 'emailto' => 'Хьаьнга:',
 'emailmessage' => 'Хаам:',
+'emailsend' => 'ДӀадахьийта',
+'emailccme' => 'Соьга а кхосса хааман копи.',
 'emailsent' => 'Кехат дӏадахьийтина',
 'emailsenttext' => 'Хьан электроннан хаам дӏабахьийтина.',
 
@@ -1765,7 +1786,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' => 'Бакъде гӀоралла дар',
@@ -2064,7 +2085,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' => 'Хийцан йоцурш',
@@ -2216,9 +2237,13 @@ 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 де}}',
+'ago' => '$1 хьалха',
 
 # Human-readable timestamps
 'hours-ago' => '$1 {{PLURAL:$1|сахьат}} хьалха',
+'minutes-ago' => '$1 {{PLURAL:$1|минут}} хьалха',
 'yesterday-at' => 'селхана $1 даьлча',
 
 # Bad image list
@@ -2317,7 +2342,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' => 'массо',
@@ -2486,6 +2511,10 @@ PICT # тайп тайпан
 # Search suggestions
 'searchsuggest-search' => 'Лаха',
 
+# Durations
+'duration-hours' => '$1 {{PLURAL:$1|сахьат}}',
+'duration-days' => '$1 {{PLURAL:$1|де}}',
+
 # Limit report
 'limitreport-title' => 'АгӀона хӀоттам къасторан хаамаш:',
 'limitreport-cputime' => 'Процессоран хан лелор',
index 7bb494f..2924f42 100644 (file)
@@ -1203,7 +1203,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..e7f1fbc 100644 (file)
@@ -12,6 +12,7 @@
  * @author Jatrobat
  * @author Magalahi
  * @author MisterWiki
+ * @author Shirayuki
  */
 
 $namespaceNames = array(
@@ -1086,7 +1087,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 d083eb5..3a98888 100644 (file)
@@ -2607,7 +2607,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' => 'نەگۆڕدراو',
@@ -3175,7 +3175,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 17de57f..b86f919 100644 (file)
@@ -953,7 +953,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 c07de24..b6ac4ee 100644 (file)
@@ -1680,7 +1680,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' => 'Буют',
@@ -1917,7 +1917,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 6bb6a4c..8d0f24d 100644 (file)
@@ -1674,7 +1674,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',
@@ -1911,7 +1911,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 8d3b367..248bfc0 100644 (file)
@@ -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.',
@@ -1317,15 +1318,15 @@ pokud nebyla nastavena další omezení.",
 * 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-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:',
@@ -3004,7 +3005,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 +3165,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 */',
@@ -3227,6 +3229,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',
@@ -3777,7 +3780,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',
@@ -3880,6 +3883,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',
@@ -4023,7 +4027,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]].',
index 2d2d4bf..1465f5d 100644 (file)
@@ -1090,7 +1090,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 +1224,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 706051c..c954f6c 100644 (file)
@@ -927,7 +927,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 a7e5063..05d0e68 100644 (file)
@@ -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',
@@ -569,7 +569,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}}.
@@ -636,7 +636,7 @@ Er mwyn rhwystro camddefnydd, dim ond un e-bost i'ch atgoffa o'ch cyfrinair gaif
 '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.',
@@ -1062,15 +1062,15 @@ Fe fydd gweinyddwyr eraill {{SITENAME}} o hyd yn gallu gweld yr hyn a guddiwyd.
 * 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' => 'Gweladwy',
+'revdelete-radio-unset' => 'Cudd',
 'revdelete-suppress' => 'Atal data oddi wrth Weinyddwyr yn ogystal ag eraill',
 'revdelete-unsuppress' => "Tynnu'r cyfyngiadau ar y golygiadau a adferwyd",
 'revdelete-log' => 'Rheswm:',
@@ -2451,7 +2451,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 +2766,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 +2931,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.",
@@ -3525,7 +3525,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',
@@ -3697,7 +3697,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]].',
index 162fee0..dc35954 100644 (file)
@@ -43,6 +43,7 @@
  * @author Qaqqalik
  * @author Remember the dot
  * @author Sarrus
+ * @author Shirayuki
  * @author Simeondahl
  * @author Sir48
  * @author Slomox
@@ -648,7 +649,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}}.
@@ -712,14 +713,14 @@ kan du bare ignorere denne e-mail og fortsætte med at bruge din gamle adgangsko
 '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 en ny adgangskode.',
-'eauthentsent' => 'En bekræftelsesmail er sendt til den angivne e-mailadresse.
+'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.',
+'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.',
@@ -1143,19 +1144,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-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:',
@@ -2664,7 +2666,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' => 'ændr blokering',
 'contribslink' => 'bidrag',
 'emaillink' => 'send e-mail',
 'autoblocker' => 'Du er automatisk blokeret, fordi du deler IP-adresse med "[[User:$1|$1]]".
@@ -2846,7 +2848,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:',
@@ -3057,6 +3059,7 @@ Udfyld '''IKKE''' dette!",
 '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',
@@ -3142,7 +3145,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',
@@ -3609,7 +3612,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',
@@ -3788,7 +3791,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]].',
@@ -3807,7 +3810,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:',
@@ -3872,7 +3875,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
index 61d3a74..10d14d2 100644 (file)
@@ -877,7 +877,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.
@@ -949,7 +949,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.',
@@ -1374,18 +1375,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:',
@@ -3070,7 +3072,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 +3234,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. */',
@@ -3297,6 +3299,7 @@ Hier '''NICHTS''' eintragen!",
 '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',
@@ -3384,7 +3387,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',
@@ -3850,7 +3853,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',
@@ -3951,6 +3954,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',
@@ -4053,7 +4057,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]].',
index ab87bab..1671ce6 100644 (file)
@@ -14,6 +14,7 @@
  * @author George Animal
  * @author Gorizon
  * @author Kaganer
+ * @author Marmase
  * @author Mirzali
  * @author Nemo bis
  * @author Neribij
@@ -374,50 +375,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 +439,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,30 +453,30 @@ $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)',
 
-'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',
@@ -483,38 +484,38 @@ $messages = array(
 # Vector skin
 'vector-action-addsection' => 'Mewzu vıraze',
 'vector-action-delete' => 'Bestere',
-'vector-action-move' => 'Berê',
-'vector-action-protect' => 'Bıpawe',
+'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éni 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',
 'permalink' => 'Gıreyo jûqere',
 'print' => 'Nusten ke',
 'view' => 'Bıvin',
 'edit' => 'Bıvurnên',
-'create' => 'Vıraze',
+'create' => 'İycad ke',
 'editthispage' => 'Ena pele bıvurne',
 'create-this-page' => 'Na pele bınuse',
 'delete' => 'Bestere',
@@ -522,19 +523,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',
@@ -552,7 +553,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ê.
@@ -564,7 +565,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}}i de',
+'aboutsite' => 'Heqdé {{SITENAME}}',
 'aboutpage' => 'Project:Heqdê cı',
 'copyright' => 'Zerrekacı $1 bındı not biya.',
 'copyrightpage' => '{{ns:project}}:Heqa telifi',
@@ -573,9 +574,9 @@ $1',
 'disclaimers' => 'Redê 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',
@@ -607,7 +608,7 @@ $1',
 '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',
@@ -631,16 +632,16 @@ $1',
 '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-template' => 'Tewre',
 'nstab-help' => 'Pela peşti',
-'nstab-category' => 'Kategoriye',
+'nstab-category' => 'Kategori',
 
 # Main script and global functions
 'nosuchaction' => 'Fealiyeto wınasi çıniyo',
@@ -653,8 +654,8 @@ 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-query' => 'Perskerdış:$1',
 'databaseerror-function' => 'Fonksiyon: $1',
 'databaseerror-error' => 'Xırab: $1',
@@ -698,7 +699,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.
@@ -717,6 +718,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\'\'".',
@@ -737,12 +740,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,7 +776,7 @@ Wexta ke verhafızayê cıgerayoxê şıma pak beno no benate de taye peli de he
 'gotaccount' => "Hesabê şıma esto? '''$1'''.",
 'gotaccountlink' => 'Cı kewe',
 'userlogin-resetlink' => 'Melumatê cıkewtışi xo vira kerdê?',
-'userlogin-resetpassword-link' => 'Parolaya xo reset ke',
+'userlogin-resetpassword-link' => 'To parola ke ğo vira?',
 'helplogin-url' => 'Help:Qeydbiyayış',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Desteg be qeydbiyayış ra]]',
 'userlogin-createanother' => 'Zewbi hesab vıraz',
@@ -841,17 +844,17 @@ Seba xırabgurenayışê xızmete ra, her {{PLURAL:$1|yew saete|$1 saetan}} de r
 '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ê',
@@ -879,7 +882,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:',
@@ -926,7 +929,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',
@@ -960,8 +963,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 +1055,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 +1121,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 +1191,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 +1203,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 +1254,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 +1265,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 +1319,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 +1339,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 +1352,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 +1362,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 +1382,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 +1400,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',
@@ -1462,7 +1465,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 +1507,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 +1541,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 +1573,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 +1581,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',
@@ -1686,7 +1689,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',
@@ -1718,16 +1721,16 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 '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.",
+'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',
@@ -2132,7 +2135,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ê',
@@ -2170,7 +2173,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}}',
@@ -2225,8 +2228,8 @@ gıreyê her satıri de gıreyi; raş motışê yewın u dıyıni esto.
 'newpages' => 'Pelê 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.',
@@ -2298,7 +2301,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 />
@@ -2582,8 +2585,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
@@ -2644,7 +2647,7 @@ $1',
 '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',
@@ -2903,14 +2906,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é uw 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?',
@@ -2965,7 +2968,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',
@@ -3165,7 +3168,7 @@ Ney '''Mefiyé de'''!",
 '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',
@@ -3173,6 +3176,7 @@ Ney '''Mefiyé de'''!",
 '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',
@@ -3228,9 +3232,9 @@ Ney '''Mefiyé de'''!",
 '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',
@@ -3261,7 +3265,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',
@@ -3283,7 +3287,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',
@@ -3543,7 +3547,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',
@@ -3830,7 +3834,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',
@@ -3939,6 +3943,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',
@@ -4108,7 +4113,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.',
@@ -4132,7 +4137,7 @@ enê programiya piya [{{SERVER}}{{SCRIPTPATH}}/COPYING jew kopyay lisans dê GNU
 '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ê',
index d53ebe1..c9c0123 100644 (file)
@@ -2655,7 +2655,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ś:',
@@ -3400,7 +3400,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',
@@ -3584,7 +3584,7 @@ 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-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.
index 2ec192b..4cffee6 100644 (file)
@@ -1477,7 +1477,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 410d7d9..7bcb901 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
@@ -811,7 +813,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' => 'Εισάγετε τα στοιχεία σας παρακάτω.',
@@ -1308,8 +1310,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' => 'Αιτία:',
@@ -2979,7 +2981,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' => 'Ταξινόμηση βάσει της δήλωσης προσαρμογής:',
@@ -3745,7 +3747,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' => 'όλες',
@@ -3932,8 +3934,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· είτε της δεύτερης έκδοσης της άδειας, είτε (κατ' επιλογή σας) οποιασδήποτε επόμενης έκδοσης.
 
@@ -4010,6 +4013,8 @@ $5
 'tags-display-header' => 'Εμφάνιση στις λίστες αλλαγής',
 'tags-description-header' => 'Πλήρης περιγραφή του νοήματος',
 'tags-hitcount-header' => 'Αλλαγές με ετικέτα',
+'tags-active-yes' => 'Ναι',
+'tags-active-no' => 'Όχι',
 'tags-edit' => 'επεξεργασία',
 'tags-hitcount' => '$1 {{PLURAL:$1|αλλαγή|αλλαγές}}',
 
index 7b62d29..0766cd2 100644 (file)
@@ -556,7 +556,7 @@ $preloadedMessages = array(
        'editsectionhint',
        'help',
        'helppage',
-       'tooltip-iwiki',
+       'interlanguage-link-title',
        'jumpto',
        'jumptonavigation',
        'jumptosearch',
@@ -915,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',
@@ -976,7 +976,7 @@ 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
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main'      => 'Page',
@@ -1134,7 +1134,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}}.
@@ -1228,8 +1228,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',
@@ -1708,7 +1708,7 @@ 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'         => 'Revision text',
 'revdelete-hide-image'        => 'Hide file content',
@@ -1717,8 +1717,8 @@ Other administrators on {{SITENAME}} will still be able to access the hidden con
 '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'         => 'Visible',
-'revdelete-radio-unset'       => 'Hidden',
+'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:',
@@ -3566,7 +3566,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:',
@@ -3871,6 +3871,7 @@ Do '''NOT''' fill this in!",
 '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',
@@ -3961,7 +3962,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',
@@ -4535,7 +4536,7 @@ $8', # only translate this message to other languages if you have to change it
 
 # 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' => 'all',
@@ -4651,6 +4652,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',
@@ -4849,7 +4851,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]].',
index b8ec1e5..93ea15e 100644 (file)
@@ -38,6 +38,7 @@
  * @author Smeira
  * @author ThomasPusch
  * @author Tlustulimu
+ * @author Umbert'
  * @author Urhixidur
  * @author Yekrats
  * @author Александр Сигачёв
@@ -570,7 +571,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',
@@ -653,6 +654,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 +780,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 +797,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 +833,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 +855,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 +877,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 +889,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 +921,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 +935,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 +1149,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 +1186,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 +1284,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:',
@@ -1535,6 +1550,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 +1577,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 +1651,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 +1704,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,12 +1714,18 @@ 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',
@@ -2923,7 +2948,7 @@ 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',
@@ -3691,7 +3716,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',
@@ -3930,7 +3955,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.
index 34455a1..5ee3f91 100644 (file)
@@ -828,7 +828,7 @@ No olvides personalizar tus [[Special:Preferences|preferencias de {{SITENAME}}]]
 'gotaccount' => '¿Ya tienes una cuenta? $1.',
 'gotaccountlink' => 'Entrar',
 '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}}.
@@ -901,7 +901,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.',
@@ -1343,15 +1343,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' => 'Visible',
+'revdelete-radio-unset' => 'Oculto',
 'revdelete-suppress' => 'Suprimir datos a los administradores así como al resto',
 'revdelete-unsuppress' => 'Eliminar restricciones de revisiones restauradas',
 'revdelete-log' => 'Motivo:',
@@ -1549,7 +1549,7 @@ 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.',
+'savedprefs' => 'Se han guardado tus preferencias.',
 'timezonelegend' => 'Zona horaria:',
 'localtime' => 'Hora local:',
 'timezoneuseserverdefault' => 'Usar la hora del servidor ($1)',
@@ -1595,8 +1595,8 @@ Esto no se puede deshacer.',
 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',
+'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.',
@@ -3044,7 +3044,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:',
@@ -3833,7 +3833,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',
@@ -4014,7 +4014,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]].',
index ecdae41..e058d6e 100644 (file)
@@ -7,6 +7,7 @@
  * @ingroup Language
  * @file
  *
+ * @author AivoK
  * @author Avjoska
  * @author Cylly1512
  * @author Geitost
@@ -746,7 +747,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 +806,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.
@@ -1119,15 +1121,15 @@ Tundub, et see on kustutatud.',
 See on juba olemas.',
 'defaultmessagetext' => 'Sõnumi vaiketekst',
 '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.",
@@ -1239,18 +1241,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:',
@@ -2889,7 +2892,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 +2936,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:',
@@ -3145,6 +3149,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',
@@ -3231,7 +3236,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',
@@ -3675,7 +3680,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',
@@ -3848,7 +3853,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.',
@@ -3867,7 +3872,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:',
index 1848261..481348c 100644 (file)
@@ -133,12 +133,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 +156,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 +269,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 +351,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 +372,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',
@@ -455,6 +455,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 +492,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 +521,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 +542,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 +579,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 +644,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 +669,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 +690,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 +716,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 +730,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 +765,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 +818,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 +866,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 +1094,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
@@ -1124,6 +1150,7 @@ Kontura zaitez nabigazio loturek, zutabea ezabatu dezakela.',
 '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
@@ -1218,7 +1245,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 +1298,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 +1315,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 +1326,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 +1485,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.',
@@ -1486,7 +1524,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 +1654,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 +1664,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 +1675,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 +1835,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 +2065,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 +2293,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 +2303,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 +2341,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 +2604,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 +2620,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 +2637,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 +2683,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 +2697,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 +2804,7 @@ 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!",
 
@@ -2756,14 +2820,15 @@ Atal hau '''EZ''' bete!",
 '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',
@@ -2772,6 +2837,7 @@ Atal hau '''EZ''' bete!",
 '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',
@@ -3047,6 +3113,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',
@@ -3058,11 +3125,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',
@@ -3089,10 +3159,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',
@@ -3275,8 +3348,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',
@@ -3313,7 +3388,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',
@@ -3457,7 +3532,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',
@@ -3486,6 +3561,7 @@ 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',
@@ -3540,6 +3616,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',
@@ -3567,6 +3646,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',
@@ -3598,7 +3678,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',
 
@@ -3609,11 +3691,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.',
index cf6a54d..197a590 100644 (file)
@@ -1758,7 +1758,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 +2180,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ó',
index c96c615..8323ac8 100644 (file)
@@ -481,7 +481,7 @@ $messages = array(
 'tog-noconvertlink' => 'تبدیل عنوان پیوند غیرفعال شود',
 'tog-norollbackdiff' => 'بعد از واگردانی تفاوت نشان داده نشود',
 'tog-useeditwarning' => 'زمان خروج از صفحهٔ ویرایش در صورت داشتن ویرایش‌های‌ ذخیره‌نشده به من هشدار داده شود',
-'tog-prefershttps' => 'هنگامی که ثبت ورود انجام گرفته همواره از اتصال امن استفاده شود',
+'tog-prefershttps' => 'در حالت ورود به سامانه همواره از اتصال امن استفاده شود',
 
 'underline-always' => 'همیشه',
 'underline-never' => 'هرگز',
@@ -976,8 +976,8 @@ $2',
 'mailerror' => 'خطا در فرستادن رایانامه: $1',
 'acct_creation_throttle_hit' => 'بازدیدکنندگان این ویکی که از نشانی آی‌پی شما استفاده می‌کنند در روز گذشته {{PLURAL:$1|یک حساب کاربری|$1 حساب کاربری}} ساخته‌اند، که بیشترین تعداد مجاز در آن بازهٔ زمانی است.
 به همین خاطر، بازدیدکنندگانی که از این نشانی آی‌پی استفاده می‌کنند نمی‌توانند در حال حاضر حساب جدیدی بسازند.',
-'emailauthenticated' => 'نشانی رایانامه شما در $2 ساعت $3 تصدیق شد.',
-'emailnotauthenticated' => 'نشانی رایانامه شما هنوز تصدیق نشده‌است.
+'emailauthenticated' => 'نشانی رایانامهٔ شما در $2 ساعت $3 تصدیق شد.',
+'emailnotauthenticated' => 'نشانی رایانامهٔ شما هنوز تصدیق نشده‌است.
 برای هیچ‌یک از ویژگی‌های زیر رایانامه ارسال نخواهد شد.',
 'noemailprefs' => 'برای راه‌اندازی این قابلیت‌ها یک نشانی رایانامه مشخص کنید.',
 'emailconfirmlink' => 'تأیید نشانی رایانامه',
@@ -1053,7 +1053,7 @@ $2
 شما باید هم‌اکنون وارد شده و یک گذرواژهٔ جدید برگزینید. اگر شخص دیگری این درخواست را داده است، یا اگر گذرواژهٔ اصلی‌تان را به خاطر آوردید و دیگر نمی‌خواهید آن را تغییر دهید، می‌توانید این پیغام را نادیده بگیرید و به استفاده از گذرواژهٔ قبلی‌تان ادامه دهید.',
 'passwordreset-emailelement' => 'نام کاربری: $1
 گذرواژهٔ موقت: $2',
-'passwordreset-emailsent' => 'یک نامهٔ بازنشانی گذرواژه فرستاده شده است.',
+'passwordreset-emailsent' => 'یک نامهٔ بازنشانی گذرواژه فرستاده شدهاست.',
 'passwordreset-emailsent-capture' => 'یک رایانامهٔ بازنشانی که در پایین نمایش داده شده، فرستاده شده است.',
 'passwordreset-emailerror-capture' => 'رایانامهٔ بازنشانی، که در زیر نمایش داده شده، ایجاد شد، ولی ارسال آن به {{GENDER:$2|کاربر}} موفقیت‌آمیز نبود: $1',
 
@@ -1250,8 +1250,8 @@ $2
 اگر می‌خواهید متن را در یک پروندهٔ متنی کپی کنید و برای آینده ذخیره‌اش کنید.
 
 مدیری که آن را قفل کرده این توضیح را ارائه کرده‌است: $1",
-'protectedpagewarning' => "'''هشدار: این صفحه قفل شده است تا فقط کاربران با امتیاز مدیر بتوانند ویرایشش کنند.'''
-آخرین موارد سیاهه در زیر آمده است:",
+'protectedpagewarning' => "'''هشدار: این صفحه قفل شده‌است تا فقط کاربران با دسترسی مدیریت بتوانند ویرایشش کنند.'''
+آخرین موارد سیاهه در زیر آمدهاست:",
 'semiprotectedpagewarning' => "'''توجه:''' این صفحه قفل شده‌است تا تنها کاربران ثبت‌نام‌کرده قادر به ویرایش آن باشند.
 آخرین موارد سیاهه در زیر آمده‌است:",
 'cascadeprotectedwarning' => "'''هشدار:''' این صفحه به علت قرارگرفتن در {{PLURAL:$1|صفحهٔ|صفحه‌های}} آبشاری-محافظت‌شدهٔ زیر قفل شده‌است تا فقط مدیران بتوانند ویرایشش کنند.",
@@ -1421,15 +1421,15 @@ $2
 * اطلاعات نامناسب شخصی
 *: ''نشانی منزل، شماره تلفن، شماره تامین اجتماعی و غیره.''",
 '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 +1534,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' => 'صفحه‌های محتوایی',
@@ -1794,7 +1794,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' => 'ویرایش واسط کاربری',
@@ -1852,7 +1852,7 @@ $1",
 'action-delete' => 'حذف این صفحه',
 'action-deleterevision' => 'حذف این نسخه',
 'action-deletedhistory' => 'مشاهدهٔ تاریخچهٔ حذف شدهٔ این صفحه',
-'action-browsearchive' => 'جستجوی صفحه‌های حذف شده',
+'action-browsearchive' => 'جستجوی صفحه‌های حذفشده',
 'action-undelete' => 'احیای این صفحه',
 'action-suppressrevision' => 'مشاهده و احیای ویرایش‌های حذف شده',
 'action-suppressionlog' => 'مشاهدهٔ این سیاههٔ خصوصی',
@@ -2121,10 +2121,10 @@ $1',
 # Special:UploadStash
 'uploadstash' => 'انبار بارگذاری',
 'uploadstash-summary' => 'این صفحه دسترسی به پرونده‌هایی که بارگذاری شده‌اند (یا در حال بارگذاری هستند) اما هنوز در ویکی منتشر نشده‌اند را فراهم می‌کند. این پرونده‌ها توسط هیچ کاربری به جز کسی که آن‌ها را بارگذاری کرده قابل دیدن نیستند.',
-'uploadstash-clear' => 'پاک کردن پرونده‌های انبارشده',
+'uploadstash-clear' => 'پاککردن پرونده‌های انبارشده',
 'uploadstash-nofiles' => 'شما هیچ پروندهٔ انبارشده‌ای ندارید.',
 'uploadstash-badtoken' => 'انجام این اقدام ناموفق بود، احتمالاً به این دلیل که اعتبار ویرایش شما به اتمام رسیده است. دوباره امتحان کنید.',
-'uploadstash-errclear' => 'پاک کردن پرونده‌ها ناموفق بود.',
+'uploadstash-errclear' => 'پاککردن پرونده‌ها ناموفق بود.',
 'uploadstash-refresh' => 'تازه‌کردن فهرست پرونده‌ها',
 'invalid-chunk-offset' => 'جابجایی نامعتبر قطعه',
 
@@ -2802,7 +2802,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 +2890,8 @@ $1',
 'ipbreason' => 'دلیل:',
 'ipbreasonotherlist' => 'دلیل دیگر',
 'ipbreason-dropdown' => '*دلایل متداول قطع دسترسی
-**وارد کردن اطلاعات نادرست
-**پاک کردن اطلاعات مفید از صفحه‌ها
+**واردکردن اطلاعات نادرست
+**پاککردن اطلاعات مفید از صفحه‌ها
 **هرزنگاری از طریق درج مکرر پیوند به وب‌گاه‌ها
 **درج چرندیات یا نوشته‌های بی‌معنا در صفحه‌ها
 **تهدید یا ارعاب دیگر کاربران
@@ -3149,7 +3149,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' => "نمی‌توان از '''{{ns:special}}:همهٔ پیغام‌ها''' استفاده کرد چود '''&lrm;\$wgUseDatabaseMessages''' خاموش شده است.",
 'allmessages-filter-legend' => 'پالایه',
 'allmessages-filter' => 'پالودن بر اساس وضعیت شخصی‌سازی:',
@@ -3240,7 +3240,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 جاوااسکریپت برای مدیاویکی',
@@ -3470,6 +3470,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|ساعت|ساعت}}',
@@ -3915,7 +3919,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' => 'همه',
@@ -3999,7 +4003,7 @@ $5
 
 # action=purge
 'confirm_purge_button' => 'تأیید',
-'confirm-purge-top' => 'پاک کردن نسخهٔ حافظهٔ نهانی (Cache) این صفحه را تأیید می‌کنید؟',
+'confirm-purge-top' => 'پاککردن نسخهٔ حافظهٔ نهانی (Cache) این صفحه را تأیید می‌کنید؟',
 'confirm-purge-bottom' => 'خالی کردن میانگیر یک صفحه باعث می‌شود که آخرین نسخهٔ آن نمایش یابد.',
 
 # action=watch/unwatch
@@ -4162,7 +4166,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|مدیاویکی]] معرفی می‌نمائیم.',
@@ -4209,7 +4213,7 @@ $5
 * صفحه‌های ویژهٔ عادی.
 * <strong class="mw-specialpagerestricted">صفحه‌های ویژهٔ محدودشده.</strong>',
 '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' => 'گزارش بارگذاری رسانه‌ها',
index 8a62105..c5a8760 100644 (file)
@@ -22,6 +22,7 @@
  * @author Kaganer
  * @author Kulmalukko
  * @author Linnea
+ * @author Mies
  * @author Mobe
  * @author Nedergard
  * @author Nike
@@ -771,7 +772,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}}.
@@ -836,7 +837,8 @@ Muita viestejä ei lähetetä, ennen kuin olet toiminut viestin ohjeiden mukaan
 '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.',
@@ -916,8 +918,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
@@ -1137,7 +1139,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',
 
@@ -1255,8 +1257,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ö',
@@ -1265,8 +1268,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:',
@@ -1282,15 +1285,17 @@ $1",
 'revdel-restore-visible' => 'näkyvät versiot',
 'pagehist' => 'Sivun muutoshistoria',
 'deletedhist' => 'Poistettujen versioiden historia',
-'revdelete-hide-current' => 'Virhe piilotettaessa $1 kello $2 päivättyä kohdetta: Tämä on uusin versio.
+'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-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 $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-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
@@ -1401,7 +1406,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.',
@@ -1412,7 +1417,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',
@@ -1604,7 +1609,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ä',
@@ -1614,9 +1619,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',
@@ -1635,20 +1640,20 @@ Tämä tieto on julkinen.',
 'right-edituserjs' => 'Muokata toisten käyttäjien JavaScript-tiedostoja',
 'right-editmyusercss' => 'Muokata omia CSS-tiedostoja',
 'right-editmyuserjs' => 'Muokata omia JavaScript-tiedostoja',
-'right-viewmywatchlist' => 'Tarkastella tarkkailulistaasi',
+'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ä',
@@ -1673,7 +1678,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',
@@ -1685,7 +1690,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',
@@ -1693,9 +1698,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',
@@ -2046,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
@@ -2459,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',
@@ -2486,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ä.',
@@ -2567,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',
@@ -2639,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',
@@ -2715,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',
@@ -2771,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.',
@@ -2903,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',
@@ -2931,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',
@@ -2960,7 +2964,7 @@ $2',
 
 # Special:Import
 'import' => 'Tuo sivuja',
-'importinterwiki' => 'Tuo sivuja lähiwikeistä',
+'importinterwiki' => 'Tuo sivuja muista wikeistä',
 '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]].',
 'import-interwiki-source' => 'Lähdewiki/sivu:',
 'import-interwiki-history' => 'Kopioi sivun koko historia',
@@ -2969,7 +2973,7 @@ $2',
 'import-interwiki-namespace' => 'Kohdenimiavaruus:',
 'import-interwiki-rootpage' => 'Tuo annetun sivun alasivuiksi (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...',
@@ -2997,9 +3001,9 @@ 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.',
@@ -3008,7 +3012,7 @@ Tallenna tiedot koneellesi ja tuo ne tällä sivulla.',
 # Import log
 'importlogpage' => 'Tuontiloki',
 'importlogpagetext' => 'Loki toisista wikeistä tuoduista sivuista.',
-'import-logentry-upload' => 'toi sivun [[$1]] lähettämällä tiedoston',
+'import-logentry-upload' => 'toi tiedoston [[$1]] tallentamalla sen',
 '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',
@@ -3041,9 +3045,9 @@ 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',
@@ -3055,7 +3059,7 @@ Voit katsella sivun lähteenä olevaa wikitekstiä.',
 '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',
@@ -3088,10 +3092,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ä. */',
@@ -3145,7 +3150,7 @@ Voit katsella sivun lähteenä olevaa wikitekstiä.',
 
 # 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',
@@ -3155,6 +3160,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',
@@ -3219,8 +3225,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
@@ -3240,7 +3246,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ä',
@@ -3707,7 +3713,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',
@@ -3889,7 +3895,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]].',
index 794d86d..f7249bf 100644 (file)
@@ -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' => 'Sjónligt',
+'revdelete-radio-unset' => 'Fjalt',
 '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:',
@@ -2625,7 +2628,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',
@@ -3055,7 +3058,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',
@@ -3145,7 +3148,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]].',
index 06f49ba..52c1055 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
@@ -434,7 +436,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',
@@ -797,7 +799,7 @@ 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' => 'Non connecté(e)',
 'exception-nologin-text' => "Cette page ou cette action nécessite d'être connecté sur ce wiki.",
 
 # Virus scanner
@@ -839,17 +841,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.',
@@ -915,8 +917,8 @@ Avant qu’un autre courriel ne soit envoyé à ce compte, vous devrez suivre le
 '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 +957,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.
@@ -996,7 +998,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 +1050,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 +1099,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 +1171,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 +1341,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 +1480,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>.',
@@ -1713,7 +1716,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",
@@ -1844,7 +1847,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 +2061,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 +2242,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)',
@@ -2318,7 +2321,7 @@ Les entrées <del>barrées</del> ont été résolues.',
 'listusers-creationsort' => 'Trier par date de création',
 'listusers-desc' => 'Trier en ordre descendant',
 'usereditcount' => '$1 modification{{PLURAL:$1||s}}',
-'usercreated' => '{{GENDER:$3|Créé}} le $1 à $2',
+'usercreated' => '{{GENDER:$3|Créé|Créée|Créé(e)}} le $1 à $2',
 'newpages' => 'Nouvelles pages',
 'newpages-username' => "Nom d'utilisateur :",
 'ancientpages' => 'Pages les plus anciennement modifiées',
@@ -2481,8 +2484,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.',
@@ -2832,7 +2835,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 +2845,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 +2920,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 +3057,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 +3224,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. */',
@@ -3285,6 +3288,7 @@ Ne '''RIEN''' inscrire ici !",
 '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',
@@ -3371,7 +3375,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',
@@ -3843,7 +3847,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',
@@ -3931,7 +3935,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.",
@@ -3953,6 +3957,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',
@@ -4105,7 +4110,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]].',
index e83aa9a..695e28a 100644 (file)
@@ -2988,7 +2988,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 :',
@@ -3737,7 +3737,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',
@@ -3999,7 +3999,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.
 
index 0087677..80b8b93 100644 (file)
@@ -479,7 +479,7 @@ 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.
@@ -505,8 +505,8 @@ Brük det formulaar diar oner, am di mä en öödern nööm uuntumeldin.',
 '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',
@@ -532,7 +532,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.
@@ -578,7 +578,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.',
 
@@ -609,10 +609,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:
@@ -626,8 +626,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',
@@ -693,7 +693,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''.
@@ -704,11 +704,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''.
@@ -719,10 +719,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]].',
@@ -976,17 +976,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' => 'Tu sen',
+'revdelete-radio-unset' => 'Ferbürgen',
 '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:',
@@ -1034,8 +1034,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.',
@@ -1475,7 +1475,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',
@@ -1515,13 +1515,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.',
@@ -1533,8 +1533,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.
@@ -1543,26 +1543,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.',
@@ -1578,7 +1578,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.',
@@ -1692,7 +1692,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',
@@ -1754,7 +1754,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',
@@ -1928,7 +1928,7 @@ Uun arke rä stun ferwisangen tu't iarst an ööder widjerfeerang an uk tu det s
 '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',
@@ -2057,7 +2057,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',
@@ -2269,7 +2269,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)',
@@ -2640,7 +2640,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:',
@@ -2801,6 +2801,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.',
@@ -2840,6 +2841,7 @@ Heer '''NIKS''' iindreeg!",
 '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',
@@ -2934,7 +2936,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)',
@@ -3385,7 +3387,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',
@@ -3477,6 +3479,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 →',
@@ -3561,7 +3566,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]].',
@@ -3580,7 +3585,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:',
@@ -3705,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.',
@@ -3755,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}}.
index e5c1211..e63a5e1 100644 (file)
@@ -1358,7 +1358,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 +1543,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',
index db3b20d..b531a43 100644 (file)
@@ -12,6 +12,7 @@
  * @author Purodha
  * @author Pyt
  * @author SK-luuut
+ * @author Shirayuki
  * @author Snakesteuben
  * @author Urhixidur
  * @author לערי ריינהארט
@@ -1987,7 +1988,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 +2194,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',
index c8172dc..1e5ade2 100644 (file)
@@ -1465,8 +1465,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.",
@@ -1639,7 +1639,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:',
@@ -1759,6 +1759,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',
@@ -2087,7 +2090,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',
index 636e841..443952b 100644 (file)
@@ -1061,7 +1061,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 bef6c2f..f5d2e4b 100644 (file)
@@ -1063,7 +1063,7 @@ $2',
 'randompage-nopages' => '个只名字空间冇𠮶页面。',
 
 # Random redirect
-'randomredirect' => '随机重定向页面',
+'randomredirect' => '随机重定向',
 'randomredirect-nopages' => '个只名字空间冇重定向页面。',
 
 # Statistics
@@ -1438,7 +1438,7 @@ $1',
 'linkshere' => '下底𠮶页面链接到[[:$1]]:',
 'nolinkshere' => '冇页面链接到[[:$1]]。',
 'nolinkshere-ns' => '选正𠮶空间名内冇页面链接到[[:$1]]。',
-'isredirect' => '重定向页',
+'isredirect' => '重定向页',
 'istemplate' => '含到',
 'isimage' => '档案连结',
 'whatlinkshere-prev' => '先$1只',
@@ -1601,7 +1601,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 +2070,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 +2194,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..a65fd5b 100644 (file)
@@ -1623,7 +1623,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 +2092,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 +2216,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 798d108..360f335 100644 (file)
@@ -235,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',
@@ -281,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',
@@ -365,6 +366,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.",
@@ -398,6 +405,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.",
@@ -425,6 +433,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\'\'".',
@@ -441,16 +453,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.',
@@ -462,18 +484,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.
@@ -516,12 +564,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.',
@@ -531,7 +579,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.
@@ -539,10 +587,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.',
@@ -558,8 +608,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',
@@ -567,11 +616,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?",
@@ -594,7 +647,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',
@@ -608,6 +661,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',
@@ -690,7 +756,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).
@@ -799,7 +865,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.'''
@@ -815,6 +881,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',
@@ -842,10 +909,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',
@@ -883,30 +969,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
@@ -916,6 +1102,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)',
 
@@ -1001,6 +1188,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',
@@ -1008,16 +1198,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',
@@ -1028,6 +1222,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',
@@ -1051,10 +1247,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.
@@ -1065,7 +1261,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',
@@ -1073,6 +1271,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
@@ -1348,9 +1547,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
@@ -1515,7 +1716,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',
@@ -1634,7 +1835,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 40c829b..cad9edd 100644 (file)
@@ -561,7 +561,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',
@@ -711,7 +711,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}}.
@@ -791,8 +791,9 @@ Para evitar o abuso do sistema só se enviará unha mensaxe de restablecemento c
 '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.
@@ -1233,19 +1234,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:',
@@ -2964,7 +2966,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 [https://www.mediawiki.org/wiki/Localisation localización 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:',
@@ -3127,6 +3129,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 */',
@@ -3191,6 +3194,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',
@@ -3276,7 +3280,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',
@@ -3745,7 +3749,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' => '(Vexa as seguintes [https://www.mediawiki.org/wiki/Manual:External_editors instrucións] <small>(en inglés)</small> para obter máis información)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'todo',
@@ -3937,7 +3941,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 © 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]].',
diff --git a/languages/messages/MessagesGom_latn.php b/languages/messages/MessagesGom_latn.php
new file mode 100644 (file)
index 0000000..6b20bea
--- /dev/null
@@ -0,0 +1,752 @@
+<?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' => '(Thollachea) 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.',
+'newmessageslink' => 'nove sondex',
+'newmessagesdifflink' => 'nimannem bodlop',
+'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' => '{{PLURAL:$1|$1 pan tujea sadurvollerint asa|$1 panam tujea sadurvollerint asat}} , ulovpachim panam meznastanam.',
+'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',
+
+# 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' => 'Akhi bariksai',
+
+# 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:',
+
+);
index f1161fd..7722ab4 100644 (file)
@@ -2443,7 +2443,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 6716266..5c0ac14 100644 (file)
@@ -2595,7 +2595,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:',
@@ -3314,7 +3314,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',
@@ -3494,7 +3494,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.
index 864ffa5..9956a5f 100644 (file)
@@ -2815,7 +2815,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' => 'સ્થાનીયકરણ સ્થિતિ દ્વારા ચાળો',
@@ -3550,7 +3550,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' => 'બધા',
@@ -3731,7 +3731,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 ને કે તે પછીના સંસ્કરણ   મઠારી શકો છો . 
@@ -3829,7 +3829,7 @@ $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' => '(ડેટાબેઝ સર્વર સાથે જોડાણ થઇ શકતું નથી)',
index 1e2aafe..b0453c8 100644 (file)
@@ -1410,7 +1410,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',
index 770bd89..45f83cd 100644 (file)
@@ -13,6 +13,7 @@
  * @author Jetlag
  * @author Mnemonic kek
  * @author Urhixidur
+ * @author Xiaomingyan
  */
 
 $messages = array(
@@ -1643,7 +1644,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 +1810,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 +1853,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..02a781d 100644 (file)
@@ -816,7 +816,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',
index aee4c07..c077337 100644 (file)
@@ -689,7 +689,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' => 'שגיאה',
@@ -820,7 +820,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}}.
@@ -898,8 +898,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' => 'כתובת הדוא"ל אינה מתקבלת כיוון שנראה שהיא בפורמט לא נכון.
@@ -986,7 +986,7 @@ $2
 
 # Special:ChangeEmail
 'changeemail' => 'שינוי כתובת דוא"ל',
-'changeemail-header' => 'שינוי כתוב דוא"ל של חשבון',
+'changeemail-header' => 'שינוי כתובת הדואר האלקטרוני בחשבון',
 'changeemail-text' => 'מלאו טופס זה כדי לשנות את כתובת הדואר האלקטרוני שלכם. יהיה עליכם למלא סיסמה כדי לאשר את השינוי.',
 'changeemail-no-info' => 'עליכם להיכנס לחשבון כדי לגשת לדף זה ישירות.',
 'changeemail-oldemail' => 'כתובת דוא"ל נוכחית:',
@@ -1021,7 +1021,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 +1332,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' => 'סיבה:',
@@ -1590,9 +1590,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' => 'השם האמיתי הוא אופציונאלי.
 אם תבחרו לספקו, הוא ישמש לייחוס עבודתכם אליכם.',
@@ -2248,7 +2248,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' => 'מתקן הפניות',
 
@@ -3283,6 +3284,7 @@ $2',
 'pageinfo-length' => 'אורך הדף (בבתים)',
 'pageinfo-article-id' => 'מזהה הדף',
 'pageinfo-language' => 'שפת התוכן של הדף',
+'pageinfo-content-model' => 'סוג התוכן של הדף',
 'pageinfo-robot-policy' => 'איסוף על ידי רובוטים של מנועי חיפוש',
 'pageinfo-robot-index' => 'מותר',
 'pageinfo-robot-noindex' => 'אסור',
@@ -3369,7 +3371,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> פיקסלים',
@@ -3842,7 +3844,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' => 'הכול',
@@ -4088,7 +4090,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|מדיה־ויקי]].',
index 9787c39..3e9137c 100644 (file)
@@ -2891,7 +2891,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' => 'अनुकूलन स्थिति के आधार पर छानें:',
@@ -3642,7 +3642,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' => 'सभी',
@@ -3879,7 +3879,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' => 'प्रोडक्ट',
index ac292cb..0119c38 100644 (file)
@@ -2714,7 +2714,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 +3464,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..064b746 100644 (file)
@@ -1240,7 +1240,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 +1417,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 +1884,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',
index aa32c73..0470ffc 100644 (file)
@@ -762,8 +762,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 +824,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 +852,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 +881,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.',
@@ -1443,7 +1448,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]].',
+'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:',
@@ -2899,7 +2904,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:',
@@ -3650,7 +3655,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',
@@ -3890,9 +3895,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.
index 42eeeb5..5f8f897 100644 (file)
@@ -2710,7 +2710,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ć:',
@@ -3467,7 +3467,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šě',
@@ -3646,7 +3646,7 @@ 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-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.
index c07491d..0360773 100644 (file)
@@ -1340,7 +1340,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 0795f8f..f2e50cd 100644 (file)
@@ -2264,7 +2264,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',
@@ -2905,7 +2905,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:',
@@ -3665,7 +3665,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',
@@ -3848,7 +3848,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.',
index aa7b289..b4c8d97 100644 (file)
@@ -1371,6 +1371,7 @@ $3 մասնակիցը տվել է հետևյալ պատճառը. ''$2''",
 'right-upload' => 'Նիշքերի բեռնում',
 'right-upload_by_url' => 'Բեռնել նիշքեր ինտերնետային հասցեից',
 'right-delete' => 'Էջերի ջնջում',
+'right-rollback' => 'Արագ հետ գլորել տվյալ էջը վերջին անգամ խմբագրած մասնակցի խմբագրումները',
 
 # Special:Log/newusers
 'newuserlogpage' => 'Մասնակիցների գրանցման տեղեկամատյան',
@@ -1390,6 +1391,7 @@ $3 մասնակիցը տվել է հետևյալ պատճառը. ''$2''",
 'action-delete' => 'Ջնջել այս էջը',
 'action-deleterevision' => 'Ջնջել այս փոփոխությունը',
 'action-deletedhistory' => 'Դիտել այս էջի ջնջված պատմությունը',
+'action-rollback' => 'արագ հետ գլորել էջը վերջին անգամ խմբագրած մասնակցի կատարած փոփոխությունները',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|փոփոխություն|փոփոխություն}}',
@@ -1905,11 +1907,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 +2272,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 +2566,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 d01a43c..9a9fc83 100644 (file)
@@ -14,6 +14,7 @@
  * @author McDutchie
  * @author Nemo bis
  * @author Reedy
+ * @author Shirayuki
  * @author Yfdyh000
  * @author לערי ריינהארט
  */
@@ -602,7 +603,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}}.
@@ -1136,18 +1137,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:',
@@ -1568,7 +1570,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',
@@ -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:',
@@ -3106,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',
@@ -3191,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',
@@ -3659,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',
@@ -3762,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 →',
@@ -3847,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]].',
index dd1a209..5795993 100644 (file)
@@ -3005,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:',
@@ -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]].',
index 0112545..ced2e20 100644 (file)
@@ -1287,7 +1287,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' => '(Vider li [https://www.mediawiki.org/wiki/Manual:External_editors instructiones de installation] por plu information)',
 
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'omni',
index d80520c..bd009a8 100644 (file)
@@ -1607,7 +1607,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',
index 1d502cb..269d0d2 100644 (file)
@@ -495,7 +495,7 @@ 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}}.
@@ -568,16 +568,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.
@@ -1030,15 +1030,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:',
@@ -2759,7 +2759,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:',
@@ -2951,7 +2951,7 @@ Daytoy ket mabalin a gapuanan babaen ti silpo a naiparit ti akin ruar a pagsaada
 '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''' mo a suratan daytoy!",
+ '''Saan''' a suratan daytoy!",
 
 # Info page
 'pageinfo-title' => 'Pakaammo para iti "$1"',
@@ -2965,6 +2965,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',
@@ -2985,7 +2986,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',
@@ -3507,7 +3508,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',
@@ -3696,7 +3697,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]].',
@@ -3715,7 +3716,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:',
index 0626ea7..282416e 100644 (file)
@@ -1088,7 +1088,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..0c01f9a 100644 (file)
@@ -1304,7 +1304,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
index 8b76026..b8d340d 100644 (file)
@@ -377,7 +377,7 @@ $messages = array(
 '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.',
@@ -480,7 +480,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',
@@ -562,6 +562,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
@@ -650,6 +651,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',
@@ -682,10 +684,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:',
@@ -694,6 +701,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}}',
@@ -763,10 +771,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ð.',
@@ -783,7 +792,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',
@@ -838,6 +847,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',
@@ -1017,7 +1038,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.'''
@@ -1076,6 +1097,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',
@@ -1104,7 +1126,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)',
 
@@ -1168,15 +1190,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:',
@@ -1258,6 +1280,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.
@@ -1359,7 +1382,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',
@@ -1415,10 +1438,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.
@@ -1432,7 +1455,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',
@@ -1440,7 +1465,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.',
@@ -1464,9 +1491,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:',
@@ -1532,13 +1561,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',
@@ -1590,8 +1625,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',
@@ -1600,12 +1635,19 @@ 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',
@@ -1633,7 +1675,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"',
 
@@ -1653,8 +1695,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',
@@ -1893,8 +1934,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',
@@ -1905,6 +1945,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á',
@@ -2001,6 +2045,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“.',
@@ -2026,6 +2077,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',
@@ -2085,6 +2140,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',
@@ -2100,6 +2156,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',
@@ -2529,7 +2586,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):',
@@ -2838,7 +2895,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:',
@@ -3035,8 +3092,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!',
+'simpleantispam-label' => "Kæfuvörn.
+'''EKKI''' fylla þetta út!",
 
 # Info page
 'pageinfo-title' => 'Upplýsingar um $1',
@@ -3051,12 +3108,12 @@ Ekki fylla þetta út!',
 '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',
@@ -3362,6 +3419,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',
@@ -3565,7 +3623,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',
@@ -3732,7 +3790,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.
 
@@ -3804,7 +3862,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}}',
 
@@ -3825,6 +3886,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.',
@@ -3960,4 +4022,8 @@ 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}}',
+
 );
index 4ad178b..2870a74 100644 (file)
@@ -311,7 +311,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',
@@ -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}}.
@@ -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:',
@@ -2906,7 +2907,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:',
@@ -3130,6 +3131,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',
@@ -3209,7 +3211,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',
@@ -3686,7 +3688,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',
@@ -3785,6 +3787,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',
@@ -3879,7 +3882,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]].',
index 7e49604..d1c5047 100644 (file)
@@ -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}} として既にログインしています。
@@ -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' => '入力されたメールアドレスが正しい形式に従っていないため、受け付けられません。
@@ -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' => '理由:',
@@ -3128,7 +3128,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 +3295,7 @@ $2',
 'tooltip-undo' => '「取り消し」はこの編集を差し戻し、編集画面をプレビュー付きで開きます。要約欄に理由を追加できます。',
 'tooltip-preferences-save' => '設定を保存する',
 'tooltip-summary' => '短い要約を入力してください',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* ここに記述したCSSはすべての外装に反映されます */',
@@ -3359,6 +3360,7 @@ $2',
 'pageinfo-length' => 'ページの長さ (バイト単位)',
 'pageinfo-article-id' => 'ページ ID',
 'pageinfo-language' => 'ページ本文の言語',
+'pageinfo-content-model' => 'ページのコンテンツ モデル',
 'pageinfo-robot-policy' => 'ロボットによるインデックス作成',
 'pageinfo-robot-index' => '許可',
 'pageinfo-robot-noindex' => '不許可',
@@ -3447,7 +3449,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 ピクセル',
@@ -3974,7 +3976,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' => 'すべて',
@@ -4241,7 +4243,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]] に貢献した以下の人たちに感謝します。',
index a5f8339..8e7a041 100644 (file)
@@ -1067,7 +1067,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 82b4075..4fce946 100644 (file)
@@ -2543,7 +2543,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:',
@@ -3274,7 +3274,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',
@@ -3445,7 +3445,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.
index dfcdb94..16a1f90 100644 (file)
@@ -625,9 +625,10 @@ $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' => 'ელ. ფოსტის მისამართი (არასავალდებულო)',
@@ -688,16 +689,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' => 'ელ. ფოსტის მისამართი არ იქნა მიღებული, ვინაიდან იგი არასწორი ფორმატითაა წარმოდგენილი.
@@ -711,8 +712,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' => 'თქვენი მოთხოვნა გასვლის შესახებ გაუქმებულია, რადგანაც იგი გავს ქეშირებადი პროქსის ან არაკორექტული ბრაუზერის მოთხოვნას.',
@@ -731,7 +732,7 @@ $2',
 'newpassword' => 'ახალი პაროლი:',
 'retypenew' => 'ახალი პაროლი განმეორებით:',
 'resetpass_submit' => 'მიუთითეთ პაროლი და დარეგისტრირდით',
-'changepassword-success' => 'თქვენი პაროლი წარმატებით შეიცვალა! ამჟამად რეგისტრირდებით...',
+'changepassword-success' => 'თქვენი პაროლი წარმატებით შეიცვალა!',
 'resetpass_forbidden' => 'პაროლის შეცვლა შეუძლებელია',
 'resetpass-no-info' => 'კონკრეტულად ამ გვერდთან სამუშაოდ თქვენ უნდა წარადგინოთ თავი სისტემისადმი.',
 'resetpass-submit-loggedin' => 'პაროლის შეცვლა',
@@ -744,7 +745,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' => 'ამ ვიკიში ელ.ფოსტის ფუნქციები გამორთულია.',
@@ -1009,7 +1010,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',
 
@@ -1133,15 +1134,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' => 'მიზეზი:',
@@ -1715,7 +1716,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' => 'ფაილების ატვირთვა შეუძლებელია.',
@@ -1975,6 +1976,7 @@ $1',
 'randompage-nopages' => '{{PLURAL:$2|სახელთა შემდეგი სივრცე|სახელთა შემდეგ სივრცეში}} "$1" არ არის გვერდები.',
 
 # Random page in category
+'randomincategory' => 'კატეგორიის შემთხვევითი გვერდი',
 'randomincategory-invalidcategory' => 'კატეგორია „$1“ არ არსებობს.',
 'randomincategory-selectcategory-submit' => 'მიდი',
 
@@ -2512,7 +2514,7 @@ $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' => 'მომხმარებელი {{GENDER:$3|$1}} წვლილი ($2)',
@@ -2822,7 +2824,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 +2985,7 @@ $2',
 'tooltip-undo' => 'შეტანილი ცვლილებების გაუქმება და წინასწარ გადახედვის ჩვენება, გაუქმების მიზეზის სქოლიოში ჩაწერასთან ერთად.',
 'tooltip-preferences-save' => 'შეინახეთ კონფიგურაცია',
 'tooltip-summary' => 'შეიყვანეთ მოკლე სქოლიო',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/** აქ ჩასმული CSS გამოყენებული იქნება გაფორმების ყველა გარეკანზე */',
@@ -3632,7 +3634,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' => 'ყველა',
@@ -3693,20 +3695,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' => 'ელ-ფოსტის დადასტურების გაუქმება',
 
@@ -3858,7 +3858,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|მედიავიკის]] განვითარებაში.',
@@ -4099,6 +4099,7 @@ 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|ბაიტი}}',
index b1314d1..dc1d76a 100644 (file)
@@ -1644,7 +1644,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",
@@ -1804,7 +1804,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..c04f0f2 100644 (file)
@@ -2302,7 +2302,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 +2811,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..a22498a 100644 (file)
@@ -1338,7 +1338,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..8277cb3 100644 (file)
@@ -1074,8 +1074,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 36c0437..9f16402 100644 (file)
@@ -8,6 +8,7 @@
  * @file
  *
  * @author Erdemaslancan
+ * @author Gorizon
  * @author Mirzali
  */
 
@@ -280,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',
@@ -1501,7 +1502,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',
index 0e98531..5546a2a 100644 (file)
@@ -2121,7 +2121,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 +2606,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 8163914..2949e7a 100644 (file)
@@ -1027,7 +1027,7 @@ IP-мекенжайыңыз бұл беттің түзету тарихында
 'blockednoreason' => 'еш себебі келтірілмеген',
 'whitelistedittext' => 'Беттерді өңдеу үшін сізде $1 болуы керек.',
 'confirmedittext' => 'Беттерді өңдеу үшін алдын ала Е-пошта мекенжайыңызды құптауыңыз жөн.
-Е-пошта мекенжайыңызды [Special:Preferences}}|қатысушы бапталымдарыңыз]] арқылы қойыңыз да жарамдылығын тексеріп шығыңыз.',
+Е-пошта мекенжайыңызды [[Special:Preferences|қатысушы бапталымдарыңыз]] арқылы қойыңыз да жарамдылығын тексеріп шығыңыз.',
 'nosuchsectiontitle' => 'Бұл бөлімді табу мүмкін емес',
 'nosuchsectiontext' => 'Сіз бұрын болмаған бөлімді өзгертпекшісіз.
 Мүмкін бұл бетті қарап жатқаныңызда ол бөлім жойылған немесе басқа орынға көшірілген.',
@@ -2751,7 +2751,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 +3403,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 67e7cf7..cf4bae8 100644 (file)
@@ -2085,7 +2085,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 +2569,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',
index 41360e7..d918602 100644 (file)
@@ -3446,7 +3446,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 +3639,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' => 'ផលិតផល',
index 060371e..914a663 100644 (file)
@@ -2042,7 +2042,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 e7feecc..092a8d8 100644 (file)
@@ -520,7 +520,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,7 +535,7 @@ $messages = array(
 'returnto' => '$1 문서로 돌아갑니다.',
 'tagline' => '{{SITENAME}}',
 'help' => '도움말',
-'search' => '찾기',
+'search' => '검색',
 'searchbutton' => '찾기',
 'go' => '보기',
 'searcharticle' => '보기',
@@ -586,7 +586,7 @@ $messages = array(
 'protectedpage' => '보호된 문서',
 'jumpto' => '이동:',
 'jumptonavigation' => '둘러보기',
-'jumptosearch' => '찾기',
+'jumptosearch' => '검색',
 'view-pool-error' => '서버가 과부하에 걸렸습니다.
 너무 많은 사용자가 이 문서를 보려고 하고 있습니다.
 이 문서를 다시 열기 전에 잠시만 기다려주세요.
@@ -810,7 +810,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로 로그인되어 있습니다. 아래의 양식으로 다른 계정으로 로그인하세요.',
@@ -887,7 +887,7 @@ $2',
 'mailerror' => '메일 보내기 오류: $1',
 'acct_creation_throttle_hit' => '당신의 IP 주소를 이용한 방문자가 이전에 이미 {{PLURAL:$1|계정 $1개}}를 만들어, 계정 만들기 한도를 초과하였습니다.
 따라서 지금은 이 IP 주소로는 더 이상 계정을 만들 수 없습니다.',
-'emailauthenticated' => '이메일 주소는 $2 $3에 인증되었습니다.',
+'emailauthenticated' => '이메일 주소는 $2 에 $3 에서 인증되었습니다.',
 'emailnotauthenticated' => '이메일 주소를 인증하지 않았습니다.
 이메일 확인 절차를 거치지 않으면 다음 이메일 기능을 사용할 수 없습니다.',
 'noemailprefs' => '이 기능을 사용하기 위해서는 사용자 환경 설정에서 이메일 주소를 설정해야 합니다.',
@@ -1088,11 +1088,11 @@ $1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대
 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 +1285,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 +1339,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 +1438,11 @@ $1",
 자세한 내용은 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 삭제 기록]에서 확인할 수 있습니다.',
 
 # Search results
-'searchresults' => '찾기 결과',
+'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'''",
+'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,7 +1454,7 @@ $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|이 접두어로 시작하는 문서 찾기]]',
@@ -1463,11 +1463,11 @@ $1",
 'searchprofile-images' => '멀티미디어',
 'searchprofile-everything' => '모든 문서 찾기',
 'searchprofile-advanced' => '고급',
-'searchprofile-articles-tooltip' => '$1에서 찾기',
+'searchprofile-articles-tooltip' => '$1에서 검색',
 'searchprofile-project-tooltip' => '$1에서 찾기',
-'searchprofile-images-tooltip' => '파일 찾기',
+'searchprofile-images-tooltip' => '파일 검색',
 'searchprofile-everything-tooltip' => '토론 문서를 포함한 모든 문서 찾기',
-'searchprofile-advanced-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,27 +1478,27 @@ $1",
 'search-interwiki-default' => '$1 결과:',
 'search-interwiki-more' => '(더 보기)',
 'search-relatedarticle' => '관련',
-'mwsuggest-disable' => '찾기 제안 비활성화',
+'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:''' 어떤 이름공간을 위해서는 접두어로 그 이름공간을 쓸 수 있습니다.",
+'nonefound' => "'''참고''': 몇개의 이름공간만 기본으로 검색하는 범위입니다. 토론이나 틀 등의 모든 자료를 검색하려면 접두어로 '''all:''' 어떤 이름공간을 위해서는 접두어로 그 이름공간을 쓸 수 있습니다.",
 'search-nonefound' => '찾기 결과가 없습니다.',
-'powersearch' => '고급 찾기',
+'powersearch' => '고급 검색',
 'powersearch-legend' => '고급 찾기',
-'powersearch-ns' => '다음 이름공간에서 찾기:',
+'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-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
@@ -1535,7 +1535,7 @@ $1",
 'prefs-editing' => '편집 상자',
 'rows' => '줄 수:',
 'columns' => '열 수:',
-'searchresultshead' => '찾기',
+'searchresultshead' => '검색',
 'resultsperpage' => '쪽마다 보이는 결과 수:',
 'stub-threshold' => '링크를 <a href="#" class="stub">토막글</a> 형식으로 보여줄 문서 크기 (바이트 수):',
 'stub-threshold-disabled' => '비활성화됨',
@@ -1565,9 +1565,9 @@ $1",
 'timezoneregion-indian' => '인도양',
 'timezoneregion-pacific' => '태평양',
 'allowemail' => '다른 사용자가 보낸 이메일을 받음',
-'prefs-searchoptions' => '찾기',
+'prefs-searchoptions' => '검색',
 'prefs-namespaces' => '이름공간',
-'defaultns' => '다음 이름공간에서 찾기:',
+'defaultns' => '다음 이름공간에서 검색:',
 'default' => '기본값',
 'prefs-files' => '파일',
 'prefs-custom-css' => '사용자 CSS',
@@ -1659,7 +1659,7 @@ HTML 태그를 확인하세요.',
 'group-bot' => '봇',
 'group-sysop' => '관리자',
 'group-bureaucrat' => '사무관',
-'group-suppress' => '오버사이트',
+'group-suppress' => '기록보호자',
 'group-all' => '(모두)',
 
 'group-user-member' => '{{GENDER:$1|사용자}}',
@@ -1667,14 +1667,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 +1705,7 @@ HTML 태그를 확인하세요.',
 'right-deleterevision' => '문서의 특정 판을 삭제하고 되살리기',
 'right-deletedhistory' => '삭제된 문서의 내용을 제외한 역사를 보기',
 'right-deletedtext' => '삭제된 문서의 내용과 편집상의 차이를 보기',
-'right-browsearchive' => '삭제된 문서 찾기',
+'right-browsearchive' => '삭제된 문서 검색',
 'right-undelete' => '삭제된 문서 되살리기',
 'right-suppressrevision' => '관리자도 보지 못하도록 숨겨진 판을 검토하고 되살리기',
 'right-suppressionlog' => '숨겨진 기록을 보기',
@@ -1739,7 +1739,7 @@ HTML 태그를 확인하세요.',
 'right-patrolmarks' => '최근 바뀜에서 검토 표시를 보기',
 'right-unwatchedpages' => '주시되지 않은 문서 목록 보기',
 'right-mergehistory' => '문서의 역사를 합침',
-'right-userrights' => '모든 사용자의 권한 조정',
+'right-userrights' => '사용자의 모든 권한 조정',
 'right-userrights-interwiki' => '다른 위키의 사용자 권한을 조정',
 'right-siteadmin' => '데이터베이스를 잠그거나 잠금 해제',
 'right-override-export-depth' => '5단계로 링크된 문서를 포함하여 문서를 내보내기',
@@ -1773,7 +1773,7 @@ HTML 태그를 확인하세요.',
 'action-delete' => '이 문서 삭제하기',
 'action-deleterevision' => '이 판을 삭제',
 'action-deletedhistory' => '이 문서의 삭제된 기여의 역사 보기',
-'action-browsearchive' => '삭제된 문서 찾기',
+'action-browsearchive' => '삭제된 문서 검색',
 'action-undelete' => '이 문서 되살리기',
 'action-suppressrevision' => '이 숨겨진 판을 검토하고 되살릴',
 'action-suppressionlog' => '비공개 기록 보기',
@@ -1786,7 +1786,7 @@ HTML 태그를 확인하세요.',
 'action-autopatrol' => '자신의 편집을 검토된 것으로 표시할',
 'action-unwatchedpages' => '주시되지 않은 문서 목록 보기',
 'action-mergehistory' => '이 문서의 역사 합치기',
-'action-userrights' => '모든 사용자의 권한을 조정',
+'action-userrights' => '사용자의 모든 권한 조정',
 'action-userrights-interwiki' => '다른 위키의 사용자 권한을 조정',
 'action-siteadmin' => '데이터베이스를 잠그거나 잠금 해제하기',
 'action-sendemail' => '이메일 보내기',
@@ -1858,7 +1858,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 +2107,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 
 # Special:ListFiles
 'listfiles-summary' => '이 특수 문서는 모든 올려진 파일을 보여줍니다.',
-'listfiles_search_for' => '다음 이름을 가진 미디어 찾기:',
+'listfiles_search_for' => '다음 미디어 이름 검색:',
 'imgfile' => '파일',
 'listfiles' => '파일 목록',
 'listfiles_thumb' => '섬네일',
@@ -2197,7 +2197,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'filedelete-maintenance-title' => '파일을 삭제할 수 없습니다',
 
 # MIME search
-'mimesearch' => 'MIME 찾기',
+'mimesearch' => 'MIME 검색',
 'mimesearch-summary' => 'MIME 타입에 해당하는 파일을 찾습니다.
 다음 형태로 입력해주세요: 내용종류/하위종류, 예를 들어 <code>image/jpeg</code>',
 'mimetype' => 'MIME 종류:',
@@ -2354,7 +2354,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 
 # Book sources
 'booksources' => '책 찾기',
-'booksources-search-legend' => 'ì±\85 ì°¾ê¸°',
+'booksources-search-legend' => 'ì±\85 ì\9b\90본 ê²\80ì\83\89',
 'booksources-isbn' => 'ISBN:',
 'booksources-go' => '찾기',
 'booksources-text' => '아래의 목록은 새 책이나 중고 책을 판매하는 바깥 사이트로, 원하는 책의 정보를 얻을 수 있습니다.',
@@ -2368,7 +2368,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'alllogstext' => '{{SITENAME}}에서의 기록이 모두 나와 있습니다.
 기록 종류, 사용자 이름, 문서 이름을 선택해서 볼 수 있습니다. (대소문자를 구별합니다.)',
 'logempty' => '일치하는 항목이 없습니다.',
-'log-title-wildcard' => '다음 글로 시작하는 제목 찾기',
+'log-title-wildcard' => '다음 글로 시작하는 제목 검색',
 'showhideselectedlogentries' => '선택한 기록 항목 보이기/숨기기',
 
 # Special:AllPages
@@ -2410,10 +2410,10 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 'sp-deletedcontributions-contribs' => '기여',
 
 # Special:LinkSearch
-'linksearch' => '바깥 링크 찾기',
+'linksearch' => '바깥 링크 검색',
 'linksearch-pat' => '찾기 패턴:',
 'linksearch-ns' => '이름공간:',
-'linksearch-ok' => '찾기',
+'linksearch-ok' => '검색',
 'linksearch-text' => '"*.wikipedia.org"와 같이 와일드 카드를 사용할 수 있습니다.
 적어도 "*.org"와 같이 최상위 도메인을 입력해야 합니다.<br />
 지원하는 {{PLURAL:$2|프로토콜}}: <code>$1</code> (프로토콜을 지정하지 않을 때 기본값은 http://)',
@@ -2739,10 +2739,10 @@ $1',
 
 [[Special:Log/delete|삭제 기록]]에서 최근의 삭제와 되살리기 기록을 볼 수 있습니다.",
 'undelete-header' => '최근에 삭제한 문서에 대한 기록은 [[Special:Log/delete|여기]]에서 볼 수 있습니다.',
-'undelete-search-title' => '삭제된 문서 찾기',
+'undelete-search-title' => '삭제된 문서 검색',
 'undelete-search-box' => '삭제된 문서 찾기',
 'undelete-search-prefix' => '다음으로 시작하는 문서 보기:',
-'undelete-search-submit' => '찾기',
+'undelete-search-submit' => '검색',
 'undelete-no-results' => '삭제된 문서 보존에서 일지하는 문서를 찾을 수 없습니다.',
 'undelete-filename-mismatch' => '타임스탬프가 $1인 파일의 버전을 되살릴 수 없습니다: 파일 이름이 일치하지 않습니다.',
 'undelete-bad-store-key' => '타임스탬프가 $1인 파일의 버전을 되살릴 수 없습니다: 파일이 삭제되기 전에 사라졌습니다.',
@@ -2768,7 +2768,7 @@ $1',
 # Contributions
 'contributions' => '{{GENDER:$1|사용자}} 기여',
 'contributions-title' => '$1 사용자의 기여 목록',
-'mycontris' => '기여 목록',
+'mycontris' => '기여',
 'contribsub2' => '{{GENDER:$3|$1}}($2)의 기여',
 'nocontribs' => '지정한 조건과 일치하는 바뀜을 찾을 수 없습니다.',
 'uctop' => '(최신)',
@@ -2788,10 +2788,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
@@ -2879,7 +2879,7 @@ $1',
 'blocklist-by' => '차단한 관리자',
 'blocklist-params' => '차단 설정',
 'blocklist-reason' => '이유',
-'ipblocklist-submit' => '찾기',
+'ipblocklist-submit' => '검색',
 'ipblocklist-localblock' => '로컬 차단',
 'ipblocklist-otherblocks' => '다른 {{PLURAL:$1|차단}} 기록',
 'infiniteblock' => '무기한',
@@ -3085,7 +3085,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' => '수정 상태로 거르기:',
@@ -3190,7 +3190,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 +3207,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 +3252,7 @@ $2',
 'tooltip-undo' => '"편집 취소" 기능을 사용하면 이 편집이 되돌려지고 차이 보기 기능이 미리 보기 형식으로 나타납니다. 편집 요약에 이 편집을 왜 되돌리는지에 대한 이유를 쓸 수 있습니다.',
 'tooltip-preferences-save' => '환경 설정 저장하기',
 'tooltip-summary' => '짧은 요약을 적어주세요',
-'tooltip-iwiki' => '$2 - $1',
+'interlanguage-link-title' => '$2 - $1',
 
 # Stylesheets
 'common.css' => '/* 이 CSS 설정은 모든 스킨에 동일하게 적용됩니다 */',
@@ -3317,6 +3317,7 @@ $2',
 'pageinfo-length' => '문서 길이 (바이트)',
 'pageinfo-article-id' => '문서 ID',
 'pageinfo-language' => '문서 내용 언어',
+'pageinfo-content-model' => '문서 콘텐츠 모델',
 'pageinfo-robot-policy' => '로봇에 의한 색인',
 'pageinfo-robot-index' => '허용됨',
 'pageinfo-robot-noindex' => '불허됨',
@@ -3424,7 +3425,7 @@ $1',
 'newimages-label' => '파일 이름 (또는 그 일부분):',
 'showhidebots' => '(봇을 $1)',
 'noimages' => '그림이 없습니다.',
-'ilsubmit' => '찾기',
+'ilsubmit' => '검색',
 'bydate' => '날짜',
 'sp-newimages-showfrom' => '$1 $2부터 올라온 파일 목록 보기',
 
@@ -3883,7 +3884,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' => '모두',
@@ -4073,7 +4074,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|미디어위키]]에 기여한 다음 사람한테 감사드립니다.',
@@ -4094,7 +4095,7 @@ $5
 # 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' => '값:',
@@ -4104,11 +4105,11 @@ $5
 'redirect-not-exists' => '값을 찾을 수 없습니다',
 
 # Special:FileDuplicateSearch
-'fileduplicatesearch' => '중복된 파일 찾기',
+'fileduplicatesearch' => '중복된 파일 검색',
 'fileduplicatesearch-summary' => '파일 해시값을 이용해 중복 파일을 찾습니다.',
-'fileduplicatesearch-legend' => '중복 찾기',
+'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개}} 있습니다.',
@@ -4201,7 +4202,7 @@ $5
 'htmlform-chosen-placeholder' => '선택하세요',
 
 # SQLite database support
-'sqlite-has-fts' => '$1 (본문 전체 찾기)',
+'sqlite-has-fts' => '$1 (본문 전체 검색 지원)',
 'sqlite-no-fts' => '$1 (본문은 찾기에서 제외)',
 
 # New logging system
@@ -4257,7 +4258,7 @@ $5
 'feedback-bugnew' => '확인했습니다. 새로운 버그 보고서를 작성합니다.',
 
 # Search suggestions
-'searchsuggest-search' => '찾기',
+'searchsuggest-search' => '검색',
 'searchsuggest-containing' => '다음 문자열 포함...',
 
 # API errors
index ab8c0d5..1901e4a 100644 (file)
@@ -742,7 +742,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..55362a7 100644 (file)
@@ -2583,7 +2583,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 +3279,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 +3506,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 лицензияны (эркин программа джазыуланы фонду чыгъаргъан; экинчи версиясы неда андан кеч къайсысы да) шартларына кёре джаяргъа эмда/неда тюрлендирирге боллукъсуз.
 
index a9e2266..81cddc3 100644 (file)
@@ -431,7 +431,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 +461,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',
@@ -685,7 +685,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 +774,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 +808,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 +826,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 +839,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 +893,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 +1139,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 +1166,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 +1359,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.
@@ -1637,6 +1649,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 +1704,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,14 +1714,19 @@ 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',
@@ -2538,10 +2559,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 +3047,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:',
@@ -3824,7 +3847,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',
@@ -4076,7 +4099,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:',
index 09da332..85b773f 100644 (file)
@@ -2025,7 +2025,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û',
index bac3319..0926c66 100644 (file)
@@ -1676,7 +1676,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..ac5d7bb 100644 (file)
@@ -824,12 +824,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 +898,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%',
@@ -1145,6 +1147,7 @@ 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',
 '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 +1449,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 +1476,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 +1719,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 +2294,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 +2430,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',
index e33bc4d..af5e5eb 100644 (file)
@@ -1177,7 +1177,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 71e57d2..1d37a10 100644 (file)
@@ -517,8 +517,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',
@@ -641,7 +641,7 @@ Vergiesst net fir Är [[Special:Preferences|{{SITENAME}} Astellungen]] z'ännere
 '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.
@@ -716,8 +716,8 @@ 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.',
 '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.
@@ -1142,18 +1142,19 @@ Dir kënnt dësen Ënnerscheed gesinn; Detailer fannt Dir am [{{fullurl:{{#Speci
 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-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:',
@@ -1450,7 +1451,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
@@ -1863,7 +1864,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",
@@ -2215,9 +2216,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
@@ -2839,7 +2840,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:',
@@ -3002,7 +3003,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''  */",
@@ -3052,6 +3053,7 @@ Fëllt dëst '''NET''' aus!",
 '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',
@@ -3137,7 +3139,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',
@@ -3319,7 +3321,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',
@@ -3596,7 +3598,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',
@@ -3683,6 +3685,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 →',
@@ -3768,7 +3773,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]].",
index df854b8..96e0bf8 100644 (file)
@@ -1266,7 +1266,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..bf8f3fc 100644 (file)
@@ -930,7 +930,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',
index da02d48..b7bcdf1 100644 (file)
@@ -1190,7 +1190,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 +1309,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 3c042be..4613789 100644 (file)
@@ -2596,7 +2596,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:',
@@ -3278,7 +3278,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',
@@ -3458,7 +3458,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.
 
index 2bd36f8..af13d6a 100644 (file)
@@ -1389,7 +1389,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..5418d93 100644 (file)
@@ -732,7 +732,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..bf2409b 100644 (file)
@@ -1325,7 +1325,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..8d95c64 100644 (file)
@@ -899,7 +899,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' => 'ທັງໝົດ',
index 0fafbb0..ae71cc6 100644 (file)
@@ -881,7 +881,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 +1011,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',
index 1c977f1..1b75b37 100644 (file)
@@ -2766,7 +2766,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ą:',
@@ -3522,7 +3522,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',
@@ -3710,7 +3710,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. 
index 558d6c0..564afea 100644 (file)
@@ -865,7 +865,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..a330310 100644 (file)
@@ -1858,7 +1858,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 f636b64..61382cb 100644 (file)
@@ -1058,11 +1058,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 +1088,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 +1112,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 +1127,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',
@@ -2353,7 +2357,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:',
@@ -2932,7 +2936,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',
@@ -3075,7 +3079,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]].',
index c57b0a5..086b5c5 100644 (file)
@@ -2327,7 +2327,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 +2637,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 +2789,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通用公共授權之款,就此本程序再發佈及/或修;依之二版(自選之)或後之。
 
index 70e2146..ebdea94 100644 (file)
@@ -2456,7 +2456,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 +3147,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 +3333,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' => 'मीडियाविकी एकटा मंगनीक तंत्रांश अछि; अहाँ एकरा बाँटि सकै छी आ/ वा संशोधित कऽ सकै छीगी.एन.यू. सामान्य जन लाइसेन्सक अन्तर्गत जेना फ्री सॉफ्टवेयर फाउन्डेशन एकरा प्रकाशित केने अछि; चाहे तँ लाइसेन्सक संस्करण २, वा (अहाँक विकल्पपर) कोनो बादक दोसर संस्करणक अन्तर्गत।
 
index d128bd8..3456f0a 100644 (file)
@@ -1821,7 +1821,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..562ac85 100644 (file)
@@ -2148,7 +2148,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 +2647,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 5386a66..0b2db54 100644 (file)
@@ -2827,7 +2827,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 :',
@@ -3370,7 +3370,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',
index 5952fe5..aa005f6 100644 (file)
@@ -230,7 +230,7 @@ $messages = array(
 'errorpagetitle' => 'Йоҥылыш',
 'returnto' => '$1 деке пӧртылаш.',
 'tagline' => '{{SITENAME}} гыч',
-'help' => 'Полшык',
+'help' => 'Полшыш',
 'search' => 'Кычалмаш',
 'searchbutton' => 'Кычалаш',
 'go' => 'Куснаш',
@@ -262,7 +262,7 @@ $messages = array(
 'userpage' => 'Пайдаланышын лаштыкым ончалаш',
 'imagepage' => 'Файлын лаштыкым ончалаш',
 'templatepage' => 'Ямдылыкын лаштыкым ончалаш',
-'viewhelppage' => 'Ð\9fолÑ\88Ñ\8bк лаштыкым ончалаш',
+'viewhelppage' => 'Ð\9fолÑ\8bÑ\88 лаштыкым ончалаш',
 'categorypage' => 'Категорийын лаштыкым ончалаш',
 'viewtalkpage' => 'Ончалаш каҥашымашым',
 'otherlanguages' => 'Вес йылме дене',
@@ -333,6 +333,7 @@ $messages = array(
 
 # General errors
 'error' => 'Йоҥылыш',
+'databaseerror-error' => 'Йоҥылыш: $1',
 'missing-article' => 'Тыгай текст дене возымо лаштык базыште муалтын огыл, "$1" $2.
 
 Кунам тый тоштемше кылвер почеш шӧрымӧ вашталтымаш лаштыкыш (але эртымгорно лаштыкыш) куснет, тыге лийын кертеш.
@@ -355,24 +356,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|регистрацийым эрте]].',
@@ -997,7 +1004,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 +1027,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 +1101,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 1d804d0..14004dc 100644 (file)
@@ -2470,7 +2470,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',
@@ -2528,7 +2528,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.
index fa50c49..db21975 100644 (file)
@@ -811,7 +811,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}}.
@@ -887,7 +887,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' => 'Наведете е-поштенска адреса за да функционираат следниве својства.',
@@ -1334,19 +1334,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' => 'Причина:',
@@ -3079,7 +3080,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' => 'Филтрирај по состојба на прилагодувањето:',
@@ -3244,7 +3245,7 @@ $2',
 'tooltip-undo' => '„Откажи“ го поништува ова уредување и ве носи на уредувањето во режим на преглед. Дава можност за наведување на причина во описот.',
 'tooltip-preferences-save' => 'Зачувај',
 'tooltip-summary' => 'Внесете краток опис',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/* Тука поставениот CSS ќе се применува врз сите рува */',
@@ -3309,6 +3310,7 @@ $2',
 'pageinfo-length' => 'Должина на страницата (во бајти)',
 'pageinfo-article-id' => 'Назнака на страницата',
 'pageinfo-language' => 'Јазик на содржината на страницата',
+'pageinfo-content-model' => 'Модел на содржината на страницата',
 'pageinfo-robot-policy' => 'Индексирање со роботи',
 'pageinfo-robot-index' => 'Дозволено',
 'pageinfo-robot-noindex' => 'Недозволено',
@@ -3397,7 +3399,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 +3931,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 +4037,7 @@ $5
 
 # Separators for various lists, etc.
 'percent' => '$1&#160;%',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '&larr; претходна страница',
@@ -4205,7 +4208,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|МедијаВики]].',
index 89621fd..9df99a7 100644 (file)
@@ -8,6 +8,7 @@
  * @file
  *
  * @author Abhishek Jacob
+ * @author Akhilan
  * @author Anoopan
  * @author Chrisportelli
  * @author Deepugn
@@ -796,7 +797,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}} ആയി പ്രവേശിച്ചിരിക്കുന്നു.
@@ -860,8 +861,8 @@ $2',
 '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 +1286,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' => 'കാരണം:',
@@ -2169,6 +2170,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization കാണുക.',
 
 'pageswithprop' => 'താളിന്റെ സവിശേഷതകളുള്ള താളുകൾ',
 'pageswithprop-legend' => 'ഒരു താൾ സവിശേഷതയുള്ള താളുകൾ',
+'pageswithprop-prop' => 'ഗുണം:',
 'pageswithprop-submit' => 'പോകൂ',
 
 'doubleredirects' => 'ഇരട്ട തിരിച്ചുവിടലുകൾ',
@@ -2981,7 +2983,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' => 'പുനഃക്രമീകരിച്ച ക്രമത്തിൽ തിരഞ്ഞുവെയ്ക്കുക:',
@@ -3205,6 +3207,7 @@ $1',
 'pageinfo-length' => 'താളിന്റെ നീളം (ബൈറ്റിൽ)',
 'pageinfo-article-id' => 'താളിന്റെ ഐ.ഡി.',
 'pageinfo-language' => 'താളിന്റെ ഉള്ളടക്കത്തിന്റെ ഭാഷ',
+'pageinfo-content-model' => 'താളിന്റെ ഉള്ളടക്ക രീതി',
 'pageinfo-robot-policy' => 'റോബോട്ടുകളുടെ സൂചികാവത്കരണം',
 'pageinfo-robot-index' => 'അനുവദിച്ചിരിക്കുന്നു',
 'pageinfo-robot-noindex' => 'അനുവദിച്ചിട്ടില്ല',
@@ -3290,7 +3293,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 പിക്സലുകൾ',
@@ -3943,7 +3946,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|മീഡിയവിക്കിയ്ക്ക്]] നൽകിയ സംഭാവനകളുടെ പേരിൽ താഴെക്കൊടുക്കുന്നവർക്ക് ഞങ്ങൾ നന്ദി പറയുന്നു.',
@@ -3964,7 +3967,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' => 'വില:',
index 04734d6..9e55b71 100644 (file)
@@ -856,8 +856,8 @@ $3-н тодорхойлсон шалтгаан нь ''$2''",
 (сүүлчийн) = өмнөх засвартай харьцуулах, Б = бага зэргийн засвар',
 'history-fieldset-title' => 'Түүх сөхөе',
 'history-show-deleted' => 'Зөвхөн устгагдсаныг',
-'histfirst' => 'Эхний',
-'histlast' => 'Сүүлийн',
+'histfirst' => 'хамгийн эхэнд',
+'histlast' => 'хамгийн шинэ',
 'historysize' => '($1 байт)',
 'historyempty' => '(хоосон байна)',
 
@@ -1649,6 +1649,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'listfiles_search_for' => 'Зургийн нэрээр хайх:',
 'imgfile' => 'файл',
 'listfiles' => 'Файлын жагсаалт',
+'listfiles_thumb' => 'товч агуулга',
 'listfiles_date' => 'Огноо',
 'listfiles_name' => 'Нэр',
 'listfiles_user' => 'Хэрэглэгч',
@@ -2243,7 +2244,7 @@ $1',
 'mycontris' => 'Оруулсан хувь нэмэр',
 'contribsub2' => 'Хэрэглэгч: $1 ($2)',
 'nocontribs' => 'Энэ шалгуурт тохирох өөрчилсөн зүйлүүд олдсонгүй.',
-'uctop' => 'ï¼\88дÑ\8dÑ\8dд)',
+'uctop' => 'ï¼\88одооÑ\85)',
 'month' => 'Дараах сараас (өмнөх засварууд нь ч орно):',
 'year' => 'Дараах жилээс (өмнөх засварууд нь ч орно):',
 
@@ -2538,7 +2539,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' => 'Өөрийн болгосон байдлаар нь шүүх:',
@@ -3158,7 +3159,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 +3327,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' => 'Бүтээгдэхүүн',
index 7a462ba..1f61c7f 100644 (file)
@@ -563,7 +563,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 +593,13 @@ $1',
 
 'ok' => 'ठीक',
 'retrievedfrom' => '"$1" पासून हुडकले',
-'youhavenewmessages' => 'तुमच्यासाठी $1 ($2) आहे.',
+'youhavenewmessages' => 'तुमच्यासाठी $1 आहे. ($2)',
 'newmessageslink' => 'नवीन संदेश',
 'newmessagesdifflink' => 'ताजा बदल',
-'youhavenewmessagesfromusers' => 'à¤\86पलà¥\87पाशà¥\80  $1à¤\9aà¥\8dया à¤ªà¤¾à¤¸à¥\82न  {{PLURAL:$3|वà¥\87à¤\97ळà¥\87 à¤¸à¤¦à¤¸à¥\8dय|$3 à¤¸à¤¦à¤¸à¥\8dय}}($2)à¤\86हà¥\87त.',
-'youhavenewmessagesmanyusers' => ' आपलेपाशी ($2) सदस्यांपासून $1 आहेत.',
-'newmessageslinkplural' => '{{PLURAL:$1|a new message|नविन संदेश}}',
-'newmessagesdifflinkplural' => 'माà¤\97िल {{PLURAL:$1|बदल}}',
+'youhavenewmessagesfromusers' => 'तà¥\81मà¤\9aà¥\8dयासाठà¥\80 {{PLURAL:$3|à¤\87तर à¤¸à¤¦à¤¸à¥\8dयाà¤\95डà¥\82न|$3 à¤¸à¤¦à¤¸à¥\8dयाà¤\82à¤\95डà¥\82न}} $1 à¤\86हà¥\87त. ($2)',
+'youhavenewmessagesmanyusers' => 'तुमच्यासाठी बऱ्याच सदस्यांकडून $1 आहेत. ($2)',
+'newmessageslinkplural' => '{{PLURAL:$1|नवीन संदेश|नवीन संदेश}}',
+'newmessagesdifflinkplural' => 'माà¤\97à¥\80ल {{PLURAL:$1|बदल}}',
 'youhavenewmessagesmulti' => '$1 वर तुमच्यासाठी नवीन संदेश आहेत.',
 'editsection' => 'संपादन',
 'editold' => 'संपादन',
@@ -612,13 +612,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 +801,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' => 'खाते तयार करण्यात चुकी',
@@ -3670,7 +3670,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' => 'सर्व',
@@ -3846,7 +3846,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|मिडियाविकि]]वर त्यांनी दिलेल्या योगदानामुळे, मान्यता देऊ ईच्छितो.',
index dfef63f..8bd16fc 100644 (file)
@@ -2856,7 +2856,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:',
@@ -3618,7 +3618,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',
@@ -3809,7 +3809,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]].',
index a1bea2d..2b71c52 100644 (file)
@@ -3466,7 +3466,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 +3666,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.
 
index 8a3fb50..d2284fc 100644 (file)
@@ -1153,7 +1153,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..df5b28e 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' => 'အက္ခရာစဉ် စာမျက်နှာများမရှိ',
@@ -1783,7 +1783,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..4965feb 100644 (file)
@@ -2081,7 +2081,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' => 'весе',
index a9eba0c..432caf8 100644 (file)
@@ -208,7 +208,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',
index 042cd49..649b386 100644 (file)
@@ -785,7 +785,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 cd16f34..32cdeec 100644 (file)
@@ -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',
@@ -827,13 +827,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.',
@@ -1278,7 +1278,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',
@@ -1462,7 +1462,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 +1708,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',
@@ -1758,7 +1758,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 +2502,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.',
@@ -3735,7 +3737,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',
@@ -3938,7 +3940,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]].',
index b981c5a..e608014 100644 (file)
@@ -2859,7 +2859,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',
@@ -3003,7 +3003,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',
index a7dd270..75bf97a 100644 (file)
@@ -759,7 +759,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 +827,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 +1262,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:',
@@ -2953,7 +2953,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:',
@@ -3119,7 +3119,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.',
@@ -3160,6 +3160,7 @@ Hier '''NIKS''' invullen!",
 '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',
@@ -3712,7 +3713,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',
@@ -3801,6 +3802,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;',
@@ -3892,7 +3896,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]].',
@@ -3911,7 +3915,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:',
index 99a16bf..1696d05 100644 (file)
@@ -849,6 +849,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 कल्स छ्न्}}.",
@@ -952,10 +957,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' => '(परिवर्तन नगर्नुहोस्)',
@@ -1115,6 +1120,7 @@ $1",
 'prefs-beta' => 'बिटा गुणहरु',
 'prefs-datetime' => 'मिति र समय',
 'prefs-labs' => 'प्रयोगशाला गुणहरु',
+'prefs-user-pages' => 'प्रयोगकर्ता पृष्ठहरू',
 'prefs-personal' => 'प्रयोगकर्ताको विवरण',
 'prefs-rc' => 'नयाँ परिवर्तनहरु',
 'prefs-watchlist' => 'अवलोकन पृष्ठ',
@@ -1207,6 +1213,8 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 'prefs-dateformat' => 'मिति ढाँचा',
 'prefs-timeoffset' => 'समय अफसेट',
 'prefs-advancedediting' => 'सामान्य विकल्पहरू',
+'prefs-editor' => 'सम्पादक',
+'prefs-preview' => 'पूर्वावलोकन',
 'prefs-advancedrc' => 'उन्नत विकल्पहरू',
 'prefs-advancedrendering' => 'उन्नत विकल्पहरु',
 'prefs-advancedsearchoptions' => 'उन्नत विकल्पहरू',
@@ -1214,6 +1222,7 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 'prefs-displayrc' => 'प्रदर्शन विकल्पहरू',
 'prefs-displaysearchoptions' => 'प्रदर्शन विकल्पहरू',
 'prefs-displaywatchlist' => 'प्रदर्शन विकल्पहरू',
+'prefs-tokenwatchlist' => 'टोकन',
 'prefs-diffs' => 'diffs(भिन्नता)',
 
 # User preference: email validation using jQuery
@@ -1372,6 +1381,7 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|परिवर्तन|परिवर्तनहरु}}',
+'enhancedrc-history' => 'इतिहास',
 'recentchanges' => 'नयाँ परिवर्तनहरु',
 'recentchanges-legend' => 'हालैको परिवर्तन विकल्पहरु',
 'recentchanges-summary' => 'विकिका भर्खरका परिवर्तनहरुलाई यस पृष्ठमा पहिल्याउने',
@@ -1587,6 +1597,8 @@ $1',
 'listfiles_size' => 'आकार',
 'listfiles_description' => 'वर्णन',
 'listfiles_count' => 'संस्करणहरु',
+'listfiles-latestversion-yes' => 'हो',
+'listfiles-latestversion-no' => 'हैन',
 
 # File description page
 'file-anchor-link' => 'फाईल',
@@ -1901,7 +1913,7 @@ $1',
 'notanarticle' => 'सामाग्री सहितको पेज हैन',
 'notvisiblerev' => 'पूर्वावलोकन हटाइयो',
 'watchlist-details' => 'तपाईको निगरानी सूचीमा रहेका{{PLURAL:$1|$1 पृष्ठ|$1 पृष्ठहरु}}वार्तालापमा पृष्ठमा गनिएका छैनन् ।',
-'wlheader-enotif' => 'ईमेलद्वारा जानकारी गराउने तरिका सक्रिय गरियो ।',
+'wlheader-enotif' => 'ईमेल जानकारी सक्रिय गरियो ।',
 'wlheader-showupdated' => "तपाइले पछिल्लो पल्ट भ्रमण गरेपछि परिवर्तन भएका पृष्ठहरूलाई '''गाढा''' गरेर देखाइएको छ ।",
 'watchmethod-recent' => 'निगरानी सुचीमा रहेका पृष्ठमा गरिएका सम्पादनहरु जाँच्दै',
 'watchmethod-list' => 'सम्पदान गरिएका निगरानी सुचीमा रहेका पृष्ठहरुको सम्पादन जाँच्दै',
@@ -2399,7 +2411,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' => 'सबै',
@@ -3065,7 +3077,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' => 'सबै',
@@ -3316,7 +3328,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' => 'उत्पादन',
index 4ec34de..26ca5b4 100644 (file)
@@ -11,6 +11,7 @@
  * @author AvatarTeam
  * @author B4bol4t
  * @author Basvb
+ * @author Breghtje
  * @author DasRakel
  * @author Effeietsanders
  * @author Erwin
@@ -831,7 +832,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,8 +916,8 @@ Om misbruik te voorkomen wordt er slechts één wachtwoordherinnering per {{PLUR
 'acct_creation_throttle_hit' => 'Bezoekers van deze wiki met hetzelfde IP-adres als u hebben de afgelopen dag al $1 gebruiker{{PLURAL:$1||s}} geregistreerd, wat het maximale aantal in deze periode is.
 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.',
+'emailnotauthenticated' => 'Uw e-mailadres is niet nog bevestigd.
+Geen e-mail zal worden verzonden voor een van de volgende functies.',
 '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.
@@ -1213,7 +1214,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.
@@ -1360,18 +1361,19 @@ U kunt deze verschillen bekijken. Er kunnen details te vinden zijn in het [{{ful
 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:
+* Potentieel lasterlijke informatie
 * Ongepaste persoonlijke informatie
-*: ''woonadres, telefoonnummers, Burger Service Nummers, enzovoort.''",
+*: ''woonadres, telefoonnummers,  rijksrigisternummers, enzovoort.''",
 'revdelete-legend' => 'Zichtbaarheidsbeperkingen instellen',
-'revdelete-hide-text' => 'Bewerkte tekst verbergen',
+'revdelete-hide-text' => 'Herziening van de tekst',
 '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' => 'Wijzig samenvatting',
+'revdelete-hide-user' => 'bewerker gebruikersnaam/IP-adres',
 '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:',
@@ -1726,7 +1728,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',
@@ -1757,7 +1759,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",
@@ -1797,7 +1799,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',
@@ -1807,7 +1809,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',
@@ -3120,7 +3122,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:',
@@ -3286,7 +3288,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 */',
@@ -3437,7 +3439,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',
@@ -3477,13 +3479,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
@@ -3906,7 +3908,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',
@@ -4109,7 +4111,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]].',
index 47bc87c..c9b1158 100644 (file)
@@ -326,10 +326,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 +347,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',
@@ -763,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.',
@@ -1134,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]])',
@@ -1221,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',
@@ -1416,7 +1418,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',
@@ -1522,7 +1524,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',
 
@@ -1696,7 +1698,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»',
 
@@ -2056,7 +2058,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',
@@ -2165,9 +2167,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',
@@ -2568,7 +2570,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:',
@@ -2864,7 +2866,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:',
@@ -3073,13 +3075,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',
@@ -3419,7 +3421,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 +3627,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 +3807,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]].',
@@ -3912,7 +3914,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',
index 99cea76..c22a78b 100644 (file)
@@ -1214,7 +1214,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',
index bd206aa..f0b49e6 100644 (file)
@@ -745,7 +745,7 @@ 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}}.
@@ -811,13 +811,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.
@@ -1232,18 +1232,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 :',
@@ -1437,6 +1438,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 :',
@@ -1538,6 +1542,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 '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 :',
@@ -1612,6 +1617,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',
@@ -1688,6 +1694,7 @@ 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',
@@ -2099,6 +2106,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',
@@ -2853,6 +2861,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',
@@ -2875,6 +2884,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',
@@ -2890,7 +2900,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 :',
@@ -2909,6 +2919,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',
@@ -2954,6 +2966,8 @@ 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-options-wrong' => '{{PLURAL:$2|Marrida opcion|Marridas opcions}} : <nowiki>$1</nowiki>',
 'import-rootpage-invalid' => 'La pagina raiç provesida es un títol invalid.',
 
@@ -3097,6 +3111,7 @@ Inscriviscatz '''PAS RES''' dedins !",
 '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',
@@ -3181,7 +3196,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',
@@ -3651,7 +3666,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',
@@ -3747,6 +3762,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',
@@ -3836,7 +3852,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',
@@ -4026,18 +4042,27 @@ Ensajatz la previsualizacion normala.',
 'api-error-filetype-banned' => 'Aqueste tipe de fichièr es interdich',
 '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}}',
index 4d8a75b..b7bf46d 100644 (file)
@@ -2890,7 +2890,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' => 'ଆପଣା ପସନ୍ଦରେ ଛାଣିବେ:',
@@ -3633,7 +3633,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' => 'ସବୁ',
@@ -3817,7 +3817,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 ଜେନେରାଲ ପବ୍ଲିକ ଲାଇସେନ୍ସ ଅଧିନରେ ବଦଳାଇପାରିବେ ଯାହା ଫ୍ରି ସଫ୍ଟୱାର ଫାଉଣ୍ଡେସନ ଦେଇ ପ୍ରକାଶିତ ହୋଇଥିବ।
index c14f4d6..ead85ea 100644 (file)
@@ -1724,7 +1724,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 +1789,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' => 'Верси',
 
index 171475b..0273a49 100644 (file)
@@ -2547,7 +2547,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' => 'ਸਭ',
index 0788b05..6bbeaae 100644 (file)
@@ -2175,7 +2175,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..ff2e396 100644 (file)
@@ -1026,7 +1026,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',
index 4d12a58..8d65c50 100644 (file)
@@ -9,6 +9,7 @@
  *
  * @author Kaganer
  * @author Krinkle
+ * @author Shirayuki
  * @author Xqt
  * @author לערי ריינהארט
  */
index 9d774d0..606ff5c 100644 (file)
@@ -1181,7 +1181,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 54fe1db..f7240f0 100644 (file)
@@ -903,7 +903,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:}}
 
@@ -928,10 +928,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',
 
@@ -3003,7 +3003,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:',
@@ -3227,6 +3227,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',
@@ -3789,7 +3790,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',
@@ -3894,6 +3895,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',
@@ -4024,7 +4026,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]].',
@@ -4043,7 +4045,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 (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/103]].',
+'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ść:',
index b90b565..7971f98 100644 (file)
@@ -496,7 +496,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}}.
@@ -569,8 +569,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',
@@ -999,19 +999,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:',
@@ -2726,7 +2727,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:',
@@ -2939,6 +2940,7 @@ Compilé '''NEN''' sòn!",
 '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à',
@@ -3019,7 +3021,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',
@@ -3491,7 +3493,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',
@@ -3592,6 +3594,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 →',
@@ -3697,7 +3702,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]].',
index 01de94d..894c432 100644 (file)
@@ -2478,7 +2478,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' => 'فلٹر',
@@ -3162,7 +3162,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' => 'سارے',
@@ -3345,7 +3345,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 نال، یا اپنی مرضی نال کسے وی ہور ورین فیر بنن والے ورین نوں۔
 
index ad44e5a..36e3486 100644 (file)
@@ -1348,7 +1348,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..bcec2af 100644 (file)
@@ -1969,7 +1969,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 +2451,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',
index 6d9661d..5acaf75 100644 (file)
@@ -1483,6 +1483,9 @@ $1',
 'randompage' => 'ناټاکلی مخ',
 'randompage-nopages' => 'په لانديني {{PLURAL:$2|نوم-تشيال|نوم-تشيالونو}} کې هېڅ کوم مخ نشته: $1.',
 
+# Random page in category
+'randomincategory-selectcategory' => 'يو ناټاکلی مخ له وېشنيزې موندل: $1 $2.',
+
 # Random redirect
 'randomredirect' => 'ناټاکلی ورگرځېدنه',
 
@@ -1684,7 +1687,7 @@ $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' => 'ستاسو برېښليکي پيغام ولېږل شو.',
@@ -2092,7 +2095,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' => 'نابدلېدلي',
@@ -2484,7 +2487,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 +2565,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 +2646,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 د ټولگړو کارېدنو د منښتليک چې د وړيا ساوتريو د بنسټ له مخې خپور شوی، خپرولی او/يا بدلولی شی؛ د منښتليک ۲ بڼه او يا (ستاسې د خوښې) هر يوه وروستۍ بڼه.
 
index fbc2ded..68fd495 100644 (file)
@@ -1302,15 +1302,15 @@ Outros administradores da {{SITENAME}} continuarão a poder aceder ao conteúdo
 * Informação pessoal imprópria
 *: ''endereços de domicílio e números de telefone, números da segurança social, 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' => 'o',
+'revdelete-radio-set' => 'Visível',
+'revdelete-radio-unset' => 'Escondido',
 'revdelete-suppress' => 'Ocultar dados dos administradores e de todos os outros',
 'revdelete-unsuppress' => 'Remover restrições das revisões restauradas',
 'revdelete-log' => 'Motivo:',
@@ -1687,6 +1687,8 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 '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',
@@ -1751,6 +1753,10 @@ 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}}',
@@ -2171,6 +2177,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
@@ -2279,6 +2286,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',
@@ -3019,7 +3027,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:',
@@ -3794,7 +3802,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',
@@ -3987,7 +3995,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.
@@ -4005,7 +4013,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:',
@@ -4228,6 +4236,7 @@ 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}}',
index 16b0d6f..a7a93fa 100644 (file)
@@ -3014,7 +3014,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:',
@@ -3781,7 +3781,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',
@@ -3970,7 +3970,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]]',
index 9d58538..e361b93 100644 (file)
@@ -70,6 +70,7 @@
  * @author Lejonel
  * @author Li-sung
  * @author Liangent
+ * @author Liuxinyu970226
  * @author Lloffiwr
  * @author MF-Warburg
  * @author Malafaya
@@ -482,7 +483,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".
 
@@ -1341,7 +1343,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.
 
@@ -1521,7 +1524,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]].
 
@@ -2024,7 +2027,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.
@@ -2446,14 +2449,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:
@@ -3012,7 +3015,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:
@@ -3029,7 +3033,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}}',
@@ -4476,7 +4481,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}}',
@@ -5907,6 +5913,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}}',
@@ -7838,7 +7845,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',
 
@@ -8006,6 +8014,13 @@ The label and the input box are always hidden.',
 '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:
@@ -8239,7 +8254,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}}.
@@ -8278,7 +8294,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]]
 
@@ -8910,7 +8928,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.',
@@ -9354,7 +9373,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.',
 
@@ -9405,7 +9425,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
@@ -9545,6 +9565,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}}',
@@ -9921,7 +9947,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]].
@@ -10036,7 +10063,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]].',
index 4d7ca96..08ebf75 100644 (file)
@@ -2841,7 +2841,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:",
@@ -3596,7 +3596,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',
@@ -3767,7 +3767,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.
index 47e5546..36d89bc 100644 (file)
@@ -867,7 +867,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..efcc823 100644 (file)
@@ -11,6 +11,7 @@
  * @author Gion-andri
  * @author Kaganer
  * @author Kazu89
+ * @author Shirayuki
  * @author Urhixidur
  * @author לערי ריינהארט
  */
@@ -2607,7 +2608,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 +3344,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 +3531,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. 
index 28e992f..eec115d 100644 (file)
@@ -756,7 +756,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}}.
@@ -827,7 +827,7 @@ să folosiți vechea parolă.',
 '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.',
@@ -1263,18 +1263,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:',
@@ -2983,7 +2984,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:',
@@ -3147,7 +3148,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 */',
@@ -3195,6 +3196,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ă',
@@ -3282,7 +3284,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',
@@ -3753,7 +3755,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',
@@ -3762,7 +3764,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ă.
@@ -3844,6 +3846,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 →',
@@ -3929,7 +3934,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]].',
index 0203dd1..150332c 100644 (file)
@@ -2772,7 +2772,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:",
@@ -3661,7 +3661,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 +3940,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]].',
index 26f4813..856963f 100644 (file)
@@ -93,6 +93,7 @@
  * @author Александр Сигачёв
  * @author Гусейн
  * @author ОйЛ
+ * @author Сай
  * @author Умар
  * @author Чаховіч Уладзіслаў
  * @author לערי ריינהארט
@@ -895,7 +896,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}}.
@@ -968,8 +969,9 @@ $2',
 'mailerror' => 'Ошибка при отправке почты: $1',
 'acct_creation_throttle_hit' => 'За сутки с вашего IP-адреса {{PLURAL:$1|была создана $1 учётная запись участника|было создано $1 учётных записей участников|было создано $1 учётных записей участников}}, что является пределом для данного отрезка времени.
 Таким образом, пользователи, обладающие данным IP-адресом, в данный момент больше не могут создавать новых учётных записей.',
-'emailauthenticated' => 'Ваш почтовый адрес подтверждён $2 в $3.',
-'emailnotauthenticated' => 'Ваш адрес электронной почты ещё не был подтверждён, функции вики-движка по работе с эл. почтой отключены.',
+'emailauthenticated' => 'Ваш адрес электронной почты подтверждён $2 в $3.',
+'emailnotauthenticated' => 'Ваш адрес электронной почты ещё не был подтверждён.
+Письма не будут отправляться ни для одной из следующий функций.',
 'noemailprefs' => 'Адрес электронной почты не был указан, функции вики-движка по работе с эл. почтой отключены.',
 'emailconfirmlink' => 'Подтвердить ваш адрес электронной почты',
 'invalidemailaddress' => 'Адрес электронной почты не может быть принят, так как он не соответствует формату.
@@ -1068,9 +1070,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 +1413,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' => 'Причина:',
@@ -1866,7 +1868,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' => 'Настройки свежих правок',
@@ -3124,7 +3126,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 +3287,7 @@ $2',
 'tooltip-undo' => 'Убрать внесённую правку и показать предпросмотр, с возможностью указать причину отмены',
 'tooltip-preferences-save' => 'Сохранить настройки',
 'tooltip-summary' => 'Введите краткое описание',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/* Размещённый здесь CSS будет применяться ко всем темам оформления */',
@@ -3351,6 +3353,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' => 'Не разрешено',
@@ -3438,7 +3441,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 пикселей',
@@ -3913,7 +3916,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' => 'все',
@@ -4023,6 +4026,7 @@ $5
 'word-separator' => '&#32;',
 'ellipsis' => '…',
 'parentheses' => '($1)',
+'quotation-marks' => '«$1»',
 
 # Multipage image navigation
 'imgmultipageprev' => '← предыдущая страница',
@@ -4179,7 +4183,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]].',
index 210df3b..96276ab 100644 (file)
@@ -2738,7 +2738,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' => 'Філтер за станом:',
@@ -3486,7 +3486,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' => 'вшыткы',
@@ -3664,7 +3664,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]].',
index 1272862..8c27d9f 100644 (file)
@@ -2787,7 +2787,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' => 'ग्राहकीकरणस्य स्थितौ शोधनी ।',
@@ -3523,7 +3523,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' => 'सर्वाणि',
@@ -3700,9 +3700,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 सर्वजनसामान्यम् अनुज्ञापत्रं पश्यतु ।
index 6c74bcd..1f6fa8a 100644 (file)
@@ -2705,7 +2705,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' => 'Уларытыы көрүҥүнэн наардыыр сиидэ:',
@@ -3466,7 +3466,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' => 'бары',
@@ -3650,7 +3650,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]] сайдыытыгар үлэлэрин иһин манна ахтыллыбыт дьоҥҥо махтанабыт.',
index 0b18a5c..38ffa05 100644 (file)
@@ -1162,7 +1162,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 d97bb14..7b7490c 100644 (file)
@@ -1441,7 +1441,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',
index 4a257c8..5c1ee3e 100644 (file)
@@ -2270,7 +2270,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 +2789,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',
index 736c64f..2d96fb6 100644 (file)
@@ -1451,7 +1451,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..b9ff975 100644 (file)
@@ -954,7 +954,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..06629dd 100644 (file)
@@ -1597,7 +1597,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 +1871,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 95e53d8..5ec3a85 100644 (file)
@@ -1792,7 +1792,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',
index 5bafdd5..dbc9451 100644 (file)
@@ -2864,7 +2864,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 +3624,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 +3807,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.
index 35fbfed..9bdc67d 100644 (file)
@@ -264,7 +264,7 @@ $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).',
@@ -1215,7 +1215,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 a020dd0..d3149b0 100644 (file)
@@ -2756,7 +2756,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' => 'පාරිභෝගීකරණ තත්ත්වය අනුව පෙරීම:',
@@ -3539,7 +3539,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 +3792,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වන හෝ (ඔබට කැමති නම්) ඉන්පසු එන සංස්කරණයකට අනුවය.
 
index fb9d616..43c6703 100644 (file)
@@ -291,7 +291,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í',
@@ -617,6 +617,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 +740,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 +806,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 +833,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 +850,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 +895,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 +910,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 +1001,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 +1012,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 +1161,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 +1181,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 +1251,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' => 'Viditeľné',
+'revdelete-radio-unset' => 'Skryté',
 '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:',
@@ -1429,7 +1442,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 +1454,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 +1488,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 +1501,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 +1517,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 +1528,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 +1552,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 +1600,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 +1620,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 +1686,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 +1703,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',
@@ -1697,7 +1726,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 +2143,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 +2218,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 +2314,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 +2475,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 +2488,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 +2498,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 +2638,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 +2760,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 +2798,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 +2903,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 +2931,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 +2959,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 +3058,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 +3079,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!',
@@ -3151,13 +3186,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',
@@ -3703,7 +3739,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',
@@ -3765,7 +3801,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ť
@@ -3774,7 +3810,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
 
@@ -3807,6 +3843,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;',
@@ -3896,7 +3935,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]].',
@@ -3915,7 +3954,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:',
@@ -3978,6 +4017,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',
@@ -4138,6 +4178,14 @@ 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}}',
index adc6c4a..8e404e6 100644 (file)
@@ -519,9 +519,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 +574,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 +647,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 +727,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 +777,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 +879,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 +1072,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 +1080,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',
@@ -1168,15 +1168,15 @@ Do skrite vsebine bodo še vedno lahko dostopali drugi administratorji {{GRAMMAR
 * Neprimerni osebni podatki
 *: ''domači naslovi in telefonske številke, številke socialnega zavarovanja, etc.''",
 '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' => 'Vidno',
+'revdelete-radio-unset' => 'Skrito',
 'revdelete-suppress' => 'Zadrži podatke od administratorjev kakor tudi od ostalih',
 'revdelete-unsuppress' => 'Odpraviti omejitve na obnovljenih redakcijah.',
 'revdelete-log' => 'Razlog:',
@@ -1360,7 +1360,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:',
@@ -2686,16 +2686,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 +2703,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 +2722,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 +2904,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 +3071,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.',
@@ -3110,6 +3111,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',
@@ -3666,7 +3668,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',
@@ -3856,7 +3858,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]].',
@@ -3877,7 +3879,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:',
index d9f0412..86b6148 100644 (file)
@@ -1801,7 +1801,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 +2140,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',
index cfba54f..53a18c8 100644 (file)
@@ -1319,7 +1319,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 +1436,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 b3aff4e..76a3ed2 100644 (file)
@@ -2748,7 +2748,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',
@@ -3437,7 +3437,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',
@@ -3617,7 +3617,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.
 
index a7b487d..6a2c6a0 100644 (file)
@@ -647,7 +647,7 @@ $1',
 'copyright' => 'Садржај је доступан под лиценцом $1 осим ако је другачије наведено.',
 'copyrightpage' => '{{ns:project}}:Ауторска права',
 'currentevents' => 'Актуелности',
-'currentevents-url' => 'Project:Ð\9dовости',
+'currentevents-url' => 'Project:Ð\90кÑ\82Ñ\83елности',
 'disclaimers' => 'Одрицање одговорности',
 'disclaimerpage' => 'Project:Одрицање одговорности',
 'edithelp' => 'Помоћ при уређивању',
@@ -800,8 +800,7 @@ $2',
 'myprivateinfoprotected' => 'Немате дозволу за мењање ваших личних информација.',
 'mypreferencesprotected' => 'Немате дозволу за мењање ваших подешавања.',
 'ns-specialprotected' => 'Посебне странице се не могу уређивати.',
-'titleprotected' => "Овај наслов је {{GENDER:$1|заштитио корисник|заштитила корисница|заштитио корисник}} [[User:$1|$1]].
-Наведени разлог: ''$2''.",
+'titleprotected' => "Овај назив је [[User:$1|$1]] заштитио од прављења. Разлог: ''$2''.",
 'filereadonlyerror' => 'Не могу да изменим датотеку „$1“ јер је ризница „$2“ у режиму за читање.
 
 Администратор који ју је закључао понудио је следеће објашњење: „$3“.',
@@ -855,7 +854,7 @@ $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-createanother' => 'Отвори још један налог',
@@ -1267,7 +1266,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
@@ -1361,15 +1360,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' => 'Ð\92идÑ\99иво',
+'revdelete-radio-unset' => 'СакÑ\80ивено',
 'revdelete-suppress' => 'Сакриј податке од администратора и других корисника',
 'revdelete-unsuppress' => 'Уклони ограничења на враћеним изменама',
 'revdelete-log' => 'Разлог:',
@@ -1439,7 +1438,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“',
@@ -1829,7 +1828,7 @@ $1",
 'diff' => 'разл',
 'hist' => 'ист',
 'hide' => 'сакриј',
-'show' => 'прикажи',
+'show' => 'Ð\9fрикажи',
 'minoreditletter' => ' м',
 'newpageletter' => 'Н',
 'boteditletter' => 'б',
@@ -2182,7 +2181,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' => 'Не постоји раније локално издање датотеке с наведеним временским подацима.',
@@ -2587,7 +2586,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“',
@@ -2720,8 +2719,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 +3092,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' => 'Филтрирај по стању:',
@@ -3975,7 +3974,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' => 'све',
@@ -4101,10 +4100,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',
@@ -4236,7 +4235,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|Медијавикији]].',
@@ -4312,7 +4311,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|измена|измене|измена}}',
 
index 592ec21..317a804 100644 (file)
@@ -554,7 +554,7 @@ $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',
@@ -701,8 +701,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“.',
@@ -753,7 +752,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.',
@@ -933,7 +932,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.
@@ -1324,7 +1323,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“',
@@ -1705,7 +1704,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',
@@ -2058,7 +2057,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.',
@@ -2289,7 +2288,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.',
 
@@ -2446,7 +2445,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“',
@@ -2579,8 +2578,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.
@@ -2952,7 +2951,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:',
@@ -3198,6 +3197,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',
@@ -3816,7 +3816,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',
@@ -3941,10 +3941,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žaja 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',
@@ -4076,7 +4076,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.
@@ -4151,7 +4151,10 @@ Trebalo bi da ste primili [{{SERVER}}{{SCRIPTPATH}}/COPYING primerak GNU-ove op
 '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}}',
 
@@ -4199,7 +4202,7 @@ Trebalo bi da ste primili [{{SERVER}}{{SCRIPTPATH}}/COPYING primerak GNU-ove op
 '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 izmjena}} na stranici $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 je {{GENDER:$2|promenio|promenila}} vidljivost izmena na stranici $3',
 'logentry-suppress-delete' => '$1 je {{GENDER:$2|potisnuo|potisnula}} stranicu $3',
@@ -4219,7 +4222,7 @@ 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 je {{GENDER:$2|osznačio|označila}} izenu $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',
index d210911..df96074 100644 (file)
@@ -1188,7 +1188,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 a5fb117..04a10bd 100644 (file)
@@ -2380,7 +2380,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:',
@@ -2957,7 +2957,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',
@@ -3130,7 +3130,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.
 
index 410e1ba..52ecb44 100644 (file)
@@ -2792,7 +2792,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',
index cd7ffa8..b137d8e 100644 (file)
@@ -781,7 +781,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}}.
@@ -852,7 +852,7 @@ För att förhindra missbruk skickas bara en lösenordsåterställning per {{PLU
 '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 +1216,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',
@@ -1287,15 +1287,15 @@ Andra administratörer på {{SITENAME}} kommer fortfarande att kunna läsa det d
 * 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' => 'Synlig',
+'revdelete-radio-unset' => 'Dold',
 'revdelete-suppress' => 'Undanhåll data även från administratörer',
 'revdelete-unsuppress' => 'Ta bort begränsningar på återställda versioner',
 'revdelete-log' => 'Anledning:',
@@ -1491,7 +1491,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:',
@@ -2997,7 +2997,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 +3161,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 */',
@@ -3781,7 +3781,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',
@@ -3966,7 +3966,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]].',
index d8ef376..73e2b60 100644 (file)
@@ -2183,7 +2183,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 +2416,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:',
@@ -2840,7 +2840,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 +3008,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.
 
index 8f32e5d..b3e547f 100644 (file)
@@ -302,7 +302,7 @@ $messages = array(
 $1',
 'pool-timeout' => 'Za dugi czas uoczekiwańo na blokada',
 'pool-queuefull' => 'Kolyjność zadań je pełno',
-'pool-errorunknown' => 'Feler ńyznany',
+'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}}}}',
@@ -441,9 +441,9 @@ Zapytańy: $2',
 '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, 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 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:
+'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.',
 'mycustomcssprotected' => 'Ńy mosz uprawńyń do sprowjańo tyj zajty CSS.',
@@ -466,7 +466,6 @@ Administrator kery zawarł wćepał kůmyntorz: "$3".',
 # Login and logout pages
 'logouttext' => "'''Terozki jeżeś wylůgowany'''.
 
-Możesz dali sam sprowjać zajty we {{SITENAME}} kej ńyzalůgowany sprowjorz, abo <span class='plainlinks'>[$1 zalůgować śe nazod]</span> kej tyn som abo inkszy używocz.
 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.
@@ -486,10 +485,10 @@ Pamjyntej coby posztalować [[Special:Preferences|preferencyji]]',
 'userlogin-signwithsecure' => 'Użyj bezpjecznygo połůnczyńa',
 'yourdomainname' => 'Twoja domyna',
 'password-change-forbidden' => 'Ńy można půmjyńać haseł na tyj wiki.',
-'externaldberror' => 'Je jaki feler we zewnyntřnyj baźe autentyfikacyjnyj, abo ńy moš uprawńyń potřebnych do aktualizacyji zewnyntřnego kůnta.',
+'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 / Tworzyńy kůnta',
-'loginprompt' => 'Muśisz mjeć zołůnczůne cookies coby můc śe sam zalůgować.',
+'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',
@@ -503,13 +502,34 @@ Pamjyntej coby posztalować [[Special:Preferences|preferencyji]]',
 'gotaccount' => "Mosz już kůnto? '''$1'''.",
 'gotaccountlink' => 'Naloguj śe',
 'userlogin-resetlink' => 'Zapomńoł żeś dane lo nalogowańo?',
+'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:',
 '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 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 ćosteczek do logowańo użytkowńikůw. Mosz zablokowano jejich uobsłůga. Sprůbuj zaś kej załůnczysz uobsłůga ćosteczek.',
@@ -543,31 +563,33 @@ Jak ftoś inkszy chćoł nowe hasło abo jak Ci śe przipůmńouo stare a ńy ch
 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.',
+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 adres e-brifa zostoł uwjerzitelńů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ć.',
+'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' => 'Potwjerdź swůj adres e-brifa',
+'emailconfirmlink' => 'Potwjyrdź swůj adres e-brifa',
 'invalidemailaddress' => 'E-brif ńy bydźe zaakceptůwany skiż tygo co jigo format ńy spełńo formalnych wymagań. Prosza naszkryflać 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ů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' => '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ć.',
+'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. 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',
@@ -579,7 +601,7 @@ Coby powstrzimać nadużyća, mogebność wysyłańo przipůmńyń nasztalowano
 '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śysz być zalogowany, coby uzyskać bezpostrzedńi dostymp do tyj zajty.',
+'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.
@@ -592,35 +614,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
@@ -638,37 +660,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:
 
@@ -678,52 +700,46 @@ 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' => "'''Przepraszomy! Serwer ńy może przetworzić tygo sprowjyńo skuli utraty danych ze sesyji. Sprůbuj jeszcze roz. Kejby to ńy pomogło - wyloguj śe a zalogůj uod nowa.'''",
 '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.''
@@ -772,7 +788,7 @@ Možeš sprowjać te co juž sům, abo [[Special:UserLogin|zalogować śe, abo z
 'nocreate-loggedin' => 'Ńy moš uprowńyń do twořyń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',
+'permissionserrors' => 'Felerne uprawńyńo',
 'permissionserrorstext' => 'Ńy moš 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.'''
@@ -835,8 +851,8 @@ Skuli: ''$2''",
 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' => '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' => '(blank)',
 
@@ -1276,7 +1292,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
@@ -1691,8 +1707,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',
@@ -1923,12 +1939,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):',
 
@@ -1962,7 +1978,7 @@ $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
@@ -2166,7 +2182,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
@@ -2426,8 +2442,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',
@@ -2441,8 +2457,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',
@@ -2516,9 +2532,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',
@@ -2651,7 +2667,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',
@@ -2734,10 +2750,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…',
@@ -2754,9 +2770,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',
@@ -2814,14 +2830,14 @@ Možeš tyž [[Special:EditWatchlist|užyć standardowygo edytora]].',
 * <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',
 
index 56b3a2b..3ea157f 100644 (file)
@@ -526,7 +526,7 @@ $1',
 'gotaccount' => "ஏற்கனவே பயனர் கணக்கு உள்ளதா? '''$1'''.",
 'gotaccountlink' => 'புகுபதிகை',
 'userlogin-resetlink' => 'உங்கள் புகுபதிகைக் குறிப்புகளை மறந்துவிட்டீர்களா?',
-'userlogin-resetpassword-link' => 'உங்கள் கடவுச்சொல் மறந்துவிட்டதா?',
+'userlogin-resetpassword-link' => 'உங்கள் கடவுச் சொல்லை மறந்து விட்டீர்களா?',
 'helplogin-url' => 'Help:புகுபதிகை',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|புகுபதிவதற்கான உதவி]]',
 'userlogin-createanother' => 'மற்றொரு கணக்கு ஒன்றை உருவாக்கவும்',
@@ -1002,8 +1002,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' => 'காரணம்:',
@@ -1237,7 +1237,7 @@ $1",
 'badsiglength' => 'தங்களது கையெழுத்து மிக நீளமானது.
 
 அது $1 {{PLURAL:$1|எழுத்து|எழுத்துக்களுக்கு}} மேல் இருக்கக்கூடாது.',
-'yourgender' => 'பாலà¯\8d:',
+'yourgender' => 'à®\89à®\99à¯\8dà®\95ளà¯\88 à®\8eபà¯\8dபà®\9fி à®µà®¿à®µà®°à®¿à®\95à¯\8dà®\95 à®µà®¿à®°à¯\81à®®à¯\8dபà¯\81à®\95ினà¯\8dà®±à¯\80à®°à¯\8dà®\95ளà¯\8d?',
 'gender-unknown' => 'நான் குறிப்பிட விரும்பவில்லை',
 'gender-male' => 'ஆண்',
 'gender-female' => 'பெண்',
@@ -1415,8 +1415,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' => 'கவனிக்கப்படாத பக்கங்களின் பட்டியலைப் பார்க்க',
@@ -1425,6 +1425,8 @@ $1",
 'action-userrights-interwiki' => 'ஏனைய விக்கித் தளங்களின் பயனர் உரிமைகளைத் தொகு',
 'action-siteadmin' => 'தரவுதளத்தை பூட்டு அல்லது  பூட்டாதே',
 'action-sendemail' => 'மின்னஞ்சல்கள் அனுப்பு',
+'action-editmywatchlist' => 'உங்கள் கவனிப்பு பட்டியலை தொகு',
+'action-viewmywatchlist' => 'உங்கள் கவனிப்பு பட்டியலை பார்',
 
 # Recent changes
 'nchanges' => '{{PLURAL:$1|ஓர் மாற்றம்|$1 மாற்றங்கள்}}',
@@ -1700,6 +1702,8 @@ $1',
 'listfiles_size' => 'அளவு',
 'listfiles_description' => 'விளக்கம்',
 'listfiles_count' => 'பதிப்புக்கள்',
+'listfiles-latestversion-yes' => 'ஆம்',
+'listfiles-latestversion-no' => 'இல்லை',
 
 # File description page
 'file-anchor-link' => 'கோப்பு',
@@ -1891,8 +1895,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' => 'நீங்கள் இந்தச் செயலை எந்தப் பயனர் அல்லது பக்கம் தொடர்பில் செய்வது என்பதைக் குறிப்பிடவில்லை.',
@@ -2583,7 +2587,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' => 'தனிப்பயனாக்கத்தின்படி வடிகட்டு.',
@@ -2733,7 +2737,7 @@ $1',
 'tooltip-undo' => '"பின்வாங்கு" என்பது முன்பு செய்த தொகுப்புக்களை இல்லாது செய்கிறது. மேலும் தாங்கள் செய்த தொகுப்பினை முன்தோற்ற நிலைக்கு கொண்டுவந்து காட்டும். அது தங்களுக்குச் சிறுகுறிப்புப் பகுதியில் அதற்கான காரணத்தைக் கூற அனுமதிக்கிறது.',
 'tooltip-preferences-save' => 'விருப்பங்களை சேமி',
 'tooltip-summary' => 'குறுகிய சுருக்கத்தை உள்ளிடவும்.',
-'tooltip-iwiki' => '$1 - $2',
+'interlanguage-link-title' => '$1 - $2',
 
 # Metadata
 'notacceptable' => 'உங்களது சேவையாளர் வாசிக்க கூடிய விதத்தில் இந்த விக்கியால தரவுகளை வழங்க முடியாது.',
@@ -3299,7 +3303,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' => 'அனைத்து',
@@ -3472,7 +3476,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 பொது உரிமத்தை பார்க்கவும்.
@@ -3617,7 +3621,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
index 238be25..f36a2f5 100644 (file)
@@ -965,7 +965,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 532db2c..443e64d 100644 (file)
@@ -147,31 +147,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 +358,7 @@ $messages = array(
 'articlepage' => 'విషయపు పేజీని చూడండి',
 'talk' => 'చర్చ',
 'views' => 'చూపులు',
-'toolbox' => 'పనిముట్ల పెట్టె',
+'toolbox' => 'పనిముట్ల',
 'userpage' => 'వాడుకరి పేజీని చూడండి',
 'projectpage' => 'ప్రాజెక్టు పేజీని చూడు',
 'imagepage' => 'ఫైలు పేజీని చూడండి',
@@ -367,7 +367,7 @@ $messages = array(
 'viewhelppage' => 'సహాయం పేజీని చూడు',
 'categorypage' => 'వర్గం పేజీని చూడు',
 'viewtalkpage' => 'చర్చను చూడు',
-'otherlanguages' => 'à°\87తర à°­à°¾à°·à°²à°²à±\8a',
+'otherlanguages' => 'à°\87తర à°­à°¾à°·à°²à°²à±\8b',
 'redirectedfrom' => '($1 నుండి మళ్ళించబడింది)',
 'redirectpagesub' => 'దారిమార్పు పుట',
 'lastmodifiedat' => 'ఈ పేజీకి $2, $1న చివరి మార్పు జరిగినది.',
@@ -388,7 +388,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:ఇప్పటి ముచ్చట్లు',
@@ -552,6 +552,7 @@ $2',
 'yourname' => 'వాడుకరి పేరు:',
 'userlogin-yourname' => 'వాడుకరి పేరు',
 'userlogin-yourname-ph' => 'మీ వాడుకరి పేరును ఇవ్వండి',
+'createacct-another-username-ph' => 'మీ వాడుకరి పేరును ఇవ్వండి',
 'yourpassword' => 'సంకేతపదం:',
 'userlogin-yourpassword' => 'సంకేతపదం',
 'userlogin-yourpassword-ph' => 'మీ సంకేతపదాన్ని ఇవ్వండి',
@@ -580,7 +581,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 +891,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 +1032,7 @@ $3 చెప్పిన కారణం: ''$2''",
 * అనుచితమైన వ్యక్తిగత సమాచారం
 * "ఇంటి చిరునామాలు, టెలిఫోను నంబర్లు, సోషల్ సెక్యూరిటీ నంబర్లు, వగైరాలు"',
 'revdelete-legend' => 'సందర్శక నిబంధనలు అమర్చు',
-'revdelete-hide-text' => 'à°\95à±\82à°°à±\8dà°ªà±\81 à°ªà°¾à° à±\8dయానà±\8dని à°¦à°¾à°\9aà±\81',
+'revdelete-hide-text' => 'à°\95à±\82à°°à±\8dà°ªà±\81 à°ªà°¾à° à±\8dà°¯à°\82',
 'revdelete-hide-image' => 'ఫైలులోని విషయాన్ని దాచు',
 'revdelete-hide-name' => 'చర్యను, లక్ష్యాన్నీ దాచు',
 'revdelete-hide-comment' => 'దిద్దుబాటు వ్యాఖ్యను దాచు',
@@ -1326,7 +1327,7 @@ $1",
 'group-bot' => 'బాట్‌లు',
 'group-sysop' => 'నిర్వాహకులు',
 'group-bureaucrat' => 'అధికారులు',
-'group-suppress' => 'మార్పులను పూర్తిగా కనిపించకుండాచేయుట',
+'group-suppress' => ' పూర్తి తొలగింపుదారులు',
 'group-all' => '(అందరూ)',
 
 'group-user-member' => '{{GENDER:$1|వాడుకరి}}',
@@ -1334,14 +1335,14 @@ $1",
 'group-bot-member' => '{{GENDER:$1|బాట్}}',
 'group-sysop-member' => '{{GENDER:$1|నిర్వాహకుడు|నిర్వాహకురాలు}}',
 'group-bureaucrat-member' => '{{GENDER:$1|అధికారి|అధికారిణి}}',
-'group-suppress-member' => '{{GENDER:$1|మార్పులను పూర్తిగా కనిపించకుండాచేయుట}}',
+'group-suppress-member' => 'పూర్తి   తొలగింపు',
 
 'grouppage-user' => '{{ns:project}}:వాడుకరులు',
 'grouppage-autoconfirmed' => '{{ns:project}}:ఆటోమాటిగ్గా నిర్ధారించబడిన వాడుకరులు',
 'grouppage-bot' => '{{ns:project}}:బాట్లు',
 'grouppage-sysop' => '{{ns:project}}:నిర్వాహకులు',
 'grouppage-bureaucrat' => '{{ns:project}}:అధికార్లు',
-'grouppage-suppress' => '{{ns:project}}:మారà±\8dà°ªà±\81లనà±\81 à°ªà±\82à°°à±\8dతిà°\97à°¾ à°\95నిపిà°\82à°\9aà°\95à±\81à°\82à°¡à°¾à°\9aà±\87à°¯à±\81à°\9f',
+'grouppage-suppress' => '{{ns:project}}:à°ªà±\82à°°à±\8dతి à°¤à±\8aà°²à°\97à°¿à°\82à°ªà±\81',
 
 # Rights
 'right-read' => 'పేజీలు చదవడం',
@@ -1481,7 +1482,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 +1903,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 +2280,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 +2580,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 +3250,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 +3416,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 లేదా (మీ ఎంపిక ప్రకారం) అంతకంటే కొత్త వెర్షను యొక్క నియమాలకు లోబడి మార్చుకోవచ్చు.
 
index 51a6d73..f1e717e 100644 (file)
@@ -915,7 +915,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',
index f7ea5cd..a9a16fa 100644 (file)
@@ -1829,7 +1829,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 +2304,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 40debf6..e7f97ae 100644 (file)
@@ -1615,7 +1615,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 +2088,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',
index a0d9ec1..18541ae 100644 (file)
@@ -2784,7 +2784,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 +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' => 'ทั้งหมด',
@@ -3645,7 +3645,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 แห่งสัญญาอนุญาต หรือรุ่นภายหลังอื่นใด (ตามที่คุณเลือก)
index 7c7b5e1..7090ecc 100644 (file)
@@ -2327,7 +2327,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:',
@@ -2838,7 +2838,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',
@@ -3000,7 +3000,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.
 
index 028870d..38099bb 100644 (file)
@@ -1654,9 +1654,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',
@@ -2029,12 +2029,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 kawing patungo sa ibang mga websayt na nanininda ng mga bago at gamit na 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
@@ -2250,7 +2249,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' => 'Burahin 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.
@@ -2593,7 +2592,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 direksiyong IP bilang isang bukas na proxy sa DNSBL na ginagamit ng {{SITENAME}}.
+Hindi ka makakalikha ng kuwenta',
 '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.',
@@ -2742,7 +2742,7 @@ Sa huling kaso, maaari mong gumamit ng ungay, hal. [[{{#Special:Export}}/{{Media
 '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.',
+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:',
@@ -2773,7 +2773,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',
@@ -2905,7 +2905,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 */',
@@ -2918,7 +2918,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 */',
@@ -2987,8 +2987,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 +3866,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.
index 5e73c11..79babc5 100644 (file)
@@ -1002,7 +1002,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..22a76af 100644 (file)
@@ -1144,7 +1144,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',
index c0c2bef..c66f7df 100644 (file)
@@ -808,7 +808,7 @@ 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]]',
 'createacct-join' => 'Aşağıya bilgilerinizi girin.',
@@ -2940,7 +2940,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:',
@@ -3684,7 +3684,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',
@@ -3876,7 +3876,7 @@ 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-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.
 
index 5dd3011..47b3f5e 100644 (file)
@@ -804,7 +804,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..d26a779 100644 (file)
@@ -877,7 +877,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',
index f6b9404..8444004 100644 (file)
@@ -2050,7 +2050,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' => 'Барысы',
@@ -2376,7 +2376,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' => 'барлык',
index 8f96b5b..7b612dc 100644 (file)
@@ -1753,7 +1753,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ı',
@@ -2038,7 +2038,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',
index 8a1d47e..63a770c 100644 (file)
@@ -1287,7 +1287,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 aad3464..226e4a2 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|تۈر|تۈرلەر}}',
@@ -178,7 +191,7 @@ $messages = array(
 '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 نىڭ مۇنازىرە بېتى',
@@ -234,6 +247,7 @@ $messages = array(
 'create-this-page' => 'بۇ بەتنى قۇر',
 'delete' => 'ئۆچۈر',
 'deletethispage' => 'بۇ بەتنى ئۆچۈر',
+'undeletethispage' => ' بۇ بەتنى ئەسلىگە كەلتۈر',
 'undelete_short' => 'ئۆچۈرۈلگەن {{PLURAL:$1|بىر تەھرىر|$1 تەھرىر}} ئەسلىگە كەلتۈرۈلدى',
 'viewdeleted_short' => '{{PLURAL:$1|بىر ئۆچۈرۈلگەن نەشرى|$1 ئۆچۈرۈلگەن نەشرى}}نى كۆرسەت',
 'protect' => 'قوغدا',
@@ -250,7 +264,7 @@ $messages = array(
 'articlepage' => 'مەزمۇن بېتىنى كۆرسەت',
 'talk' => 'مۇنازىرە',
 'views' => 'كۆرۈنۈش',
-'toolbox' => 'قورال ساندۇقى',
+'toolbox' => 'قوراللار',
 'userpage' => 'ئىشلەتكۈچى بېتىنى كۆرسەت',
 'projectpage' => 'قۇرۇلۇش بېتىنى كۆرسەت',
 'imagepage' => 'ھۆججەت بېتىنى كۆرسەت',
@@ -373,6 +387,8 @@ URL نى خاتا كىرگۈزۈپ قالدىڭىز ياكى خاتا ئۇلان
 # General errors
 'error' => 'خاتالىق',
 'databaseerror' => 'ساندان خاتالىقى',
+'databaseerror-function' => 'فۇنكىسىيە: $1',
+'databaseerror-error' => 'خاتا: $1',
 'laggedslavemode' => 'ئاگاھلاندۇرۇش: بەت يېقىنقى يېڭىلاشنى ئۆز ئىچىگە ئالمىغان بولۇشى مۇمكىن.',
 'readonly' => 'ساندان قۇلۇپلانغان',
 'enterlockreason' => 'قۇلۇپلىنىش سەۋەبىنى كىرگۈزۈڭ، قايتا ئېچىشنىڭ مۆلچەر ۋاقتىنىمۇ ئۆز ئىچىگە ئالىدۇ',
@@ -470,9 +486,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' => 'بۇ سانداننى دەلىللەش خاتالىقى ياكى سىرتقى ھېساباتىڭىزنى يېڭىلاشنى چەكلىگەنلىكتىن بولغان بولۇشى مۇمكىن.',
@@ -484,18 +510,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' => 'ئىشلەتكۈچى ھېساباتى قۇرۇلدى ئەمما سىز تېخى كىرمىدىڭىز..
 
@@ -522,15 +572,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" غا تەڭشىدى.
@@ -552,7 +602,7 @@ cookies نى قوزغاتقانلىقىڭىزنى جەزملەڭ، بۇ بەتن
 'mailerror' => 'ئېلخەت يوللىغاندا خاتالىق كۆرۈلدى:$1',
 'acct_creation_throttle_hit' => 'Wiki ئىشلىتىدىغان زىيارەتچى IP ئادرېسىڭىزنى ئىشلىتىپ {{PLURAL:$1|1 ھېسابات|$1 ھېسابات}} قۇردى.
 مۇشۇ پەيتتە يەنە ھېسابات قۇرالمايسىز.',
-'emailauthenticated' => 'ئېلخەت ئادرېسىڭىز $2 $3 ئىناۋەتلىك ئىكەنلىكى دەلىللەندى.',
+'emailauthenticated' => 'ئېلخەت ئادرېسىڭىز $2 سائەت $3 دە دەلىللەندى.',
 'emailnotauthenticated' => 'ئېلخەت ئادرېسىڭىز تېخى دەلىللەنمىدى.
 تۆۋەندىكى ئىقتىدارى ھېچقانداق ئېلخەت ئەۋەتمەيدۇ.',
 'noemailprefs' => 'بۇ ئىقتىدارنى ئىشلىتىش ئۈچۈن مايىللىق تەڭشىكىڭىزدە ئېلخەت ئادرېسى بەلگىلەڭ.',
@@ -581,25 +631,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' => 'ئىمنى ئەسلىگە قايتۇرماق',
@@ -642,7 +692,7 @@ $2
 'changeemail-oldemail' => 'نۆۋەتتىكى ئېلخەت ئادرېسى:',
 'changeemail-newemail' => 'يېڭى ئېلخەت ئادرېسى:',
 'changeemail-none' => '(يوق)',
-'changeemail-password' => '{{SITENAME}} دىكى ئىم:',
+'changeemail-password' => '{{SITENAME}} دىكى پارولىڭىز:',
 'changeemail-submit' => 'ئېلخەت ئۆزگەرت',
 'changeemail-cancel' => 'ۋاز كەچ',
 
@@ -723,7 +773,7 @@ $2
 'loginreqtitle' => 'تىزىمغا كىرىڭ',
 'loginreqlink' => 'تىزىمغا كىر',
 'loginreqpagetext' => '$1 بولغاندىلا ئاندىن باشقا بەتلەرنى كۆرەلەيسىز.',
-'accmailtitle' => 'ئىم يوللاندى.',
+'accmailtitle' => 'پارول يوللاندى.',
 'accmailtext' => "[[User talk:$1|$1]] ئىختىيارىي قۇرۇلغان ئىم  $2 غا يوللاندى.
 
 يېڭى ھېساباتقا قۇرغان ئىمنى تىزىمغا كىرىپ''[[Special:ChangePassword|ئىم ئۆزگەرت]]'' بېتىدىن ئۆزگەرتەلەيسىز.",
@@ -920,8 +970,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' => '(بوش)',
 
@@ -987,7 +1037,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' => 'ھەئە',
@@ -1120,7 +1170,7 @@ $1",
 'search-interwiki-default' => '$1 نەتىجە:',
 'search-interwiki-more' => '(تېخىمۇ كۆپ)',
 'search-relatedarticle' => 'ئالاقىدار',
-'mwsuggest-disable' => 'AJAX تەكلىپىنى چەكلە',
+'mwsuggest-disable' => 'ئىزدەش تەكلىپىنى چەكلە',
 'searcheverything-enable' => 'ھەممە ئات بوشلۇقىدىن ئىزدە',
 'searchrelated' => 'ئالاقىدار',
 'searchall' => 'ھەممىسى',
@@ -1148,7 +1198,7 @@ $1",
 'prefs-edits' => 'تەھرىر سانى:',
 'prefsnologin' => 'تىزىمغا كىرمىدى',
 'prefsnologintext' => 'سىز ئالدى بىلەن <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} تىزىمغا كىر]</span>سىڭىز ئاندىن ئىشلەتكۈچى مايىللىقنى تەڭشىيەلەيسىز.',
-'changepassword' => 'ئىم ئۆزگەرت',
+'changepassword' => 'پارولنى ئۆزگەرتىش',
 'prefs-skin' => 'تېرە',
 'skin-preview' => 'ئالدىن كۆزەت',
 'datedefault' => 'مايىللىق يوق',
@@ -1165,7 +1215,7 @@ $1",
 'prefs-watchlist-edits-max' => 'ئەڭ كۆپ سانى: 1000',
 'prefs-watchlist-token' => 'كۆزەت تىزىملىك نىشانى:',
 'prefs-misc' => 'ئارىلاشما تۈر',
-'prefs-resetpass' => 'ئىم ئۆزگەرت',
+'prefs-resetpass' => 'پارولنى ئۆزگەرتىش',
 'prefs-changeemail' => 'ئېلخەت ئۆزگەرت',
 'prefs-setemail' => 'ئېلخەت ئادرېس تەڭشەك',
 'prefs-email' => 'ئېلخەت تاللانما',
@@ -1253,6 +1303,8 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'prefs-dateformat' => 'چېسلا فورماتى',
 'prefs-timeoffset' => 'ۋاقىت پەرقى',
 'prefs-advancedediting' => 'ئالىي تاللانما',
+'prefs-editor' => 'تەھرىرلىگۈچ',
+'prefs-preview' => 'ئالدىن كۆزەت',
 'prefs-advancedrc' => 'ئالىي تاللانما',
 'prefs-advancedrendering' => 'ئالىي تاللانما',
 'prefs-advancedsearchoptions' => 'ئالىي تاللانما',
@@ -1260,6 +1312,7 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'prefs-displayrc' => 'كۆرسىتىش تاللانما',
 'prefs-displaysearchoptions' => 'كۆرسىتىش تاللانما',
 'prefs-displaywatchlist' => 'كۆرسىتىش تاللانما',
+'prefs-tokenwatchlist' => 'ئاچقۇچ',
 'prefs-diffs' => 'پەرقلەر',
 
 # User preference: email validation using jQuery
@@ -1359,6 +1412,8 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 'right-editusercssjs' => 'باشقا ئىشلەتكۈچىنىڭ CSS ۋە JS ھۆججىتىنى تەھرىرلە',
 'right-editusercss' => 'باشقا ئىشلەتكۈچىنىڭ CSS ھۆججىتىنى تەھرىرلە',
 'right-edituserjs' => 'باشقا ئىشلەتكۈچىنىڭ  JS ھۆججىتىنى تەھرىرلە',
+'right-editmyusercss' => 'ئۆزىڭىزنىڭ CSS ھۆججىتىڭىزنى تەھرىرلەڭ',
+'right-editmyuserjs' => 'ئۆزىڭىزنىڭ JavaScript ھۆججىتىڭىزنى تەھرىرلەڭ',
 'right-rollback' => 'ئاخىرقى ئىشلەتكۈچىنىڭ مەلۇم بەتكە ئېلىپ بارغان تەھرىرىنى تېزلىكتە ئەسلىگە كەلتۈر',
 'right-markbotedits' => 'ئەسلىگە كەلتۈرۈلگەن تەھرىرنى ماشىنا ئادەم تەھرىرى دەپ بەلگە قوي',
 'right-noratelimit' => 'چاستوتا چەكلىمىسى ئىشلىتىلمىدى',
@@ -1423,6 +1478,7 @@ HTML بەلگىسىنى تەكشۈرۈڭ.',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|ئۆزگەرتىش|ئۆزگەرتىش}}',
+'enhancedrc-history' => 'تارىخ',
 'recentchanges' => 'يېقىنقى ئۆزگەرتىشلەر',
 'recentchanges-legend' => 'يېقىنقى ئۆزگەرتىش تاللانمىسى',
 'recentchanges-summary' => 'بۇ wiki نىڭ يېقىنقى ئۆزگىرىشىنى ئىز قوغلا.',
@@ -1455,7 +1511,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" سۈپىتىدە قۇرۇلغان',
 
@@ -1728,6 +1784,9 @@ URL نىڭ توغرىلىقى ۋە تور بېكەتنى زىيارەت قىلى
 'listfiles_size' => 'چوڭلۇقى',
 'listfiles_description' => 'چۈشەندۈرۈش',
 'listfiles_count' => 'نەشرى',
+'listfiles-latestversion' => 'نۆۋەتتىكى نەشرى',
+'listfiles-latestversion-yes' => 'ھەئە',
+'listfiles-latestversion-no' => 'ياق',
 
 # File description page
 'file-anchor-link' => 'ھۆججەت',
@@ -1825,6 +1884,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" ئات بوشلۇقىدا قايتا نىشانلانغان بەت يوق.',
@@ -2355,9 +2419,9 @@ $1',
 'contributions' => '{{$1:GENDER|ئىشلەتكۈچى}} تۆھپىسى',
 'contributions-title' => '$1 نىڭ ئىشلەتكۈچى تۆھپىسى',
 'mycontris' => 'تۆھپە',
-'contribsub2' => '$1 نىڭ تۆھپىسى ($2)',
+'contribsub2' => '{{GENDER:$3|$1}} ($2) ئۈچۈن',
 'nocontribs' => 'بۇ ئۆلچەمگە ماس كېلىدىغان ئۆزگەرتىش تېپىلمىدى.',
-'uctop' => '(ئۈستى)',
+'uctop' => '(نۆۋەتتىكى)',
 'month' => 'ئايدىن بۇيان (ياكى ئىلگىرى):',
 'year' => 'يىلدىن بۇيان (ياكى ئىلگىرى):',
 
@@ -2676,7 +2740,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' => 'ئىختىيارىچە سۈزگۈچ ھالىتى:',
@@ -2906,8 +2970,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' => 'بۇ بەتكە قايتا نىشانلايدۇ',
@@ -3030,6 +3094,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' => 'تۆۋەندىكى فورماتتا يېزىڭ:
 
@@ -3277,7 +3351,7 @@ Variants for Chinese language
 'exif-compression-4' => 'CCITT نىڭ 4-گۇرۇپپا فاكس كودلىنىشى',
 
 'exif-copyrighted-true' => 'نەشر ھوقۇقى',
-'exif-copyrighted-false' => 'ئاممىۋى دائىرە',
+'exif-copyrighted-false' => 'نەشىر ھوقۇقى ھالىتى بېكىتىلمىگەن',
 
 'exif-unknowndate' => 'نامەلۇم چېسلا',
 
@@ -3483,7 +3557,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' => 'ھەممىسى',
@@ -3667,8 +3741,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 ئاممىباپ ئاممىۋى ئىجازەت ماددىلىرىدىكى بەلگىمىلەرگە ئاساسەن، بۇ پىروگراممىنى قايتا تارقىتىپ ياكى ئۆزگەرتەلەيسىز؛ مەيلى سىز مەزكۇر ئىجازەتنامىنىڭ ئىككىنچى نەشرى ياكى (ئۆزىڭىز تاللىغان) خالىغان كۈندە تارقىتىلغان نەشرىنى ئاساس قىلسىڭىز بولۇۋېرىدۇ.
 
@@ -3682,6 +3757,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) قىممىتىگە ئاساسەن تەكرار ھۆججەت ئىزدە.',
@@ -3734,7 +3814,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|ئۆزگەرتىش|ئۆزگەرتىش}}',
 
@@ -3755,6 +3838,7 @@ MediaWiki ئىشلىتىش مەقسىتىنى ئاساس قىلىپ ئېلان 
 'dberr-problems' => 'كەچۈرۈڭ! بۇ بېكەتتە تېخنىكىلىق قىيىنچىلىق كۆرۈلدى.',
 'dberr-again' => 'بىر قانچە مىنۇت كۈتۈپ ئاندىن قايتا يۈكلەڭ.',
 'dberr-info' => '(ساندان مۇلازىمىتىرىغا ئۇلىنالمىدى:  $1)',
+'dberr-info-hidden' => '(ساندان مۇلازىمېتىرىغا ئۇلىنالمىدى)',
 'dberr-usegoogle' => 'بۇ ۋاقىتتا Google ئىزدىگۈچتىن ئىزدەشنى سىناپ بېقىڭ.',
 'dberr-outofdate' => 'دىققەت ئۇلار ئىندىكېسلىغان مەزمۇن ئەڭ يېڭى بولماسلىقى مۇمكىن.',
 'dberr-cachederror' => 'بۇ ئىلتىماس قىلغان بەتنىڭ غەملەنگەن كۆپەيتىلمىسى، ئەڭ يېڭىسى بولماسلىقى مۇمكىن.',
@@ -3770,14 +3854,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 ئۆزگەرتتى',
@@ -3883,4 +3970,10 @@ 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|سېكۇنت}}',
+
 );
index a135875..1fe93fe 100644 (file)
@@ -821,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}}.
@@ -900,8 +900,8 @@ $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' => 'Уведена адреса не може бути прийнята, бо вона не відповідає формату адрес електронної пошти.
@@ -1339,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' => 'Причина:',
@@ -2806,9 +2806,11 @@ $1',
 'blockip' => 'Блокування',
 'blockip-title' => 'Блокування користувача',
 'blockip-legend' => 'Блокування користувача',
-'blockiptext' => "Використовуйте форму нижче, щоб заблокувати можливість редагування із зазначеної IP-адреси або або ім'я користувача.
-Це слід робити лише для попередження вандалізму і у відповідності до [[{{MediaWiki:Policy-url}}|правил]].
-Заповніть конкретну причину нижче (наприклад, вкажіть точні сторінки, на яких було зроблено акт вандалізму).",
+'blockiptext' => "Використовуйте форму нижче, щоб заблокувати можливість редагування зазначеній IP-адресі або користувачу.
+Це слід робити лише для запобігання порушенням і у відповідності до [[{{MediaWiki:Policy-url}}|правил]].
+Обов'язково заповніть причину нижче, бажано дати інформативну вичерпну інформацію (наприклад, послатися на конкретні правила, дати посилання на редагування користувача, які призвели до блокування). Можна конкретизувати причину блокування на сторінці обговорення користувача.
+* Якщо ви блокуєте обліковий запис бота, переконайтеся, що ви вимкнули автоблокування (для запобігання автоматичного блокування облікових записів власника бота або інших ботів).
+* Зверніть увагу, що IP-адреси у більшості випадків не варто блокувати на більший за декілька днів термін, щоб під блокування не підпали інші користувачі з таким самим IP. Винятки — частий довготривалий вандалізм.",
 'ipadressorusername' => "IP-адреса або ім'я користувача:",
 'ipbexpiry' => 'Термін:',
 'ipbreason' => 'Причина:',
@@ -3065,7 +3067,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' => 'Фільтр за внесеними змінами:',
@@ -3226,7 +3228,7 @@ $2',
 'tooltip-undo' => 'Прибрати внесені зміни і показати попередній перегляд. Дозволяє зазначити причину скасування.',
 'tooltip-preferences-save' => 'Зберегти налаштування',
 'tooltip-summary' => 'Введіть короткий опис',
-'tooltip-iwiki' => '$1 — $2',
+'interlanguage-link-title' => '$1 — $2',
 
 # Stylesheets
 'common.css' => '/** Розміщений тут CSS буде застосовуватися до всіх тем оформлення */',
@@ -3292,6 +3294,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' => 'Не індексується',
@@ -3940,7 +3943,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' => 'всі',
@@ -4047,6 +4050,7 @@ $5
 'ellipsis' => '...',
 'percent' => '$1%',
 'parentheses' => '($1)',
+'quotation-marks' => '„$1“',
 
 # Multipage image navigation
 'imgmultipageprev' => '← попередня сторінка',
@@ -4198,7 +4202,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]].',
index b154b14..f6ae821 100644 (file)
@@ -1657,7 +1657,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 535d622..adf3bca 100644 (file)
@@ -2715,7 +2715,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:',
@@ -3470,7 +3470,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',
@@ -3646,7 +3646,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]].",
index a724c1e..98ad9f3 100644 (file)
@@ -2762,7 +2762,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',
index 2a1fca9..1bf601a 100644 (file)
@@ -777,7 +777,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.
@@ -835,12 +835,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.
@@ -1030,7 +1030,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 +1275,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:',
@@ -2731,9 +2731,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 +2980,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 +3142,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 */',
@@ -3206,6 +3207,7 @@ Xin '''ĐỪNG''' điền gì vào!",
 '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',
@@ -3810,7 +3812,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ả',
@@ -3913,6 +3915,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',
@@ -4054,7 +4057,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]].',
@@ -4080,7 +4083,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ị:',
index 11b0ea3..0019952 100644 (file)
@@ -1010,7 +1010,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 a2868eb..019ee08 100644 (file)
@@ -2183,7 +2183,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',
@@ -2695,7 +2695,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',
index 3998ef4..b21667c 100644 (file)
@@ -898,7 +898,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..8f9695f 100644 (file)
@@ -1649,7 +1649,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 +2105,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',
index 52b3202..bc2295d 100644 (file)
@@ -1803,7 +1803,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 +2128,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 14db086..ab280d9 100644 (file)
@@ -2076,7 +2076,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',
@@ -2341,7 +2341,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',
@@ -2442,7 +2442,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..ef55c2e 100644 (file)
@@ -2097,7 +2097,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..60606bf 100644 (file)
@@ -12,7 +12,9 @@
  * @author O
  * @author Reedy
  * @author Wu-chinese.com
+ * @author Xiaomingyan
  * @author Yfdyh000
+ * @author 乌拉跨氪
  * @author 十弌
  */
 
@@ -839,7 +841,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' => "'''只有'''出现下头眼情况再应阻止访问:
@@ -1342,7 +1344,7 @@ $1",
 
 # Book sources
 'booksources' => '书源',
-'booksources-search-legend' => '搜索网络书源',
+'booksources-search-legend' => '搜索图书来源',
 'booksources-go' => '去',
 
 # Special:Log
@@ -1665,7 +1667,7 @@ $1",
 'tooltip-rollback' => '揿一记“回转”就回退到上一位贡献者个编辑状态',
 'tooltip-undo' => '“撤销”可以恢复该编辑并且垃拉预览模式下头打开编辑表单。渠允许垃拉摘要里向说明原因。',
 'tooltip-summary' => '打进短摘要',
-'tooltip-iwiki' => '̩$1 - $2',
+'interlanguage-link-title' => '̩$1 - $2',
 
 # Attribution
 'anonymous' => '{{SITENAME}}浪个匿名用户',
@@ -1739,7 +1741,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..6ed1f28 100644 (file)
@@ -1166,7 +1166,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..fe9c8e0 100644 (file)
@@ -883,7 +883,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 1910ca5..688f52b 100644 (file)
@@ -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}}.
@@ -733,7 +733,8 @@ $2',
 
 דערפֿאַר קענען באַזוכער וואס באַניצן דעם  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' => 'אורזאַך:',
@@ -1481,6 +1483,8 @@ $1",
 'userrights-notallowed' => 'איר האט נישט קיין ערלויבניש צוצולייגן אדער אוועקנעמען באַניצער רעכטן.',
 'userrights-changeable-col' => 'גרופעס איר קענט ענדערן',
 'userrights-unchangeable-col' => 'גרופעס איר קענט נישט ענדערן',
+'userrights-conflict' => 'קאנפֿליקט פון באניצער־רעכטן ענדערונגען! זייט אזוי גוט רעצענזירן און באשטעטיקן אײַערע ענדערונגען.',
+'userrights-removed-self' => 'איר האט דערפאלגרייך אראפגענומען אייערע אייגענע רעכטע. אזוי קענט איר מער נישט דערגרייכן דעם בלאט.',
 
 # Groups
 'group' => 'גרופע:',
@@ -1543,6 +1547,7 @@ $1",
 'right-blockemail' => 'בלאקירן א באַניצער פֿון שיקן ע־פאסט',
 'right-hideuser' => 'בלאקירן באַניצער־נאָמען און פֿאַרבארגן אים',
 'right-ipblock-exempt' => 'ארומגיין IP בלאקן, אויטאבלאקן און גרייך־בלאקן',
+'right-proxyunbannable' => 'ארומגיין אויטאמאטישע בלאקירן פון פראקסיס',
 'right-unblockself' => 'זיך אליין אויפֿשפאַרן',
 'right-protect' => 'ענדערן שוץ ניוואען און רעדאַגירן קאסקאד־געשיצטע בלעטער',
 'right-editprotected' => 'רעדאַגירן בלעטער געשיצט ווי "{{int:protect-level-sysop}}"',
@@ -1554,6 +1559,7 @@ $1",
 'right-editmyusercss' => 'רעדאקטירע אײַערע אייגענע באניצער CSS טעקעס',
 'right-editmyuserjs' => 'רעדאקטירן אײַערע אייגענע באניצער JavaScript טעקעס',
 'right-viewmywatchlist' => 'באקוקן אייער אייגענע אויפפאסונג ליסטע',
+'right-editmywatchlist' => 'רעדאקטירן אייער אייגענע אויפפאסונג ליסטער. טייל פעולות וועלן דאך צולייגן בלעטער אפילו אן דעם רעכט.',
 'right-viewmyprivateinfo' => 'באקוקן אײַער אייגענע פריוואטע דאטן (צ"ב ע־פאסט אדרעס, אמתער נאמען)',
 'right-editmyprivateinfo' => 'רעדאקטירן אײַער אייגענע פריוואטע דאטן (צ"ב ע־פאסט אדרעס, אמתער נאמען)',
 'right-editmyoptions' => 'רעדאקטירן אײַערע אייגענע פרעפערענצן',
@@ -2098,6 +2104,7 @@ $1",
 'listusers' => 'באַניצער ליסטע',
 'listusers-editsonly' => 'ווייזן נאר באניצערס מיט רעדאקטירונגען',
 'listusers-creationsort' => 'סארטירן לויט דער שאַפן דאַטע',
+'listusers-desc' => 'סארטירן אין אראפרשטייגעדיקן סדר',
 'usereditcount' => '{{PLURAL:$1|רעדאַקטירונג|$1 רעדאַקטירונגען}}',
 'usercreated' => '{{GENDER:$3|געשאַפֿן}} אום $2, $1',
 'newpages' => 'נייע בלעטער',
@@ -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' => 'פֿילטערן לויטן סטאטוס פון מעלדונג:',
@@ -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' => 'אַלע',
index 1d2c0b2..1b4338a 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ọ́',
@@ -460,10 +460,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 +498,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 +563,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 +587,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 +607,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 +644,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 +737,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 +998,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íẹ̀:',
@@ -1192,7 +1189,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 +1246,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',
@@ -2685,7 +2682,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:',
@@ -3284,7 +3281,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 +3443,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ú',
index d048e58..7bd19a2 100644 (file)
@@ -2470,7 +2470,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' => '以自定狀況過濾:',
@@ -3039,7 +3039,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' => '全部',
@@ -3205,7 +3205,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條款規定,就本程式再發佈同/或修改;無論你根據嘅係呢個牌照嘅第二版或(任你揀)任一日之後發行嘅版本。
 
index c14af62..720d5c5 100644 (file)
@@ -1319,7 +1319,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 cf98e7a..469c941 100644 (file)
@@ -25,6 +25,7 @@
  * @author Fantasticfears
  * @author Fengchao
  * @author Franklsf95
+ * @author Gakmo
  * @author Gaoxuewei
  * @author GeneralNFS
  * @author Gzdavidwong
@@ -511,7 +512,7 @@ $messages = array(
 'mytalk' => '讨论',
 'anontalk' => '该IP地址的讨论',
 'navigation' => '导航',
-'and' => '和',
+'and' => '&#32;和',
 
 # Cologne Blue skin
 'qbfind' => '查找',
@@ -681,8 +682,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}}]]找到。',
 
@@ -728,10 +729,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',
@@ -754,7 +754,7 @@ $2',
 'customjsprotected' => '您没有权限编辑此JavaScript页面,因为它包含另一位用户的个人设置。',
 'mycustomcssprotected' => '您没有权限编辑这个 CSS 页面。',
 'mycustomjsprotected' => '您没有权限编辑这个 JavaScript 页面。',
-'myprivateinfoprotected' => '您没有权限来编辑您的私人信息。',
+'myprivateinfoprotected' => '你没有权限编辑你的私人信息。',
 'mypreferencesprotected' => '您没有权限来编辑您的个人设置。',
 'ns-specialprotected' => '特殊页面不可编辑。',
 'titleprotected' => '此标题已被[[User:$1|$1]]保护以防止创建。理由是“$2”。',
@@ -810,12 +810,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' => '电子邮件地址',
@@ -826,11 +825,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|页面}}',
@@ -869,12 +868,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' => '邮箱地址格式不正确,请输入正确的邮箱地址或清空该输入框。',
@@ -948,8 +949,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' => '当前电子邮件地址:',
@@ -1145,10 +1146,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',
@@ -1158,8 +1159,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' => '包含着略过模板参数的页面',
@@ -1253,20 +1254,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' => 'å\90¦',
+'revdelete-radio-same' => '(不更改)',
+'revdelete-radio-set' => '隐藏',
+'revdelete-radio-unset' => 'å\8f¯è§\81',
 'revdelete-suppress' => '同时阻止管理员与其他用户查看数据',
 'revdelete-unsuppress' => '在已恢复的修订中移除限制',
 'revdelete-log' => '原因:',
@@ -1395,13 +1396,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' => '全选',
@@ -1420,7 +1421,7 @@ $1",
 'prefs-skin' => '皮肤',
 'skin-preview' => '预览',
 'datedefault' => '默认格式',
-'prefs-beta' => '测试特性',
+'prefs-beta' => '测试功能',
 'prefs-datetime' => '日期时间',
 'prefs-labs' => '实验室特性',
 'prefs-user-pages' => '用户页面',
@@ -1492,7 +1493,7 @@ $1",
 'yourrealname' => '真实姓名:',
 'yourlanguage' => '语言:',
 'yourvariant' => '内容语言变种:',
-'prefs-help-variant' => '您希望用于显示本站内容的语种或拼写语系。',
+'prefs-help-variant' => '你希望用于显示该wiki的内容页面的语言变种或正字法。',
 'yournick' => '新签名:',
 'prefs-help-signature' => '讨论页面上的评论应该使用“<nowiki>~~~~</nowiki>”签名,它会自动转换为你的签名及时间戳。',
 'badsig' => '错误的原始签名。请检查HTML标签。',
@@ -1506,7 +1507,7 @@ $1",
 该信息将会公开。',
 'email' => '电子邮件',
 'prefs-help-realname' => '真实姓名是选填项目。如果你选择提供它,它将会用于贡献署名。',
-'prefs-help-email' => '电子邮件地址是选填项目,但是当你忘记密码需要重置密码时需要该项信息。',
+'prefs-help-email' => '电子邮件是可选项,但是在您忘记密码时很有用。',
 'prefs-help-email-others' => '你也可以选择让其他用户通过你的用户或讨论页面上的链接用电子邮件联系你。其他用户联系你时你的电子邮件地址不会显示。',
 'prefs-help-email-required' => '电子邮件地址是必填项目。',
 'prefs-info' => '基本信息',
@@ -1602,7 +1603,7 @@ $1",
 'right-bot' => '被视为自动过程',
 'right-nominornewtalk' => '不使小编辑在讨论页面引发新信息提示',
 'right-apihighlimits' => '在API查询中使用更高的限制',
-'right-writeapi' => '使用书写API',
+'right-writeapi' => '使用写入API',
 'right-delete' => '删除页面',
 'right-bigdelete' => '删除有大型历史的页面',
 'right-deletelogentry' => '删除和恢复特定的日志项目',
@@ -1626,12 +1627,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' => '标记回退编辑为机器人编辑',
@@ -1673,7 +1674,7 @@ $1",
 'action-reupload' => '覆盖本文件',
 'action-reupload-shared' => '覆盖共享文件库的本文件',
 'action-upload_by_url' => '从URL上传本文件',
-'action-writeapi' => '使用书写API',
+'action-writeapi' => '使用写入API',
 'action-delete' => '删除本页',
 'action-deleterevision' => '删除本版本',
 'action-deletedhistory' => '查看本页面被删除的历史',
@@ -1697,7 +1698,7 @@ $1",
 'action-editmywatchlist' => '编辑你的监视列表',
 'action-viewmywatchlist' => '查看你的监视列表',
 'action-viewmyprivateinfo' => '查看您的私人信息',
-'action-editmyprivateinfo' => '编辑的私人信息',
+'action-editmyprivateinfo' => '编辑的私人信息',
 
 # Recent changes
 'nchanges' => '$1个更改',
@@ -1970,7 +1971,7 @@ $1',
 'upload_source_file' => '(您计算机上的一个文件)',
 
 # Special:ListFiles
-'listfiles-summary' => '本特殊页面示所有上传的文件。',
+'listfiles-summary' => '本特殊页面示所有上传的文件。',
 'listfiles_search_for' => '按媒体名称搜索:',
 'imgfile' => '文件',
 'listfiles' => '文件列表',
@@ -1978,7 +1979,7 @@ $1',
 'listfiles_date' => '日期',
 'listfiles_name' => '名称',
 'listfiles_user' => '用户',
-'listfiles_size' => '大å°\8f',
+'listfiles_size' => '尺寸',
 'listfiles_description' => '说明',
 'listfiles_count' => '版本',
 'listfiles-show-all' => '包括图片的旧版本',
@@ -2070,7 +2071,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
@@ -2078,11 +2079,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' => '随机重定向',
@@ -2103,37 +2104,37 @@ $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字节',
@@ -2147,7 +2148,7 @@ $1',
 'ntransclusions' => '用于$1个页面中',
 'specialpage-empty' => '无该报告的结果。',
 'lonelypages' => '孤立页面',
-'lonelypagestext' => '以下页面尚未被{{SITENAME}}中的其它页面链接或被之包含。',
+'lonelypagestext' => '以下页面没有被{{SITENAME}}的其它页面链接或包含。',
 'uncategorizedpages' => '未归类页面',
 'uncategorizedcategories' => '未归类分类',
 'uncategorizedimages' => '未归类文件',
@@ -2159,30 +2160,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' => '只显示有编辑的用户',
@@ -2195,9 +2196,8 @@ $1',
 'ancientpages' => '最老页面',
 'move' => '移动',
 'movethispage' => '移动本页',
-'unusedimagestext' => '下列文件已存在,但并未插入任何页面。
-请注意其它网站可能会直接通过URL链接此文件,因此下面列出的文件依然有可能被使用。',
-'unusedcategoriestext' => '虽然没有被其它页面或者分类所采用,但列表中的分类页依然存在。',
+'unusedimagestext' => '以下文件实际存在,但并没有插入任何页面。请注意,其他网站可能会使用直接URL链接某个文件,因此它即使被实际使用也可能在这里列出。',
+'unusedcategoriestext' => '以下分类页面实际存在,即使没有其它页面或分类利用它们。',
 'notargettitle' => '无目标',
 'notargettext' => '您还没有指定一个目标页面或用户以进行此项操作。',
 'nopagetitle' => '无目标页面',
@@ -2212,7 +2212,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
@@ -2230,18 +2230,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前的缓存版本。',
@@ -2250,10 +2250,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' => '按字母排列',
 
@@ -2289,8 +2287,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>',
@@ -2524,8 +2521,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)
@@ -2902,7 +2899,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' => '按自定义状态过滤:',
@@ -3008,14 +3005,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' => '如果相同的标题存在的话便直接前往该页面',
@@ -3062,7 +3060,7 @@ $2',
 'tooltip-undo' => '“撤销”可以恢复该编辑并在预览模式下打开编辑表单。它允许在摘要中加入原因。',
 'tooltip-preferences-save' => '保存系统设置',
 'tooltip-summary' => '请输入简短的摘要',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* 此处的 CSS 将应用于所有的皮肤 */',
@@ -3127,14 +3125,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' => '页面创建日期',
@@ -3200,17 +3199,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' => '完分辨率',
+'show-big-image' => '完分辨率',
 'show-big-image-preview' => '本预览的尺寸:$1。',
 'show-big-image-other' => '其他{{PLURAL:$2|分辨率}}:$1。',
 'show-big-image-size' => '$1×$2像素',
@@ -3703,7 +3702,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' => '所有',
@@ -3745,8 +3744,7 @@ $5
 确认码会在$4过期。',
 'confirmemail_body_changed' => '拥有IP地址$1的用户(可能是您)在{{SITENAME}}更改了账户“$2”的电子邮箱地址。
 
-请确认这个账户是属于您的,并同时重新激活在{{SITENAME}}上的电子邮件功能。请
-在浏览器中打开下面的链接:
+要确认此账户确实属于您并同时激活在{{SITENAME}}的电子邮件功能,请在浏览器中打开下面的链接:
 
 $3
 
@@ -3800,6 +3798,7 @@ $5
 'colon-separator' => ':',
 'word-separator' => '',
 'parentheses' => '($1)',
+'quotation-marks' => '“$1”',
 
 # Multipage image navigation
 'imgmultipageprev' => '← 上一页',
@@ -3886,7 +3885,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]]作出的贡献。',
@@ -3938,7 +3937,7 @@ MediaWiki发表时预期有用,但对此'''无任何保证''',亦无隐含
 'specialpages-group-changes' => '最近更改与日志',
 'specialpages-group-media' => '媒体文件报告与上传',
 'specialpages-group-users' => '用户与权限',
-'specialpages-group-highuse' => '高使用页面',
+'specialpages-group-highuse' => '高使用页面',
 'specialpages-group-pages' => '页面列表',
 'specialpages-group-pagetools' => '页面工具',
 'specialpages-group-wiki' => '数据与工具',
@@ -4109,7 +4108,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' => '该文件可能损坏或扩展名错误。',
index 4da841d..2d1a7f8 100644 (file)
@@ -54,6 +54,7 @@
  * @author Xiaomingyan
  * @author Yfdyh000
  * @author Yuyu
+ * @author 乌拉跨氪
  */
 
 $fallback = 'zh-hans';
@@ -721,7 +722,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}}登錄。
@@ -783,14 +784,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' => '郵箱地址格式不正確,請輸入正確的郵箱位址或清空該輸入框。',
@@ -1199,19 +1202,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' => '理由:',
@@ -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' => '基本資料',
@@ -2196,7 +2200,7 @@ $1',
 'allpagesprev' => '前',
 'allpagesnext' => '後',
 'allpagessubmit' => '提交',
-'allpagesprefix' => '顯示具有此前綴(名字空間)的頁面:',
+'allpagesprefix' => '顯示有此前綴的頁面:',
 'allpagesbadtitle' => '給定的頁面標題是非法的,或者具有一個內部語言或內部 wiki 的前綴。它可能包含一個或更多的不能用於標題的字元。',
 'allpages-bad-ns' => '在{{SITENAME}}中沒有一個叫做「$1」的名字空間。',
 'allpages-hide-redirects' => '隱藏重定向頁',
@@ -2877,7 +2881,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,7 +3043,7 @@ $2',
 'tooltip-undo' => '「復原」可以在編輯模式上開啟編輯表格以便恢復。它容許在摘要中加入原因。',
 'tooltip-preferences-save' => '儲存使用偏好',
 'tooltip-summary' => '輸入一個簡短的摘要',
-'tooltip-iwiki' => '$1 – $2',
+'interlanguage-link-title' => '$1 – $2',
 
 # Stylesheets
 'common.css' => '/* 此處的 CSS 將應用於所有的面板 */',
@@ -3085,7 +3089,7 @@ $2',
 'spam_reverting' => '恢復到不包含連結至$1的最近修訂版本',
 'spam_blanking' => '所有包含連結至$1的修訂,清空',
 'spam_deleting' => '所有包含連結至$1的修訂,刪除中',
-'simpleantispam-label' => "反垃圾檢查。
+'simpleantispam-label' => "反濫發電郵檢查。
 '''不要'''加入這個!",
 
 # Info page
@@ -3100,6 +3104,7 @@ $2',
 'pageinfo-length' => '頁面長度 (以位元組為單位)',
 'pageinfo-article-id' => '頁面編號',
 'pageinfo-language' => '頁面內容語言',
+'pageinfo-content-model' => '頁面內容模型',
 'pageinfo-robot-policy' => '機械人索引',
 'pageinfo-robot-index' => '容許',
 'pageinfo-robot-noindex' => '阻止',
@@ -3672,7 +3677,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' => '全部',
@@ -3770,6 +3775,7 @@ $5
 'colon-separator' => ':',
 'word-separator' => '',
 'parentheses' => '($1)',
+'quotation-marks' => '“$1”',
 
 # Multipage image navigation
 'imgmultipageprev' => '← 上一頁',
@@ -3856,7 +3862,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]]作出的貢獻。',
@@ -3876,7 +3882,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' => '值:',
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..8fdb958 100644 (file)
@@ -126,7 +126,7 @@ class TextPassDumper extends BackupDumper {
 
                // 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() . ")" );
                }
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..49af0b8 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 ) );
@@ -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 3bd508c..3157318 100644 (file)
@@ -98,7 +98,7 @@ if ( $maintenance->getDbType() === Maintenance::DB_ADMIN &&
 
 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 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 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..4e845f1 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 267666d..746f14f 100644 (file)
@@ -484,7 +484,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 1ac9500..09bd302 100644 (file)
@@ -287,7 +287,6 @@ $wgMessageStructure = array(
                'disclaimerpage',
                'edithelp',
                'edithelppage',
-               'help',
                'helppage',
                'mainpage',
                'mainpage-description',
@@ -1090,7 +1089,6 @@ $wgMessageStructure = array(
                'prefs-namespaces',
                'defaultns',
                'default',
-               'defaultns',
                'prefs-files',
                'prefs-custom-css',
                'prefs-custom-js',
@@ -1517,7 +1515,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',
@@ -1769,7 +1766,6 @@ $wgMessageStructure = array(
                'nmembers',
                'nrevisions',
                'nviews',
-               'nchanges',
                'nimagelinks',
                'ntransclusions',
                'specialpage-empty',
@@ -2724,7 +2720,7 @@ $wgMessageStructure = array(
                'tooltip-undo',
                'tooltip-preferences-save',
                'tooltip-summary',
-               'tooltip-iwiki',
+               'interlanguage-link-title',
        ),
        'stylesheets' => array(
                'common.css',
@@ -2788,6 +2784,7 @@ $wgMessageStructure = array(
                'pageinfo-length',
                'pageinfo-article-id',
                'pageinfo-language',
+               'pageinfo-content-model',
                'pageinfo-robot-policy',
                'pageinfo-robot-index',
                'pageinfo-robot-noindex',
@@ -3522,6 +3519,7 @@ $wgMessageStructure = array(
                'percent',
                'parentheses',
                'brackets',
+               'quotation-marks',
        ),
        'imgmulti' => array(
                'imgmultipageprev',
@@ -3582,9 +3580,6 @@ $wgMessageStructure = array(
                'lag-warn-normal',
                'lag-warn-high',
        ),
-       'watch' => array(
-               'confirm-watch-button',
-       ),
        'watchlisteditor' => array(
                'editwatchlist-summary',
                'watchlistedit-numitems',
@@ -3820,9 +3815,6 @@ $wgMessageStructure = array(
                'sqlite-has-fts',
                'sqlite-no-fts',
        ),
-       'unwatch' => array(
-               'confirm-unwatch-button',
-       ),
        'logging' => array(
                'logentry-delete-delete',
                'logentry-delete-restore',
@@ -3881,8 +3873,6 @@ $wgMessageStructure = array(
                'newuserlog-create-entry',
                'newuserlog-create2-entry',
                'newuserlog-autocreate-entry',
-               'suppressedarticle',
-               'deletedarticle',
                // 'uploadedimage',
                // 'overwroteimage',
                'rightslogentry',
@@ -3986,244 +3976,247 @@ $wgMessageStructure = array(
 
 /** 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' => '',
+       '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',
 );
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 {
index 34e6428..f991c1b 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 {
@@ -99,7 +102,7 @@ class MoveBatch extends Maintenance {
 
                        $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 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 9f83ee7..c21301b 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() {
@@ -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 ) );
 
@@ -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 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 315176c..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',
@@ -185,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',
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 af01a30..14468f3 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
@@ -1519,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 5c93964..e39661a 100644 (file)
@@ -180,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 543094a..f5cd2d6 100644 (file)
@@ -1050,7 +1050,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(
@@ -1131,7 +1134,6 @@ return array(
                'remoteBasePath' => $GLOBALS['wgStylePath'],
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
                'dependencies' => array(
-                       'mediawiki.legacy.wikibits',
                        'jquery.byteLimit',
                ),
                'position' => 'top',
@@ -1152,9 +1154,9 @@ return array(
                'remoteBasePath' => $GLOBALS['wgStylePath'],
                'localBasePath' => $GLOBALS['wgStyleDirectory'],
                'dependencies' => array(
+                       'jquery.spinner',
                        'mediawiki.api',
                        'mediawiki.Title',
-                       'mediawiki.legacy.wikibits',
                        'mediawiki.util',
                ),
        ),
@@ -1169,8 +1171,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 8044d88..abada19 100644 (file)
@@ -6,7 +6,7 @@
  * @author Trevor Parscal <tparscal@wikimedia.org>, 2012
  * @author Krinkle <krinklemail@gmail.com>, 2012
  * @version 0.2.0
- * @license GPL v2
+ * @license MIT
  */
 ( function ( $ ) {
 
index 93e30b9..27dabc6 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:
                 *
                 * 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
+                * 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
+                * - .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' });
                 *
-                * @param {Object|String} opts [optional] ID string or options:
-                *  - id: If given, spinner will be given an id of "mw-spinner-<id>"
+                * @static
+                * @inheritable
+                * @param {Object|string} [opts] 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
                },
 
                /**
-                * 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
+        *
+        * Inserts spinner as siblings, not children, of the target elements.
+        * Collection contents remain unchanged.
         *
-        * @param {Object|String} opts See createSpinner() for description.
+        * @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 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
                                        );
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..10d36ff
--- /dev/null
@@ -0,0 +1,69 @@
+@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;
+
+       // Content styling
+       vertical-align: middle;
+
+       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..4ed7261
--- /dev/null
@@ -0,0 +1,51 @@
+@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;
+}
+
+.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 4a64566..dde5abf 100644 (file)
                /**
                 * Get the URL to this title
                 *
-                * @see mw.util#wikiGetlink
+                * @see mw.util#getUrl
                 * @return {string}
                 */
                getUrl: function () {
-                       return mw.util.wikiGetlink( this.toString() );
+                       return mw.util.getUrl( this.toString() );
                },
 
                /**
index 668aa2a..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
 
                                // 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 9267a49..8a8215d 100644 (file)
@@ -75,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;
        }
 
@@ -1749,6 +1749,38 @@ var mw = ( function ( $, undefined ) {
                                        // Cache hit stats
                                        stats: { hits: 0, misses: 0, expired: 0 },
 
+                                       // Experiment data
+                                       experiment: ( function () {
+                                               var start = ( new Date() ).getTime(), id = 0, seed = 0;
+
+                                               try {
+                                                       id = JSON.parse( localStorage.getItem( 'moduleStorageExperiment' ) );
+                                                       if ( typeof id !== 'number' ) {
+                                                               id = Math.floor( Math.random() * Math.random() * 1e16 );
+                                                               localStorage.setItem( 'moduleStorageExperiment', id );
+                                                       }
+                                                       seed = id % 2000;
+                                               } catch ( e ) {}
+
+                                               return {
+                                                       // Unique identifier for this browser. This allows us to group all
+                                                       // datapoints generated by a particular browser, which in turn allows us
+                                                       // to see how the initial load compares to subsequent page loads.
+                                                       id: id,
+
+                                                       // Group assignment may be 0 (not in experiment), 1 (control group), or 2
+                                                       // (experimental group). Browsers that don't implement all the prerequisite APIs
+                                                       // (JSON and Web Storage) are ineligible. Eligible browsers have a 0.1% chance
+                                                       // of being included in the experiment, in which case they are equally likely to
+                                                       // be assigned to either the experimental or control group.
+                                                       group: seed === 1 ? 1 : ( seed === 2 ? 2 : 0 ),
+
+                                                       // Assess module storage performance by measuring the time between this
+                                                       // reference point and the window load event.
+                                                       start: start
+                                               };
+                                       }() ),
+
                                        /**
                                         * Construct a JSON-serializable object representing the content of the store.
                                         * @return {Object} Module store contents.
@@ -1799,20 +1831,19 @@ var mw = ( function ( $, undefined ) {
                                         * code for a full account of why we need a try / catch: <http://git.io/4NEwKg>.
                                         */
                                        init: function () {
-                                               var raw, data, optedIn;
+                                               var raw, data;
 
                                                if ( mw.loader.store.enabled !== null ) {
                                                        // #init already ran.
                                                        return;
                                                }
 
-                                               // Temporarily allow users to opt-in during mw.loader.store test phase by
-                                               // manually setting a cookie (bug 56397).
-                                               optedIn = /ResourceLoaderStorageEnabled=1/.test( document.cookie );
-
-                                               if ( !( mw.config.get( 'wgResourceLoaderStorageEnabled' ) || optedIn ) || mw.config.get( 'debug' ) ) {
-                                                       // Disabled by configuration, or because debug mode is set.
-                                                       mw.loader.store.enabled = false;
+                                               if (
+                                                       // We're in debug mode
+                                                       mw.config.get( 'debug' ) ||
+                                                       // Module storage is neither enabled by default, nor enabled for this user's group.
+                                                       !( mw.config.get( 'wgResourceLoaderStorageEnabled' ) || mw.loader.store.experiment.group === 2 )
+                                               ) {
                                                        return;
                                                }
 
@@ -1944,14 +1975,19 @@ var mw = ( function ( $, undefined ) {
                                                var timer;
 
                                                function flush() {
-                                                       var data;
+                                                       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( mw.loader.store.getStoreKey(), data );
+                                                               localStorage.setItem( key, data );
                                                        } catch (e) {}
                                                }
 
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..a057cce 100644 (file)
                 *     e.g. { action: 'edit' }. Optional.
                 * @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 ) );
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 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 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 65db555..d28ca0a 100644 (file)
@@ -89,17 +89,17 @@ mw.log.deprecate( win, 'ie6_bugs', false, msg );
 msg = 'Use jQuery instead';
 
 // Ignored dummy values
-mw.log.deprecate( win, 'doneOnloadHook', undefined );
-mw.log.deprecate( win, 'onloadFuncts', [] );
-mw.log.deprecate( win, 'runOnloadHook', $.noop );
-mw.log.deprecate( win, 'changeText', $.noop );
-mw.log.deprecate( win, 'killEvt', $.noop );
-mw.log.deprecate( win, 'addHandler', $.noop );
-mw.log.deprecate( win, 'hookEvent', $.noop );
-mw.log.deprecate( win, 'addClickHandler', $.noop );
-mw.log.deprecate( win, 'removeHandler', $.noop );
-mw.log.deprecate( win, 'getElementsByClassName', function () { return []; } );
-mw.log.deprecate( win, 'getInnerText', function () { return ''; } );
+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 ) {
@@ -110,7 +110,7 @@ mw.log.deprecate( win, 'addOnloadHook', function ( hookFunct ) {
                // run immediately instead of queueing.
                hookFunct();
        }
-} );
+}, msg );
 
 $( win ).on( 'load', function () {
        var i, functs;
@@ -198,7 +198,7 @@ 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 );
+mw.log.deprecate( win, 'appendCSS', mw.util.addCSS, msg );
 
 /**
  * Wikipage import methods
index f8be097..4651b48 100644 (file)
@@ -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;
 }
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 dec8e22..46a894c 100644 (file)
@@ -89,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 13312bb..cc935da 100644 (file)
@@ -11709,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
@@ -14922,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
index 8c849bc..6ce78b5 100644 (file)
@@ -537,6 +537,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
index c749598..7f9a023 100644 (file)
@@ -24,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 );
diff --git a/tests/phpunit/includes/CdbTest.php b/tests/phpunit/includes/CdbTest.php
deleted file mode 100644 (file)
index 4832ada..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-/**
- * Test the CDB reader/writer
- * @covers CdbWriter_PHP
- * @covers CdbWriter_DBA
- */
-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 )
-               );
-       }
-}
diff --git a/tests/phpunit/includes/ExceptionTest.php b/tests/phpunit/includes/ExceptionTest.php
new file mode 100644 (file)
index 0000000..9e76045
--- /dev/null
@@ -0,0 +1,118 @@
+<?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 08d6ba8..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 );
        }
@@ -71,10 +75,15 @@ 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' );
        }
 
        /**
index 6154df1..868090e 100644 (file)
@@ -143,7 +143,7 @@ class GlobalTest extends MediaWikiTestCase {
 
 
        /**
-        * @covers ::testWfArrayDiff2
+        * @covers ::wfArrayToCgi
         */
        public function testArrayToCGI2() {
                $this->assertEquals(
index 41230a1..b06f3d2 100644 (file)
@@ -7,19 +7,13 @@ class WfExpandUrlTest extends MediaWikiTestCase {
         * @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 );
        }
 
diff --git a/tests/phpunit/includes/HashRingTest.php b/tests/phpunit/includes/HashRingTest.php
deleted file mode 100644 (file)
index 68dfea1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<?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/IPTest.php b/tests/phpunit/includes/IPTest.php
deleted file mode 100644 (file)
index c074eea..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
-        */
-       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/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/SpecialPageTest.php b/tests/phpunit/includes/SpecialPageTest.php
new file mode 100644 (file)
index 0000000..fb8f7ad
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @covers SpecialPage
+ *
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class SpecialPageTest extends MediaWikiTestCase {
+
+       public function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       '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' )
+               );
+       }
+
+}
diff --git a/tests/phpunit/includes/StringUtilsTest.php b/tests/phpunit/includes/StringUtilsTest.php
deleted file mode 100644 (file)
index 89759e5..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
-        */
-       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" ),
-               );
-       }
-}
index fb63a56..b0d1726 100644 (file)
@@ -11,11 +11,11 @@ class TemplateCategoriesTest extends MediaWikiLangTestCase {
         * @covers Title::getParentCategories
         */
        public function testTemplateCategories() {
-               $title = Title::newFromText( "Categorized from template" );
-               $page = WikiPage::factory( $title );
                $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'
+               );
+
        }
 }
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" );
-               }
-       }
-
-}
index f8ed14b..06ed1fd 100644 (file)
@@ -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'
+                       ),
                );
        }
 
@@ -277,6 +299,14 @@ class WebRequestTest extends MediaWikiTestCase {
         * @covers WebRequest::getIP
         */
        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();
diff --git a/tests/phpunit/includes/ZipDirectoryReaderTest.php b/tests/phpunit/includes/ZipDirectoryReaderTest.php
deleted file mode 100644 (file)
index 2627a41..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 );
-       }
-
-       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' );
-       }
-}
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"
+               );
+       }
+
+}
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" ) );
+       }
+
+}
diff --git a/tests/phpunit/includes/api/ApiTest.php b/tests/phpunit/includes/api/ApiTest.php
deleted file mode 100644 (file)
index 472f8c4..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-<?php
-
-/**
- * @group API
- * @group Database
- * @group medium
- */
-class ApiTest extends ApiTestCase {
-
-       public function testRequireOnlyOneParameterDefault() {
-               $mock = new MockApi();
-
-               $this->assertEquals(
-                       null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
-                       "enablechunks" => false ), "filename", "enablechunks" ) );
-       }
-
-       /**
-        * @expectedException UsageException
-        */
-       public function testRequireOnlyOneParameterZero() {
-               $mock = new MockApi();
-
-               $this->assertEquals(
-                       null, $mock->requireOnlyOneParameter( array( "filename" => "foo.txt",
-                       "enablechunks" => 0 ), "filename", "enablechunks" ) );
-       }
-
-       /**
-        * @expectedException UsageException
-        */
-       public 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
-        */
-       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" ) );
-       }
-
-       /**
-        * 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 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;
-       }
-
-       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'] );
-
-               return $data;
-       }
-
-       public 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;
-       }
-}
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 );
+               }
+       }
+
+}
index 2cf6dca..d075f54 100644 (file)
@@ -8,6 +8,9 @@
  */
 class ApiFormatWddxTest extends ApiFormatTestBase {
 
+       /**
+        * @requires function wddx_deserialize
+        */
        public function testValidSyntax( ) {
                $data = $this->apiRequest( 'wddx', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
 
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 75a7278..7c62dca 100644 (file)
@@ -79,6 +79,8 @@ class WikitextContentHandlerTest extends MediaWikiLangTestCase {
                global $wgContLang;
                $wgContLang->resetNamespaces();
 
+               MagicWord::clearCache();
+
                if ( is_string( $title ) ) {
                        $title = Title::newFromText( $title );
                }
index 134f856..2162a02 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 ) {}
@@ -123,4 +125,87 @@ class DatabaseMysqlBaseTest extends MediaWikiTestCase {
                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 70ee946..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" )
+               );
        }
 
        /**
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..f0203d4
--- /dev/null
@@ -0,0 +1,85 @@
+<?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 78929e2..aa09def 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'
+               );
        }
 
        /**
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 f5ff1d9..733368d 100644 (file)
@@ -1,6 +1,6 @@
 <?php
-class AutoLoaderTest extends MediaWikiTestCase {
 
+class AutoLoaderTest extends MediaWikiTestCase {
        protected function setUp() {
                global $wgAutoloadLocalClasses, $wgAutoloadClasses;
 
@@ -13,7 +13,7 @@ class AutoLoaderTest extends MediaWikiTestCase {
                        'TestAutoloadedSerializedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedSerializedClass.php',
                );
                $this->setMwGlobals( 'wgAutoloadLocalClasses', $this->testLocalClasses + $wgAutoloadLocalClasses );
-               InstrumentedAutoLoader::resetAutoloadLocalClassesLower();
+               AutoLoader::resetAutoloadLocalClassesLower();
 
                $this->testExtensionClasses = array(
                        'TestAutoloadedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedClass.php',
@@ -93,12 +93,3 @@ class AutoLoaderTest extends MediaWikiTestCase {
                        "unserialize() can load classes case-insensitively.");
        }
 }
-
-/**
- * Cheater to poke protected members
- */
-class InstrumentedAutoLoader extends AutoLoader {
-       static function resetAutoloadLocalClassesLower() {
-               self::$autoloadLocalClassesLower = null;
-       }
-}
index fe823fa..746cb70 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,14 +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 13c0efc..f0bb0fc 100644 (file)
                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 functionally, getUrl uses mw.util.getUrl' );
 
                title = new mw.Title( 'John Doe', 3 );
                assert.equal( title.getUrl(), '/wiki/User_talk:John_Doe', 'Escaping in title and namespace for urls' );
index e0e823d..be362e2 100644 (file)
@@ -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 913adc1..35ab9f2 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
@@ -235,14 +244,6 @@ 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.