Merge "User.php: Update 'setEmailWithConfirmation' for notification email"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sun, 10 Apr 2016 05:30:11 +0000 (05:30 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sun, 10 Apr 2016 05:30:11 +0000 (05:30 +0000)
790 files changed:
.jscsrc
RELEASE-NOTES-1.27
autoload.php
composer.json
docs/contenthandler.txt
docs/extension.schema.json
docs/hooks.txt
docs/injection.txt [new file with mode: 0644]
docs/memcached.txt
includes/Block.php
includes/Collation.php [deleted file]
includes/DefaultSettings.php
includes/EditPage.php
includes/Fallback.php [deleted file]
includes/FauxRequest.php
includes/GitInfo.php
includes/GlobalFunctions.php
includes/HistoryBlob.php
includes/Html.php
includes/HtmlFormatter.php
includes/HttpFunctions.php
includes/Linker.php
includes/MediaWiki.php
includes/MediaWikiServices.php [new file with mode: 0644]
includes/MergeHistory.php
includes/Message.php
includes/MimeMagic.php
includes/MovePage.php
includes/OutputPage.php
includes/Preferences.php
includes/Revision.php
includes/Sanitizer.php
includes/ServiceWiring.php [new file with mode: 0644]
includes/Services/ServiceContainer.php [new file with mode: 0644]
includes/Setup.php
includes/SiteStats.php
includes/StubObject.php
includes/TemplateParser.php
includes/Title.php
includes/WatchedItem.php
includes/WatchedItemStore.php
includes/WebRequest.php
includes/WikiMap.php
includes/actions/Action.php
includes/actions/InfoAction.php
includes/actions/PurgeAction.php
includes/api/ApiBase.php
includes/api/ApiMain.php
includes/api/ApiPageSet.php
includes/api/ApiPurge.php
includes/api/ApiQuery.php
includes/api/ApiQueryExtLinksUsage.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryStashImageInfo.php
includes/api/ApiQueryTokens.php
includes/api/ApiQueryUserInfo.php
includes/api/ApiResult.php
includes/api/i18n/ar.json
includes/api/i18n/ast.json
includes/api/i18n/ba.json
includes/api/i18n/be-tarask.json
includes/api/i18n/bn.json
includes/api/i18n/cs.json
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/eo.json [new file with mode: 0644]
includes/api/i18n/es.json
includes/api/i18n/fa.json
includes/api/i18n/fr.json
includes/api/i18n/gl.json
includes/api/i18n/he.json
includes/api/i18n/hu.json
includes/api/i18n/id.json
includes/api/i18n/it.json
includes/api/i18n/ja.json
includes/api/i18n/ko.json
includes/api/i18n/ksh.json
includes/api/i18n/mg.json
includes/api/i18n/nap.json
includes/api/i18n/pl.json
includes/api/i18n/pt.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/uk.json
includes/api/i18n/vi.json
includes/api/i18n/zh-hans.json
includes/cache/BacklinkCache.php
includes/cache/LCStoreStaticArray.php [deleted file]
includes/cache/LocalisationCache.php [deleted file]
includes/cache/localisation/LCStore.php [new file with mode: 0644]
includes/cache/localisation/LCStoreCDB.php [new file with mode: 0644]
includes/cache/localisation/LCStoreDB.php [new file with mode: 0644]
includes/cache/localisation/LCStoreNull.php [new file with mode: 0644]
includes/cache/localisation/LCStoreStaticArray.php [new file with mode: 0644]
includes/cache/localisation/LocalisationCache.php [new file with mode: 0644]
includes/cache/localisation/LocalisationCacheBulkLoad.php [new file with mode: 0644]
includes/changes/ChangesList.php
includes/changes/EnhancedChangesList.php
includes/changes/OldChangesList.php
includes/changes/RecentChange.php
includes/changetags/ChangeTagsLogItem.php
includes/collation/Collation.php [new file with mode: 0644]
includes/collation/CollationCkb.php [new file with mode: 0644]
includes/collation/CollationEt.php [new file with mode: 0644]
includes/collation/IcuCollation.php [new file with mode: 0644]
includes/collation/IdentityCollation.php [new file with mode: 0644]
includes/collation/UppercaseCollation.php [new file with mode: 0644]
includes/config/ConfigFactory.php
includes/content/ContentHandler.php
includes/content/TextContentHandler.php
includes/db/DatabaseMysqlBase.php
includes/db/DatabaseMysqli.php
includes/db/DatabasePostgres.php
includes/db/loadbalancer/LoadBalancer.php
includes/debug/logger/monolog/LineFormatter.php
includes/debug/logger/monolog/WikiProcessor.php
includes/diff/DifferenceEngine.php
includes/exception/MWException.php
includes/exception/MWExceptionHandler.php
includes/exception/PermissionsError.php
includes/export/XmlDumpWriter.php
includes/filebackend/SwiftFileBackend.php
includes/filerepo/FileRepo.php
includes/filerepo/LocalRepo.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/htmlform/HTMLAutoCompleteSelectField.php
includes/htmlform/HTMLButtonField.php
includes/htmlform/HTMLCheckField.php
includes/htmlform/HTMLCheckMatrix.php
includes/htmlform/HTMLComboboxField.php
includes/htmlform/HTMLEditTools.php
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLFormField.php
includes/htmlform/HTMLFormFieldCloner.php
includes/htmlform/HTMLFormFieldWithButton.php
includes/htmlform/HTMLMultiSelectField.php
includes/htmlform/HTMLRadioField.php
includes/htmlform/HTMLSelectAndOtherField.php
includes/htmlform/HTMLSelectField.php
includes/htmlform/HTMLTextAreaField.php
includes/htmlform/HTMLTextField.php
includes/htmlform/HTMLTitleTextField.php
includes/htmlform/HTMLUserTextField.php
includes/htmlform/VFormHTMLForm.php
includes/import/WikiImporter.php
includes/import/WikiRevision.php
includes/installer/CliInstaller.php
includes/installer/DatabaseInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/MssqlInstaller.php
includes/installer/MssqlUpdater.php
includes/installer/MysqlUpdater.php
includes/installer/OracleUpdater.php
includes/installer/PostgresInstaller.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/WebInstaller.php
includes/installer/WebInstallerComplete.php
includes/installer/WebInstallerInstall.php
includes/installer/WebInstallerName.php
includes/installer/WebInstallerOptions.php
includes/installer/i18n/ar.json
includes/installer/i18n/ast.json
includes/installer/i18n/ba.json
includes/installer/i18n/be-tarask.json
includes/installer/i18n/bn.json
includes/installer/i18n/ce.json
includes/installer/i18n/cs.json
includes/installer/i18n/de.json
includes/installer/i18n/en.json
includes/installer/i18n/eo.json
includes/installer/i18n/es.json
includes/installer/i18n/fa.json
includes/installer/i18n/fi.json
includes/installer/i18n/fr.json
includes/installer/i18n/gl.json
includes/installer/i18n/ia.json
includes/installer/i18n/inh.json [new file with mode: 0644]
includes/installer/i18n/is.json
includes/installer/i18n/it.json
includes/installer/i18n/ja.json
includes/installer/i18n/jbo.json [new file with mode: 0644]
includes/installer/i18n/ka.json
includes/installer/i18n/ko.json
includes/installer/i18n/lt.json
includes/installer/i18n/lv.json
includes/installer/i18n/mg.json
includes/installer/i18n/mk.json
includes/installer/i18n/pl.json
includes/installer/i18n/ps.json
includes/installer/i18n/pt-br.json
includes/installer/i18n/pt.json
includes/installer/i18n/qqq.json
includes/installer/i18n/ru.json
includes/installer/i18n/sr-ec.json
includes/installer/i18n/sr-el.json
includes/installer/i18n/tt-cyrl.json
includes/installer/i18n/uk.json
includes/installer/i18n/vi.json
includes/installer/i18n/yi.json
includes/installer/i18n/zh-hans.json
includes/installer/i18n/zh-hant.json
includes/jobqueue/Job.php
includes/jobqueue/JobRunner.php
includes/jobqueue/JobSpecification.php
includes/jobqueue/utils/BacklinkJobUtils.php
includes/libs/BufferingStatsdDataFactory.php [deleted file]
includes/libs/Cookie.php
includes/libs/CookieJar.php [new file with mode: 0644]
includes/libs/MWMessagePack.php
includes/libs/StatusValue.php
includes/libs/StringUtils.php
includes/libs/eventrelayer/EventRelayer.php
includes/libs/eventrelayer/EventRelayerNull.php [new file with mode: 0644]
includes/libs/objectcache/CachedBagOStuff.php
includes/libs/objectcache/WANObjectCache.php
includes/libs/stats/BufferingStatsdDataFactory.php [new file with mode: 0644]
includes/libs/stats/NullStatsdDataFactory.php [new file with mode: 0644]
includes/libs/stats/StatsdAwareInterface.php [new file with mode: 0644]
includes/logging/BlockLogFormatter.php
includes/logging/LogEntry.php
includes/logging/LogEventsList.php
includes/logging/LogPager.php
includes/logging/PatrolLog.php
includes/logging/PatrolLogFormatter.php
includes/mail/EmailNotification.php
includes/mail/UserMailer.php
includes/media/Bitmap.php
includes/media/Bitmap_ClientOnly.php
includes/media/DjVu.php
includes/media/MediaTransformOutput.php
includes/media/SVG.php
includes/media/SVGMetadataExtractor.php
includes/media/TransformationalImageHandler.php
includes/media/WebP.php
includes/media/XCF.php
includes/page/Article.php
includes/page/ImagePage.php
includes/page/Page.php [new file with mode: 0644]
includes/page/WikiPage.php
includes/pager/ReverseChronologicalPager.php
includes/pager/TablePager.php
includes/parser/CoreParserFunctions.php
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserOptions.php
includes/parser/Preprocessor.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/poolcounter/PoolCounter.php
includes/registration/ExtensionProcessor.php
includes/registration/ExtensionRegistry.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderContext.php
includes/resourceloader/ResourceLoaderImage.php
includes/resourceloader/ResourceLoaderRawFileModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/resourceloader/ResourceLoaderUserTokensModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/revisiondelete/RevDelLogItem.php
includes/search/SearchEngine.php
includes/search/SearchExactMatchRescorer.php
includes/search/SearchSuggestion.php
includes/session/BotPasswordSessionProvider.php
includes/session/Session.php
includes/session/SessionBackend.php
includes/session/SessionId.php
includes/session/SessionManager.php
includes/session/SessionManagerInterface.php
includes/session/SessionProvider.php
includes/site/DBSiteStore.php
includes/site/HashSiteStore.php
includes/site/MediaWikiSite.php
includes/site/SiteSQLStore.php
includes/skins/Skin.php
includes/skins/SkinTemplate.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialActiveusers.php
includes/specials/SpecialAllMessages.php
includes/specials/SpecialBlockList.php
includes/specials/SpecialBotPasswords.php
includes/specials/SpecialCategories.php
includes/specials/SpecialChangeContentModel.php
includes/specials/SpecialChangePassword.php
includes/specials/SpecialConfirmemail.php
includes/specials/SpecialContributions.php
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialEditWatchlist.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialFileDuplicateSearch.php
includes/specials/SpecialJavaScriptTest.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListDuplicatedFiles.php
includes/specials/SpecialListfiles.php
includes/specials/SpecialListusers.php
includes/specials/SpecialLog.php
includes/specials/SpecialMediaStatistics.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialNewimages.php
includes/specials/SpecialNewpages.php
includes/specials/SpecialPasswordReset.php
includes/specials/SpecialProtectedpages.php
includes/specials/SpecialProtectedtitles.php
includes/specials/SpecialRandomInCategory.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRecentchangeslinked.php
includes/specials/SpecialRedirect.php
includes/specials/SpecialSearch.php
includes/specials/SpecialStatistics.php
includes/specials/SpecialTags.php
includes/specials/SpecialUnblock.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUploadStash.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWatchlist.php
includes/specials/SpecialWhatlinkshere.php
includes/specials/pagers/ActiveUsersPager.php [new file with mode: 0644]
includes/specials/pagers/AllMessagesTablePager.php [new file with mode: 0644]
includes/specials/pagers/BlockListPager.php [new file with mode: 0644]
includes/specials/pagers/CategoryPager.php [new file with mode: 0644]
includes/specials/pagers/ContribsPager.php [new file with mode: 0644]
includes/specials/pagers/DeletedContribsPager.php [new file with mode: 0644]
includes/specials/pagers/ImageListPager.php [new file with mode: 0644]
includes/specials/pagers/MergeHistoryPager.php [new file with mode: 0644]
includes/specials/pagers/NewFilesPager.php [new file with mode: 0644]
includes/specials/pagers/NewPagesPager.php [new file with mode: 0644]
includes/specials/pagers/ProtectedTitlesPager.php [new file with mode: 0644]
includes/specials/pagers/UsersPager.php [new file with mode: 0644]
includes/templates/Usercreate.php
includes/templates/Userlogin.php
includes/upload/UploadBase.php
includes/upload/UploadFromChunks.php
includes/upload/UploadFromUrl.php
includes/upload/UploadStash.php
includes/user/BotPassword.php
includes/user/LoggedOutEditToken.php
includes/user/User.php
includes/utils/BatchRowIterator.php
includes/utils/IP.php
includes/utils/MWCryptHash.php
includes/utils/ZipDirectoryReader.php
languages/Language.php
languages/classes/LanguageFi.php
languages/data/Names.php
languages/data/ZhConversion.php
languages/i18n/af.json
languages/i18n/an.json
languages/i18n/ar.json
languages/i18n/arq.json
languages/i18n/ast.json
languages/i18n/azb.json
languages/i18n/ba.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bgn.json
languages/i18n/bn.json
languages/i18n/bs.json
languages/i18n/ca.json
languages/i18n/cdo.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/crh-cyrl.json
languages/i18n/crh-latn.json
languages/i18n/cs.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/frp.json
languages/i18n/frr.json
languages/i18n/fy.json
languages/i18n/ga.json
languages/i18n/gl.json
languages/i18n/gom-latn.json
languages/i18n/grc.json
languages/i18n/gsw.json
languages/i18n/gu.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hu.json
languages/i18n/hy.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/ilo.json
languages/i18n/inh.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/jut.json
languages/i18n/ka.json
languages/i18n/khw.json
languages/i18n/kk-cyrl.json
languages/i18n/kn.json
languages/i18n/ko.json
languages/i18n/ksh.json
languages/i18n/la.json
languages/i18n/lb.json
languages/i18n/lij.json
languages/i18n/lki.json
languages/i18n/lrc.json
languages/i18n/lt.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/mai.json
languages/i18n/mg.json
languages/i18n/min.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/mr.json
languages/i18n/ms.json
languages/i18n/my.json
languages/i18n/nan.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/oc.json
languages/i18n/or.json
languages/i18n/pdc.json
languages/i18n/pl.json
languages/i18n/ps.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/sa.json
languages/i18n/sah.json
languages/i18n/sh.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/sv.json
languages/i18n/ta.json
languages/i18n/te.json
languages/i18n/tl.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/uk.json
languages/i18n/uz.json
languages/i18n/vep.json
languages/i18n/vi.json
languages/i18n/wa.json
languages/i18n/war.json
languages/i18n/wuu.json
languages/i18n/xal.json
languages/i18n/xmf.json
languages/i18n/yi.json
languages/i18n/yue.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesAf.php
languages/messages/MessagesAn.php
languages/messages/MessagesAr.php
languages/messages/MessagesArc.php
languages/messages/MessagesArz.php
languages/messages/MessagesAzb.php
languages/messages/MessagesBcl.php
languages/messages/MessagesBe.php
languages/messages/MessagesBg.php
languages/messages/MessagesBs.php
languages/messages/MessagesCe.php
languages/messages/MessagesCkb.php
languages/messages/MessagesCs.php
languages/messages/MessagesCy.php
languages/messages/MessagesDe.php
languages/messages/MessagesDiq.php
languages/messages/MessagesEl.php
languages/messages/MessagesEn.php
languages/messages/MessagesEo.php
languages/messages/MessagesEs.php
languages/messages/MessagesEt.php
languages/messages/MessagesFa.php
languages/messages/MessagesFi.php
languages/messages/MessagesFr.php
languages/messages/MessagesFrp.php
languages/messages/MessagesGa.php
languages/messages/MessagesGl.php
languages/messages/MessagesHe.php
languages/messages/MessagesHi.php
languages/messages/MessagesHr.php
languages/messages/MessagesHu.php
languages/messages/MessagesHy.php
languages/messages/MessagesId.php
languages/messages/MessagesIt.php
languages/messages/MessagesJa.php
languages/messages/MessagesKa.php
languages/messages/MessagesKm.php
languages/messages/MessagesKo.php
languages/messages/MessagesKsh.php
languages/messages/MessagesKw.php
languages/messages/MessagesLb.php
languages/messages/MessagesLt.php
languages/messages/MessagesMg.php
languages/messages/MessagesMhr.php
languages/messages/MessagesMk.php
languages/messages/MessagesMl.php
languages/messages/MessagesMr.php
languages/messages/MessagesMt.php
languages/messages/MessagesMyv.php
languages/messages/MessagesNds.php
languages/messages/MessagesNl.php
languages/messages/MessagesNn.php
languages/messages/MessagesOc.php
languages/messages/MessagesOr.php
languages/messages/MessagesOs.php
languages/messages/MessagesPl.php
languages/messages/MessagesPs.php
languages/messages/MessagesPt.php
languages/messages/MessagesQu.php
languages/messages/MessagesRm.php
languages/messages/MessagesRo.php
languages/messages/MessagesRu.php
languages/messages/MessagesSa.php
languages/messages/MessagesSe.php
languages/messages/MessagesSh.php
languages/messages/MessagesSk.php
languages/messages/MessagesSl.php
languages/messages/MessagesSq.php
languages/messages/MessagesSv.php
languages/messages/MessagesTr.php
languages/messages/MessagesUk.php
languages/messages/MessagesUr.php
languages/messages/MessagesVi.php
languages/messages/MessagesYi.php
load.php
maintenance/Maintenance.php
maintenance/archives/patch-add-cl_collation_ext_index.sql [new file with mode: 0644]
maintenance/archives/patch-categorylinks-better-collation.sql
maintenance/archives/patch-kill-cl_collation_index.sql [new file with mode: 0644]
maintenance/archives/patch-watchlist-wl_id.sql [new file with mode: 0644]
maintenance/benchmarks/bench_utf8_title_check.php
maintenance/cleanupUploadStash.php
maintenance/commandLine.inc
maintenance/createAndPromote.php
maintenance/dictionary/mediawiki.dic
maintenance/dumpBackup.php
maintenance/exportSites.php
maintenance/importImages.php
maintenance/importSites.php
maintenance/language/checkDupeMessages.php
maintenance/language/checkLanguage.php
maintenance/language/digit2html.php
maintenance/language/generateUtf8Case.php [deleted file]
maintenance/language/transstat.php
maintenance/language/zhtable/Makefile.py
maintenance/language/zhtable/toCN.manual
maintenance/language/zhtable/toHK.manual
maintenance/language/zhtable/toTW.manual
maintenance/language/zhtable/toTrad.manual
maintenance/language/zhtable/trad2simp.manual
maintenance/language/zhtable/tradphrases.manual
maintenance/language/zhtable/tradphrases_exclude.manual
maintenance/mcc.php
maintenance/mctest.php
maintenance/mergeMessageFileList.php
maintenance/mssql/archives/patch-watchlist-wl_id.sql [new file with mode: 0644]
maintenance/mssql/tables.sql
maintenance/namespaceDupes.php
maintenance/oracle/archives/patch-watchlist-wl_id.sql [new file with mode: 0644]
maintenance/oracle/tables.sql
maintenance/parse.php
maintenance/postgres/tables.sql
maintenance/preprocessorFuzzTest.php
maintenance/rebuildSitesCache.php
maintenance/refreshImageMetadata.php
maintenance/resetUserEmail.php
maintenance/sqlite.php
maintenance/sqlite/archives/patch-watchlist-wl_id.sql [new file with mode: 0644]
maintenance/storage/checkStorage.php
maintenance/storage/fixBug20757.php
maintenance/storage/moveToExternal.php
maintenance/tables.sql
maintenance/update.php
maintenance/updateCollation.php
maintenance/updateSearchIndex.php
package.json
phpcs.xml
resources/Resources.php
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js [new file with mode: 0644]
resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js [new file with mode: 0644]
resources/lib/oojs-ui/i18n/azb.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/ba.json
resources/lib/oojs-ui/i18n/hi.json
resources/lib/oojs-ui/i18n/ka.json
resources/lib/oojs-ui/i18n/khw.json [new file with mode: 0644]
resources/lib/oojs-ui/i18n/nan.json
resources/lib/oojs-ui/i18n/sah.json
resources/lib/oojs-ui/i18n/zh-hant.json
resources/lib/oojs-ui/oojs-ui-apex.js
resources/lib/oojs-ui/oojs-ui-core-apex.css
resources/lib/oojs-ui/oojs-ui-core-mediawiki.css
resources/lib/oojs-ui/oojs-ui-core.js
resources/lib/oojs-ui/oojs-ui-mediawiki.js
resources/lib/oojs-ui/oojs-ui-toolbars-apex.css
resources/lib/oojs-ui/oojs-ui-toolbars-mediawiki.css
resources/lib/oojs-ui/oojs-ui-toolbars.js
resources/lib/oojs-ui/oojs-ui-widgets-apex.css
resources/lib/oojs-ui/oojs-ui-widgets-mediawiki.css
resources/lib/oojs-ui/oojs-ui-widgets.js
resources/lib/oojs-ui/oojs-ui-windows-apex.css
resources/lib/oojs-ui/oojs-ui-windows-mediawiki.css
resources/lib/oojs-ui/oojs-ui-windows.js
resources/lib/oojs-ui/themes/apex/icons-content.json
resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/icons-content.json
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.png
resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.svg
resources/lib/qunitjs/qunit.css
resources/lib/qunitjs/qunit.js
resources/lib/sinonjs/sinon-1.15.4.js [deleted file]
resources/lib/sinonjs/sinon-1.17.3.js [new file with mode: 0644]
resources/lib/sinonjs/sinon-ie-1.15.4.js [deleted file]
resources/src/jquery/jquery.makeCollapsible.js
resources/src/jquery/jquery.suggestions.js
resources/src/jquery/jquery.tablesorter.js
resources/src/mediawiki.action/mediawiki.action.view.postEdit.js
resources/src/mediawiki.language/mediawiki.language.js
resources/src/mediawiki.language/specialcharacters.json
resources/src/mediawiki.special/mediawiki.special.apisandbox.js
resources/src/mediawiki.special/mediawiki.special.userlogin.common.css
resources/src/mediawiki.special/mediawiki.special.userlogin.login.css
resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
resources/src/mediawiki/api.js
resources/src/mediawiki/api/parse.js
resources/src/mediawiki/mediawiki.Title.js
resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
resources/src/mediawiki/mediawiki.js
resources/src/mediawiki/mediawiki.requestIdleCallback.js
resources/src/mediawiki/mediawiki.user.js
resources/src/mediawiki/mediawiki.util.js
resources/src/mediawiki/mediawiki.viewport.js
resources/src/mediawiki/page/image-pagination.js
resources/src/mediawiki/page/watch.js
serialized/Makefile
serialized/Utf8Case.ser [deleted file]
tests/TestsAutoLoader.php
tests/parser/extraParserTests.txt
tests/parser/parserTest.inc
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/BlockTest.php
tests/phpunit/includes/FallbackTest.php [deleted file]
tests/phpunit/includes/FauxResponseTest.php
tests/phpunit/includes/HtmlTest.php
tests/phpunit/includes/HttpTest.php
tests/phpunit/includes/LinkerTest.php
tests/phpunit/includes/MediaWikiServicesTest.php [new file with mode: 0644]
tests/phpunit/includes/MergeHistoryTest.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/PathRouterTest.php
tests/phpunit/includes/PrefixSearchTest.php
tests/phpunit/includes/RevisionStorageTest.php
tests/phpunit/includes/RevisionTest.php
tests/phpunit/includes/Services/ServiceContainerTest.php [new file with mode: 0644]
tests/phpunit/includes/Services/TestWiring1.php [new file with mode: 0644]
tests/phpunit/includes/Services/TestWiring2.php [new file with mode: 0644]
tests/phpunit/includes/TitlePermissionTest.php
tests/phpunit/includes/WatchedItemStoreIntegrationTest.php
tests/phpunit/includes/WatchedItemStoreUnitTest.php
tests/phpunit/includes/WatchedItemUnitTest.php
tests/phpunit/includes/XmlTest.php
tests/phpunit/includes/api/ApiBlockTest.php
tests/phpunit/includes/api/ApiLoginTest.php
tests/phpunit/includes/api/ApiUploadTest.php
tests/phpunit/includes/api/UserWrapper.php
tests/phpunit/includes/api/format/ApiFormatPhpTest.php
tests/phpunit/includes/api/format/ApiFormatXmlTest.php
tests/phpunit/includes/api/query/ApiQueryBasicTest.php
tests/phpunit/includes/api/query/ApiQueryContinue2Test.php
tests/phpunit/includes/api/query/ApiQueryContinueTest.php
tests/phpunit/includes/cache/GenderCacheTest.php
tests/phpunit/includes/cache/LocalisationCacheTest.php
tests/phpunit/includes/cache/MessageCacheTest.php
tests/phpunit/includes/changes/CategoryMembershipChangeTest.php
tests/phpunit/includes/config/ConfigFactoryTest.php
tests/phpunit/includes/content/CssContentHandlerTest.php
tests/phpunit/includes/content/JavaScriptContentHandlerTest.php
tests/phpunit/includes/content/JavaScriptContentTest.php
tests/phpunit/includes/content/TextContentTest.php
tests/phpunit/includes/context/RequestContextTest.php
tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
tests/phpunit/includes/db/DatabaseSqliteTest.php
tests/phpunit/includes/debug/logger/monolog/AvroFormatterTest.php
tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php
tests/phpunit/includes/deferred/LinksUpdateTest.php
tests/phpunit/includes/exception/HttpErrorTest.php
tests/phpunit/includes/filebackend/FileBackendTest.php
tests/phpunit/includes/filerepo/FileBackendDBRepoWrapperTest.php
tests/phpunit/includes/filerepo/file/FileTest.php
tests/phpunit/includes/filerepo/file/LocalFileTest.php
tests/phpunit/includes/import/ImportTest.php
tests/phpunit/includes/jobqueue/JobTest.php
tests/phpunit/includes/jobqueue/jobs/CategoryMembershipChangeJobTest.php
tests/phpunit/includes/libs/CSSMinTest.php
tests/phpunit/includes/libs/StringUtilsTest.php
tests/phpunit/includes/media/BitmapMetadataHandlerTest.php
tests/phpunit/includes/media/GIFTest.php
tests/phpunit/includes/media/MediaWikiMediaTestCase.php
tests/phpunit/includes/media/PNGTest.php
tests/phpunit/includes/media/WebPTest.php
tests/phpunit/includes/page/WikiPageTest.php
tests/phpunit/includes/parser/NewParserTest.php
tests/phpunit/includes/parser/PreprocessorTest.php
tests/phpunit/includes/password/BcryptPasswordTest.php
tests/phpunit/includes/password/LayeredParameterizedPasswordTest.php
tests/phpunit/includes/password/PasswordPolicyChecksTest.php
tests/phpunit/includes/password/UserPasswordPolicyTest.php
tests/phpunit/includes/search/SearchEnginePrefixTest.php
tests/phpunit/includes/search/SearchEngineTest.php
tests/phpunit/includes/session/BotPasswordSessionProviderTest.php
tests/phpunit/includes/session/CookieSessionProviderTest.php
tests/phpunit/includes/session/ImmutableSessionProviderWithCookieTest.php
tests/phpunit/includes/session/PHPSessionHandlerTest.php
tests/phpunit/includes/session/SessionBackendTest.php
tests/phpunit/includes/session/SessionInfoTest.php
tests/phpunit/includes/session/SessionManagerTest.php
tests/phpunit/includes/session/SessionProviderTest.php
tests/phpunit/includes/session/SessionTest.php
tests/phpunit/includes/session/TestUtils.php
tests/phpunit/includes/session/TokenTest.php
tests/phpunit/includes/site/DBSiteStoreTest.php
tests/phpunit/includes/site/SiteSQLStoreTest.php [deleted file]
tests/phpunit/includes/site/TestSites.php
tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
tests/phpunit/includes/specials/SpecialEditWatchlistTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/SpecialMyLanguageTest.php
tests/phpunit/includes/specials/SpecialPageExecutor.php [new file with mode: 0644]
tests/phpunit/includes/specials/SpecialPageTestBase.php
tests/phpunit/includes/specials/SpecialWatchlistTest.php [new file with mode: 0644]
tests/phpunit/includes/upload/UploadBaseTest.php
tests/phpunit/includes/user/BotPasswordTest.php
tests/phpunit/includes/user/LocalIdLookupTest.php
tests/phpunit/includes/utils/MWCryptHKDFTest.php
tests/phpunit/includes/utils/UIDGeneratorTest.php
tests/phpunit/languages/LanguageTest.php
tests/phpunit/maintenance/backupTextPassTest.php
tests/phpunit/maintenance/backup_LogTest.php
tests/phpunit/maintenance/backup_PageTest.php
tests/phpunit/phpunit.php
tests/phpunit/skins/SideBarTest.php
tests/phpunit/structure/ApiDocumentationTest.php
tests/phpunit/structure/ExtensionJsonValidationTest.php [new file with mode: 0644]
tests/phpunit/suites/ExtensionsTestSuite.php
tests/phpunit/suites/UploadFromUrlTestSuite.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.requestIdleCallback.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.viewport.test.js

diff --git a/.jscsrc b/.jscsrc
index 116c5cf..f3db218 100644 (file)
--- a/.jscsrc
+++ b/.jscsrc
@@ -4,7 +4,6 @@
 
        "requireVarDeclFirst": null,
 
-       "disallowQuotedKeysInObjects": "allButReserved",
        "requireDotNotation": { "allExcept": [ "keywords" ] },
        "jsDoc": {
                "checkAnnotations": {
index 302e20a..a6dfecc 100644 (file)
@@ -7,9 +7,17 @@ production.
 
 === PHP version requirement ===
 As of 1.27, MediaWiki now requires PHP 5.5.9 or higher. This corresponds with
-HHVM 3.1.
+HHVM 3.1. Additionally, the following PHP extensions are required:
+* ctype
+* iconv
+* json
+* mbstring
+* xml
 
 === Configuration changes in 1.27 ===
+* $wgAllowMicrodataAttributes and $wgAllowRdfaAttributes were removed,
+  now always enabled. If you use RDFa on your wiki, you now have to explicitly
+  set $wgHtml5Version to 'HTML+RDFa 1.0' or 'XHTML+RDFa 1.0'.
 * $wgUseLinkNamespaceDBFields was removed.
 * Deprecated $wgResourceLoaderMinifierStatementsOnOwnLine and
   $wgResourceLoaderMinifierMaxLineLength, because there was little value in
@@ -98,6 +106,14 @@ HHVM 3.1.
 * $wgEnotifUseJobQ was removed and the job queue is always used.
 * The functionality of the ApiSandbox extension has been merged into core. The
   extension should no longer be used.
+* $wgPreloadJavaScriptMwUtil was removed (deprecated in 1.26).
+  Extensions, skins, gadgets and scripts that use the mediawiki.util module must
+  express a dependency on it.
+* $wgIncludeLegacyJavaScript, deprecated in MediaWiki 1.26, now defaults false.
+  Extensions, skins, gadgets and scripts that need the mediawiki.legacy.wikibits
+  module should express a dependency on it.
+* Removed configuration option $wgCopyrightIcon (deprecated since 1.18). Use
+  $wgFooterIcons['copyright']['copyright'] instead.
 
 === New features in 1.27 ===
 * $wgDataCenterUpdateStickTTL was also added. This decides how long a user
@@ -166,13 +182,20 @@ HHVM 3.1.
   be a good idea, but will log out all current sessions.
 * $wgEventRelayerConfig was added, for managing PubSub event relay configuration,
   specifically for reliable CDN url purges.
+* Requests have unique IDs, equal to the UNIQUE_ID environment variable (when
+  MediaWiki is behind Apache+mod_unique_id or something similar) or a randomly-
+  generated 24-character string. This request ID is used to annotate log records
+  and error messages. It is available client-side via mw.config.get( 'wgRequestId' ).
+  The request ID supplants exception IDs. Accordingly, MWExceptionHandler::getLogId()
+  is deprecated.
 
 === External library changes in 1.27 ===
 
 ==== Upgraded external libraries ====
 * Updated oojs/oojs-ui from v0.12.12 to v0.13.3.
 * Updated composer/semver from v1.0.0 to v1.2.0.
-* Update liuggio/statsd-php-client to 1.0.18.
+* Updated liuggio/statsd-php-client to 1.0.18.
+* Updated QUnit from v1.18.0 to v1.22.0.
 
 ==== New external libraries ====
 * Added wikimedia/base-convert v1.0.1.
@@ -213,6 +236,16 @@ HHVM 3.1.
 ** ApiFormatDbg
 ** ApiFormatTxt
 ** ApiFormatYaml
+* ApiBase::addTokenProperties() was removed (deprecated since 1.24).
+* ApiBase::getFinalPossibleErrors() was removed (deprecated since 1.24).
+* ApiBase::getFinalResultProperties() was removed (deprecated since 1.24).
+* ApiBase::getRequireAtLeastOneParameterErrorMessages() was removed (deprecated since 1.24).
+* ApiBase::getPossibleErrors() was removed (deprecated since 1.24).
+* ApiBase::getRequireMaxOneParameterErrorMessages() was removed (deprecated since 1.24).
+* ApiBase::getRequireOnlyOneParameterErrorMessages() was removed (deprecated since 1.24).
+* ApiBase::getResultProperties() was removed (deprecated since 1.24).
+* ApiBase::getTitleOrPageIdErrorMessage() was removed (deprecated since 1.24).
+* ApiBase::parseErrors() was removed (deprecated since 1.24).
 * ApiQueryBase::titleToKey(), ApiQueryBase::keyToTitle() and
   ApiQueryBase::keyPartToTitle() all removed (deprecated since 1.24).
 * ApiQueryBase::checkRowCount() was removed (deprecated since 1.24).
@@ -223,15 +256,11 @@ HHVM 3.1.
 * ApiQuery::setGeneratorContinue() was removed (deprecated since 1.24).
 * ApiMain::getModules() was removed (deprecated since 1.21).
 * ApiBase::getVersion() was removed (deprecated since 1.21).
-* Language::getLangObj() was removed (deprecated since 1.24).
-* Language::getLanguageName() was removed (deprecated since 1.20).
-* Language::getLanguageNames() was removed (deprecated since 1.20).
-* Language::getTranslatedLanguageNames() was removed (deprecated since 1.20).
-* Language::specialPage() was removed (deprecated since 1.24).
-* OutputPage::getHeadItems() was removed (deprecated since 1.24).
-* OutputPage::getScript() was removed (deprecated since 1.24).
-* OutputPage::out() was removed (deprecated since 1.22).
-* OutputPage::setAllowedModules() was removed (deprecated since 1.24).
+* ApiMain::getShowVersions() was removed (deprecated in 1.21).
+* ApiMain::addModule() was removed (deprecated in 1.21).
+* ApiMain::addFormat() was removed (deprecated in 1.21).
+* ApiMain::getFormats() was removed (deprecated in 1.21).
+* ApiPageSet::finishPageSetGeneration() was removed (deprecated in 1.21).
 
 === Languages updated in 1.27 ===
 
@@ -240,8 +269,12 @@ regularly. Below only new and removed languages are listed, as well as
 changes to languages because of Phabricator reports.
 
 * (T113688) Change default numerals from Gurmukhi to Arabic for Punjabi locale.
+* (T116020) Aliases of magic words in MessagesXx.php are sorted by usage.
 
 === Other changes in 1.27 ===
+* Added dependency injection (DI) infrastructure, see docs/injection.txt for details.
+  It is planned to incrementally move MediaWiki code towards using DI, using the
+  service locator (SL) pattern as a stepping stone.
 * ProfilerOutputUdp was removed. Note that there is a ProfilerOutputStats class.
 * WikiPage::doDeleteArticleReal() and WikiPage::doDeleteArticle() now
   ignore the 2nd and 3rd arguments (formerly $id and $commit).
@@ -348,6 +381,37 @@ changes to languages because of Phabricator reports.
 ** WatchedItem::duplicateEntries was deprecated.
 ** EmailNotification::updateWatchlistTimestamp was deprecated.
 ** User::getWatchedItem was removed.
+* Unit tests don't work with external PHPUnit anymore, Composer is now the only supported
+  way. Run `composer install` to install it and other dev dependencies to run unit tests.
+* wl_id field added to the watchlist table.
+* Revision::getRawText() was removed (deprecated since 1.21).
+* WikiPage::replaceSection() was removed (deprecated since 1.21).
+* Article::replaceSection() was removed (deprecated since 1.21).
+* Language::getLangObj() was removed (deprecated since 1.24).
+* Language::getLanguageName() was removed (deprecated since 1.20).
+* Language::getLanguageNames() was removed (deprecated since 1.20).
+* Language::getTranslatedLanguageNames() was removed (deprecated since 1.20).
+* Language::specialPage() was removed (deprecated since 1.24).
+* MediaWikiTestCase::assertException() was removed (deprecated since 1.22).
+* OutputPage::getHeadItems() was removed (deprecated since 1.24).
+* OutputPage::getScript() was removed (deprecated since 1.24).
+* OutputPage::out() was removed (deprecated since 1.22).
+* OutputPage::setAllowedModules() was removed (deprecated since 1.24).
+* UserrightsPage::makeGroupNameListForLog() was removed (deprecated since 1.21).
+* MediaWikiSite::newFromGlobalId() was removed (deprecated since 1.21).
+* Title::newFromRedirect() was removed (deprecated since 1.21).
+* Skin::commonPrintStylesheet() was removed (deprecated since 1.22).
+* Skin::getCommonStylePath() was removed (deprecated since 1.24).
+* Skin::newFromKey() was removed (deprecated since 1.24).
+* Skin::getUsableSkins() was removed (deprecated since 1.23).
+* LoadBalancer::pickRandom() was removed (deprecated in 1.21).
+* Article::getUndoText() and WikiPage::getUndoText were removed (deprecated since
+  1.21).
+* DifferenceEngine::setText() was removed (deprecated in 1.21).
+* Title::newFromRedirectArray() was removed (deprecated in 1.21).
+* UserMailer::send() no longer accepts $replyto as the 5th argument and $contentType
+  as the 6th. These must be passed in the options array now.
+* Title::newFromRedirectRecurse() was removed (deprecated in 1.21).
 
 == Compatibility ==
 
index e74df0a..c3e988c 100644 (file)
@@ -7,11 +7,11 @@ $wgAutoloadLocalClasses = [
        'APCBagOStuff' => __DIR__ . '/includes/libs/objectcache/APCBagOStuff.php',
        'AbstractContent' => __DIR__ . '/includes/content/AbstractContent.php',
        'Action' => __DIR__ . '/includes/actions/Action.php',
-       'ActiveUsersPager' => __DIR__ . '/includes/specials/SpecialActiveusers.php',
+       'ActiveUsersPager' => __DIR__ . '/includes/specials/pagers/ActiveUsersPager.php',
        'ActivityUpdateJob' => __DIR__ . '/includes/jobqueue/jobs/ActivityUpdateJob.php',
        'AjaxDispatcher' => __DIR__ . '/includes/AjaxDispatcher.php',
        'AjaxResponse' => __DIR__ . '/includes/AjaxResponse.php',
-       'AllMessagesTablePager' => __DIR__ . '/includes/specials/SpecialAllMessages.php',
+       'AllMessagesTablePager' => __DIR__ . '/includes/specials/pagers/AllMessagesTablePager.php',
        'AllTrans' => __DIR__ . '/maintenance/language/alltrans.php',
        'AlphabeticPager' => __DIR__ . '/includes/pager/AlphabeticPager.php',
        'AlterSharedConstraints' => __DIR__ . '/maintenance/oracle/alterSharedConstraints.php',
@@ -180,12 +180,12 @@ $wgAutoloadLocalClasses = [
        'BitmapMetadataHandler' => __DIR__ . '/includes/media/BitmapMetadataHandler.php',
        'Blob' => __DIR__ . '/includes/db/DatabaseUtility.php',
        'Block' => __DIR__ . '/includes/Block.php',
-       'BlockListPager' => __DIR__ . '/includes/specials/SpecialBlockList.php',
+       'BlockListPager' => __DIR__ . '/includes/specials/pagers/BlockListPager.php',
        'BlockLogFormatter' => __DIR__ . '/includes/logging/BlockLogFormatter.php',
        'BmpHandler' => __DIR__ . '/includes/media/BMP.php',
        'BotPassword' => __DIR__ . '/includes/user/BotPassword.php',
        'BrokenRedirectsPage' => __DIR__ . '/includes/specials/SpecialBrokenRedirects.php',
-       'BufferingStatsdDataFactory' => __DIR__ . '/includes/libs/BufferingStatsdDataFactory.php',
+       'BufferingStatsdDataFactory' => __DIR__ . '/includes/libs/stats/BufferingStatsdDataFactory.php',
        'CLIParser' => __DIR__ . '/maintenance/parse.php',
        'CSSMin' => __DIR__ . '/includes/libs/CSSMin.php',
        'CacheDependency' => __DIR__ . '/includes/cache/CacheDependency.php',
@@ -200,7 +200,7 @@ $wgAutoloadLocalClasses = [
        'CategoryMembershipChange' => __DIR__ . '/includes/changes/CategoryMembershipChange.php',
        'CategoryMembershipChangeJob' => __DIR__ . '/includes/jobqueue/jobs/CategoryMembershipChangeJob.php',
        'CategoryPage' => __DIR__ . '/includes/page/CategoryPage.php',
-       'CategoryPager' => __DIR__ . '/includes/specials/SpecialCategories.php',
+       'CategoryPager' => __DIR__ . '/includes/specials/pagers/CategoryPager.php',
        'CategoryViewer' => __DIR__ . '/includes/CategoryViewer.php',
        'CdbException' => __DIR__ . '/includes/compat/CdbCompat.php',
        'CdbReader' => __DIR__ . '/includes/compat/CdbCompat.php',
@@ -240,9 +240,9 @@ $wgAutoloadLocalClasses = [
        'CliInstaller' => __DIR__ . '/includes/installer/CliInstaller.php',
        'CloneDatabase' => __DIR__ . '/includes/db/CloneDatabase.php',
        'CodeContentHandler' => __DIR__ . '/includes/content/CodeContentHandler.php',
-       'Collation' => __DIR__ . '/includes/Collation.php',
-       'CollationCkb' => __DIR__ . '/includes/Collation.php',
-       'CollationEt' => __DIR__ . '/includes/Collation.php',
+       'Collation' => __DIR__ . '/includes/collation/Collation.php',
+       'CollationCkb' => __DIR__ . '/includes/collation/CollationCkb.php',
+       'CollationEt' => __DIR__ . '/includes/collation/CollationEt.php',
        'CommandLineInc' => __DIR__ . '/maintenance/commandLine.inc',
        'CommandLineInstaller' => __DIR__ . '/maintenance/install.php',
        'CompareParserCache' => __DIR__ . '/maintenance/compareParserCache.php',
@@ -263,13 +263,13 @@ $wgAutoloadLocalClasses = [
        'ContentHandler' => __DIR__ . '/includes/content/ContentHandler.php',
        'ContentModelLogFormatter' => __DIR__ . '/includes/logging/ContentModelLogFormatter.php',
        'ContextSource' => __DIR__ . '/includes/context/ContextSource.php',
-       'ContribsPager' => __DIR__ . '/includes/specials/SpecialContributions.php',
+       'ContribsPager' => __DIR__ . '/includes/specials/pagers/ContribsPager.php',
        'ConvertExtensionToRegistration' => __DIR__ . '/maintenance/convertExtensionToRegistration.php',
        'ConvertLinks' => __DIR__ . '/maintenance/convertLinks.php',
        'ConvertUserOptions' => __DIR__ . '/maintenance/convertUserOptions.php',
        'ConverterRule' => __DIR__ . '/languages/ConverterRule.php',
        'Cookie' => __DIR__ . '/includes/libs/Cookie.php',
-       'CookieJar' => __DIR__ . '/includes/libs/Cookie.php',
+       'CookieJar' => __DIR__ . '/includes/libs/CookieJar.php',
        'CopyFileBackend' => __DIR__ . '/maintenance/copyFileBackend.php',
        'CopyFileOp' => __DIR__ . '/includes/filebackend/FileOp.php',
        'CopyJobQueue' => __DIR__ . '/maintenance/copyJobQueue.php',
@@ -332,7 +332,7 @@ $wgAutoloadLocalClasses = [
        'DeleteOrphanedRevisions' => __DIR__ . '/maintenance/deleteOrphanedRevisions.php',
        'DeleteRevision' => __DIR__ . '/maintenance/deleteRevision.php',
        'DeleteSelfExternals' => __DIR__ . '/maintenance/deleteSelfExternals.php',
-       'DeletedContribsPager' => __DIR__ . '/includes/specials/SpecialDeletedContributions.php',
+       'DeletedContribsPager' => __DIR__ . '/includes/specials/pagers/DeletedContribsPager.php',
        'DeletedContributionsPage' => __DIR__ . '/includes/specials/SpecialDeletedContributions.php',
        'DependencyWrapper' => __DIR__ . '/includes/cache/CacheDependency.php',
        'DeprecatedGlobal' => __DIR__ . '/includes/DeprecatedGlobal.php',
@@ -398,7 +398,7 @@ $wgAutoloadLocalClasses = [
        'EventRelayer' => __DIR__ . '/includes/libs/eventrelayer/EventRelayer.php',
        'EventRelayerGroup' => __DIR__ . '/includes/EventRelayerGroup.php',
        'EventRelayerMCRD' => __DIR__ . '/includes/libs/eventrelayer/EventRelayerMCRD.php',
-       'EventRelayerNull' => __DIR__ . '/includes/libs/eventrelayer/EventRelayer.php',
+       'EventRelayerNull' => __DIR__ . '/includes/libs/eventrelayer/EventRelayerNull.php',
        'Exif' => __DIR__ . '/includes/media/Exif.php',
        'ExifBitmapHandler' => __DIR__ . '/includes/media/ExifBitmap.php',
        'ExplodeIterator' => __DIR__ . '/includes/libs/ExplodeIterator.php',
@@ -423,7 +423,6 @@ $wgAutoloadLocalClasses = [
        'FakeConverter' => __DIR__ . '/languages/FakeConverter.php',
        'FakeMaintenance' => __DIR__ . '/maintenance/Maintenance.php',
        'FakeResultWrapper' => __DIR__ . '/includes/db/DatabaseUtility.php',
-       'Fallback' => __DIR__ . '/includes/Fallback.php',
        'FatalError' => __DIR__ . '/includes/exception/FatalError.php',
        'FauxRequest' => __DIR__ . '/includes/FauxRequest.php',
        'FauxResponse' => __DIR__ . '/includes/WebResponse.php',
@@ -490,7 +489,6 @@ $wgAutoloadLocalClasses = [
        'GenerateNormalizerDataAr' => __DIR__ . '/maintenance/language/generateNormalizerDataAr.php',
        'GenerateNormalizerDataMl' => __DIR__ . '/maintenance/language/generateNormalizerDataMl.php',
        'GenerateSitemap' => __DIR__ . '/maintenance/generateSitemap.php',
-       'GenerateUtf8Case' => __DIR__ . '/maintenance/language/generateUtf8Case.php',
        'GenericArrayObject' => __DIR__ . '/includes/libs/GenericArrayObject.php',
        'GetConfiguration' => __DIR__ . '/maintenance/getConfiguration.php',
        'GetLagTimes' => __DIR__ . '/maintenance/getLagTimes.php',
@@ -564,8 +562,8 @@ $wgAutoloadLocalClasses = [
        'IPSet' => __DIR__ . '/includes/compat/IPSetCompat.php',
        'IPTC' => __DIR__ . '/includes/media/IPTC.php',
        'IRCColourfulRCFeedFormatter' => __DIR__ . '/includes/rcfeed/IRCColourfulRCFeedFormatter.php',
-       'IcuCollation' => __DIR__ . '/includes/Collation.php',
-       'IdentityCollation' => __DIR__ . '/includes/Collation.php',
+       'IcuCollation' => __DIR__ . '/includes/collation/IcuCollation.php',
+       'IdentityCollation' => __DIR__ . '/includes/collation/IdentityCollation.php',
        'ImageBuilder' => __DIR__ . '/maintenance/rebuildImages.php',
        'ImageCleanup' => __DIR__ . '/maintenance/cleanupImages.php',
        'ImageGallery' => __DIR__ . '/includes/gallery/TraditionalImageGallery.php',
@@ -573,7 +571,7 @@ $wgAutoloadLocalClasses = [
        'ImageHandler' => __DIR__ . '/includes/media/ImageHandler.php',
        'ImageHistoryList' => __DIR__ . '/includes/page/ImageHistoryList.php',
        'ImageHistoryPseudoPager' => __DIR__ . '/includes/page/ImageHistoryPseudoPager.php',
-       'ImageListPager' => __DIR__ . '/includes/specials/SpecialListfiles.php',
+       'ImageListPager' => __DIR__ . '/includes/specials/pagers/ImageListPager.php',
        'ImagePage' => __DIR__ . '/includes/page/ImagePage.php',
        'ImageQueryPage' => __DIR__ . '/includes/specialpage/ImageQueryPage.php',
        'ImportLogFormatter' => __DIR__ . '/includes/logging/ImportLogFormatter.php',
@@ -634,11 +632,11 @@ $wgAutoloadLocalClasses = [
        'LBFactoryMulti' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMulti.php',
        'LBFactorySimple' => __DIR__ . '/includes/db/loadbalancer/LBFactorySimple.php',
        'LBFactorySingle' => __DIR__ . '/includes/db/loadbalancer/LBFactorySingle.php',
-       'LCStore' => __DIR__ . '/includes/cache/LocalisationCache.php',
-       'LCStoreCDB' => __DIR__ . '/includes/cache/LocalisationCache.php',
-       'LCStoreDB' => __DIR__ . '/includes/cache/LocalisationCache.php',
-       'LCStoreNull' => __DIR__ . '/includes/cache/LocalisationCache.php',
-       'LCStoreStaticArray' => __DIR__ . '/includes/cache/LCStoreStaticArray.php',
+       'LCStore' => __DIR__ . '/includes/cache/localisation/LCStore.php',
+       'LCStoreCDB' => __DIR__ . '/includes/cache/localisation/LCStoreCDB.php',
+       'LCStoreDB' => __DIR__ . '/includes/cache/localisation/LCStoreDB.php',
+       'LCStoreNull' => __DIR__ . '/includes/cache/localisation/LCStoreNull.php',
+       'LCStoreStaticArray' => __DIR__ . '/includes/cache/localisation/LCStoreStaticArray.php',
        'LangMemUsage' => __DIR__ . '/maintenance/language/langmemusage.php',
        'Language' => __DIR__ . '/languages/Language.php',
        'LanguageAr' => __DIR__ . '/languages/classes/LanguageAr.php',
@@ -718,8 +716,8 @@ $wgAutoloadLocalClasses = [
        'LocalIdLookup' => __DIR__ . '/includes/user/LocalIdLookup.php',
        'LocalRepo' => __DIR__ . '/includes/filerepo/LocalRepo.php',
        'LocalSettingsGenerator' => __DIR__ . '/includes/installer/LocalSettingsGenerator.php',
-       'LocalisationCache' => __DIR__ . '/includes/cache/LocalisationCache.php',
-       'LocalisationCacheBulkLoad' => __DIR__ . '/includes/cache/LocalisationCache.php',
+       'LocalisationCache' => __DIR__ . '/includes/cache/localisation/LocalisationCache.php',
+       'LocalisationCacheBulkLoad' => __DIR__ . '/includes/cache/localisation/LocalisationCacheBulkLoad.php',
        'LockManager' => __DIR__ . '/includes/filebackend/lockmanager/LockManager.php',
        'LockManagerGroup' => __DIR__ . '/includes/filebackend/lockmanager/LockManagerGroup.php',
        'LogEntry' => __DIR__ . '/includes/logging/LogEntry.php',
@@ -795,6 +793,8 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\Logger\\Monolog\\WikiProcessor' => __DIR__ . '/includes/debug/logger/monolog/WikiProcessor.php',
        'MediaWiki\\Logger\\NullSpi' => __DIR__ . '/includes/debug/logger/NullSpi.php',
        'MediaWiki\\Logger\\Spi' => __DIR__ . '/includes/debug/logger/Spi.php',
+       'MediaWiki\\MediaWikiServices' => __DIR__ . '/includes/MediaWikiServices.php',
+       'MediaWiki\\Services\\ServiceContainer' => __DIR__ . '/includes/Services/ServiceContainer.php',
        'MediaWiki\\Session\\BotPasswordSessionProvider' => __DIR__ . '/includes/session/BotPasswordSessionProvider.php',
        'MediaWiki\\Session\\CookieSessionProvider' => __DIR__ . '/includes/session/CookieSessionProvider.php',
        'MediaWiki\\Session\\ImmutableSessionProviderWithCookie' => __DIR__ . '/includes/session/ImmutableSessionProviderWithCookie.php',
@@ -833,7 +833,7 @@ $wgAutoloadLocalClasses = [
        'MemoizedCallable' => __DIR__ . '/includes/libs/MemoizedCallable.php',
        'MemoryFileBackend' => __DIR__ . '/includes/filebackend/MemoryFileBackend.php',
        'MergeHistory' => __DIR__ . '/includes/MergeHistory.php',
-       'MergeHistoryPager' => __DIR__ . '/includes/specials/SpecialMergeHistory.php',
+       'MergeHistoryPager' => __DIR__ . '/includes/specials/pagers/MergeHistoryPager.php',
        'MergeLogFormatter' => __DIR__ . '/includes/logging/MergeLogFormatter.php',
        'MergeMessageFileList' => __DIR__ . '/maintenance/mergeMessageFileList.php',
        'MergeableUpdate' => __DIR__ . '/includes/deferred/MergeableUpdate.php',
@@ -880,8 +880,8 @@ $wgAutoloadLocalClasses = [
        'NamespaceAwareForeignTitleFactory' => __DIR__ . '/includes/title/NamespaceAwareForeignTitleFactory.php',
        'NamespaceConflictChecker' => __DIR__ . '/maintenance/namespaceDupes.php',
        'NamespaceImportTitleFactory' => __DIR__ . '/includes/title/NamespaceImportTitleFactory.php',
-       'NewFilesPager' => __DIR__ . '/includes/specials/SpecialNewimages.php',
-       'NewPagesPager' => __DIR__ . '/includes/specials/SpecialNewpages.php',
+       'NewFilesPager' => __DIR__ . '/includes/specials/pagers/NewFilesPager.php',
+       'NewPagesPager' => __DIR__ . '/includes/specials/pagers/NewPagesPager.php',
        'NewUsersLogFormatter' => __DIR__ . '/includes/logging/NewUsersLogFormatter.php',
        'NolinesImageGallery' => __DIR__ . '/includes/gallery/NolinesImageGallery.php',
        'NotRecursiveIterator' => __DIR__ . '/includes/utils/iterators/NotRecursiveIterator.php',
@@ -892,6 +892,7 @@ $wgAutoloadLocalClasses = [
        'NullJob' => __DIR__ . '/includes/jobqueue/jobs/NullJob.php',
        'NullLockManager' => __DIR__ . '/includes/filebackend/lockmanager/LockManager.php',
        'NullRepo' => __DIR__ . '/includes/filerepo/NullRepo.php',
+       'NullStatsdDataFactory' => __DIR__ . '/includes/libs/stats/NullStatsdDataFactory.php',
        'OOUIHTMLForm' => __DIR__ . '/includes/htmlform/OOUIHTMLForm.php',
        'ORAField' => __DIR__ . '/includes/db/DatabaseOracle.php',
        'ORAResult' => __DIR__ . '/includes/db/DatabaseOracle.php',
@@ -933,7 +934,7 @@ $wgAutoloadLocalClasses = [
        'PackedHoverImageGallery' => __DIR__ . '/includes/gallery/PackedOverlayImageGallery.php',
        'PackedImageGallery' => __DIR__ . '/includes/gallery/PackedImageGallery.php',
        'PackedOverlayImageGallery' => __DIR__ . '/includes/gallery/PackedOverlayImageGallery.php',
-       'Page' => __DIR__ . '/includes/page/WikiPage.php',
+       'Page' => __DIR__ . '/includes/page/Page.php',
        'PageArchive' => __DIR__ . '/includes/specials/SpecialUndelete.php',
        'PageExists' => __DIR__ . '/maintenance/pageExists.php',
        'PageLangLogFormatter' => __DIR__ . '/includes/logging/PageLangLogFormatter.php',
@@ -1006,7 +1007,7 @@ $wgAutoloadLocalClasses = [
        'ProtectAction' => __DIR__ . '/includes/actions/ProtectAction.php',
        'ProtectLogFormatter' => __DIR__ . '/includes/logging/ProtectLogFormatter.php',
        'ProtectedPagesPager' => __DIR__ . '/includes/specials/SpecialProtectedpages.php',
-       'ProtectedTitlesPager' => __DIR__ . '/includes/specials/SpecialProtectedtitles.php',
+       'ProtectedTitlesPager' => __DIR__ . '/includes/specials/pagers/ProtectedTitlesPager.php',
        'ProtectionForm' => __DIR__ . '/includes/ProtectionForm.php',
        'PruneFileCache' => __DIR__ . '/maintenance/pruneFileCache.php',
        'PublishStashedFileJob' => __DIR__ . '/includes/jobqueue/jobs/PublishStashedFileJob.php',
@@ -1266,6 +1267,7 @@ $wgAutoloadLocalClasses = [
        'SquidUpdate' => __DIR__ . '/includes/deferred/CdnCacheUpdate.php',
        'SrConverter' => __DIR__ . '/languages/classes/LanguageSr.php',
        'StatsOutput' => __DIR__ . '/maintenance/language/StatOutputs.php',
+       'StatsdAwareInterface' => __DIR__ . '/includes/libs/stats/StatsdAwareInterface.php',
        'Status' => __DIR__ . '/includes/Status.php',
        'StatusValue' => __DIR__ . '/includes/libs/StatusValue.php',
        'StorageTypeStats' => __DIR__ . '/maintenance/storage/storageTypeStats.php',
@@ -1370,7 +1372,7 @@ $wgAutoloadLocalClasses = [
        'UploadStashNotLoggedInException' => __DIR__ . '/includes/upload/UploadStash.php',
        'UploadStashWrongOwnerException' => __DIR__ . '/includes/upload/UploadStash.php',
        'UploadStashZeroLengthFileException' => __DIR__ . '/includes/upload/UploadStash.php',
-       'UppercaseCollation' => __DIR__ . '/includes/Collation.php',
+       'UppercaseCollation' => __DIR__ . '/includes/collation/UppercaseCollation.php',
        'UsageException' => __DIR__ . '/includes/api/ApiMain.php',
        'User' => __DIR__ . '/includes/user/User.php',
        'UserArray' => __DIR__ . '/includes/user/UserArray.php',
@@ -1387,7 +1389,7 @@ $wgAutoloadLocalClasses = [
        'UsercreateTemplate' => __DIR__ . '/includes/templates/Usercreate.php',
        'UserloginTemplate' => __DIR__ . '/includes/templates/Userlogin.php',
        'UserrightsPage' => __DIR__ . '/includes/specials/SpecialUserrights.php',
-       'UsersPager' => __DIR__ . '/includes/specials/SpecialListusers.php',
+       'UsersPager' => __DIR__ . '/includes/specials/pagers/UsersPager.php',
        'UtfNormal' => __DIR__ . '/includes/compat/normal/UtfNormal.php',
        'UzConverter' => __DIR__ . '/languages/classes/LanguageUz.php',
        'VFormHTMLForm' => __DIR__ . '/includes/htmlform/VFormHTMLForm.php',
index cf012a4..1378e96 100644 (file)
                "wiki": "https://www.mediawiki.org/"
        },
        "require": {
-               "composer/semver": "1.2.0",
+               "composer/semver": "1.4.0",
                "cssjanus/cssjanus": "1.1.2",
+               "ext-ctype": "*",
                "ext-iconv": "*",
+               "ext-json": "*",
+               "ext-mbstring": "*",
+               "ext-xml": "*",
                "liuggio/statsd-php-client": "1.0.18",
                "mediawiki/at-ease": "1.1.0",
-               "oojs/oojs-ui": "0.16.2",
+               "oojs/oojs-ui": "0.16.5",
                "oyejorge/less.php": "1.7.0.10",
                "php": ">=5.5.9",
                "psr/log": "1.0.0",
@@ -29,7 +33,7 @@
                "wikimedia/base-convert": "1.0.1",
                "wikimedia/cdb": "1.3.0",
                "wikimedia/cldr-plural-rule-parser": "1.0.0",
-               "wikimedia/composer-merge-plugin": "1.3.0",
+               "wikimedia/composer-merge-plugin": "1.3.1",
                "wikimedia/ip-set": "1.0.1",
                "wikimedia/php-session-serializer": "1.0.3",
                "wikimedia/relpath": "1.0.3",
                "jakub-onderka/php-parallel-lint": "0.9.2",
                "justinrainbow/json-schema": "~1.3",
                "mediawiki/mediawiki-codesniffer": "0.6.0",
-               "monolog/monolog": "~1.17.2",
+               "monolog/monolog": "~1.18.2",
                "nikic/php-parser": "1.4.1",
                "nmred/kafka-php": "0.1.5",
-               "phpunit/phpunit": "4.8.23",
+               "phpunit/phpunit": "4.8.24",
                "wikimedia/avro": "1.7.7"
        },
        "suggest": {
                "ext-apc": "Local data and opcode cache",
                "ext-fileinfo": "Improved mime magic detection",
                "ext-intl": "ICU integration",
-               "ext-mbstring": "Multibyte string support",
                "ext-wikidiff2": "Diff accelerator",
                "monolog/monolog": "Flexible debug logging system",
                "nmred/kafka-php": "Send debug log events to kafka",
index f1f478e..6209b14 100644 (file)
@@ -96,7 +96,7 @@ used.
 
 Most importantly, the following functions have been deprecated:
 
-* Revisions::getText() and Revisions::getRawText() is deprecated in favor Revisions::getContent()
+* Revisions::getText() is deprecated in favor Revisions::getContent()
 * WikiPage::getText() is deprecated in favor WikiPage::getContent()
 
 Also, the old Article::getContent() (which returns text) is superceded by Article::getContentObject(). However, both
index 4218e8a..a743afa 100644 (file)
                                                                        ]
                                                                },
                                                                "templates": {
-                                                                       "type": "object",
+                                                                       "type": ["object", "array"],
                                                                        "description": "Templates to be loaded for client-side usage"
                                                                },
                                                                "targets": {
index a431f1b..31e9d92 100644 (file)
@@ -376,6 +376,7 @@ $user: Current user
 'APIEditBeforeSave': Before saving a page with api.php?action=edit, after
 processing request parameters. Return false to let the request fail, returning
 an error message or an <edit result="Failure"> tag if $resultArr was filled.
+Unlike for example 'EditFilterMergedContent' this also being run on undo.
 $editPage: the EditPage object
 $text: the new text of the article (has yet to be saved)
 &$resultArr: data in this array will be added to the API result
@@ -1996,6 +1997,11 @@ $user: $wgUser
 $request: $wgRequest
 $mediaWiki: The $mediawiki object
 
+'MediaWikiServices': Override services in the default MediaWikiServices instance.
+Extensions may use this to define, replace, or wrap existing services.
+However, the preferred way to define a new service is the $wgServiceWiringFiles array.
+$services: MediaWikiServices
+
 'MessageCache::get': When fetching a message. Can be used to override the key
 for customisations. Given and returned message key must be in special format:
 1) first letter must be in lower case according to the content language.
@@ -2854,6 +2860,7 @@ $special: the SpecialPage object
 $subPage: the subpage string or null if no subpage was specified
 
 'SpecialPageBeforeExecute': Called before SpecialPage::execute.
+Return false to prevent execution.
 $special: the SpecialPage object
 $subPage: the subpage string or null if no subpage was specified
 
diff --git a/docs/injection.txt b/docs/injection.txt
new file mode 100644 (file)
index 0000000..e0466c4
--- /dev/null
@@ -0,0 +1,248 @@
+injection.txt
+
+This is an overview of how MediaWiki makes use of dependency injection.
+The design described here grew from the discussion of RFC T384.
+
+
+The term "dependency injection" (DI) refers to a pattern on object oriented
+programming that tries to improve modularity by reducing strong coupling
+between classes. In practical terms, this means that anything an object needs
+to operate should be injected from the outside, the object itself should only
+know narrow interfaces, no concrete implementation of the logic it relies on.
+
+The requirement to inject everything typically results in an architecture that
+based on two main types of objects: simple value objects with no business logic
+(and often immutable), and essentially stateless service objects that use
+other service objects to operate on the value objects.
+
+As of the beginning of 2016 (MW version 1.27), MediaWiki is only starting to
+use the DI approach. Much of the code still relies on global state or direct
+instantiation, resulting in a highly cyclical dependency graph.
+
+
+== Overview ==
+The heart of the DI in MediaWiki is the central service locator,
+MediaWikiServices, which acts as the top level factory for services in
+MediaWiki. MediaWikiServices::getInstance() returns the default service
+locator instance, which can be used to gain access to default instances of
+various services. MediaWikiServices however also allows new services to be
+defined and default services to be redefined. Services are defined or
+redefined by providing a callback function, the "instantiator" function,
+that will return a new instance of the service.
+
+When MediaWikiServices::getInstance() is first called, it will create an
+instance of MediaWikiServices and populate it with the services defined
+in the files listed by $wgServiceWiringFiles, thereby "bootstrapping" the
+DI framework. Per default, $wgServiceWiringFiles lists
+includes/ServiceWiring.php, which defines all default service
+implementations, and specifies how they depend on each other ("wiring").
+
+When a new service is added to MediaWiki core, an instantiator function
+that will create the appropriate default instance for that service must
+be added to ServiceWiring.php. This makes the service available through
+the generic getService() method on the service locator returned by
+MediaWikiServices::getInstance().
+
+Extensions can add their own wiring files to $wgServiceWiringFiles, in order
+to define their own service. Extensions may also use the 'MediaWikiServices'
+hook to define or redefined services by calling methods on the default
+MediaWikiServices instance.
+
+
+It should be noted that the term "service locator" is often used to refer to a
+top level factory that is accessed directly, throughout the code, to avoid
+explicit dependency injection. In contrast, the term "DI container" is often
+used to describe a top level factory that is only accessed when services
+are created. We use the term "service locator" for the top level factory
+because it is more descriptive than "DI container", even though application
+logic is strongly discouraged from accessing MediaWikiServices directly.
+MediaWikiServices::getInstance() should ideally be accessed only in "static
+entry points" such as hook handler functions. See "Migration" below.
+
+
+== Configuration ==
+
+When the default MediaWikiServices instance is created, a Config object is
+provided to the constructor. This Config object represents the "bootstrap"
+configuration which will become available as the 'BootstrapConfig' service.
+As of MW 1.27, the bootstrap config is a GlobalVarConfig object providing
+access to the $wgXxx configuration variables.
+
+The bootstrap config is then used to construct a 'ConfigFactory' service,
+which in turn is used to construct the 'MainConfig' service. Application
+logic should use the 'MainConfig' service (or a more specific configuration
+object). 'BootstrapConfig' should only be used for bootstrapping basic
+services that are needed to load the 'MainConfig'.
+
+
+Note: Several well known services in MediaWiki core act as factories
+themselves, e.g. ApiModuleManager, ObjectCache, SpecialPageFactory, etc.
+The registries these factories are based on are currently managed as part of
+the configuration. This may however change in the future.
+
+
+== Migration ==
+
+This section provides some recipes for improving code modularity by reducing
+strong coupling. The dependency injection mechanism described above is an
+essential tool in this effort.
+
+Migrate access to global service instances and config variables:
+Assume Foo is a class that uses the $wgScriptPath global and calls
+wfGetDB() to get a database connection, in non-static methods.
+* Add $scriptPath as a constructor parameter and use $this->scriptPath
+  instead of $wgScriptPath.
+* Add LoadBalancer $dbLoadBalancer as a constructor parameter. Use
+  $this->dbLoadBalancer->getConnection() instead of wfGetDB().
+* Any code that calls Foo's constructor would now need to provide the
+  $scriptPath and $dbLoadBalancer. To avoid this, avoid direct instantiation
+  of services all together - see below.
+
+Migrate class-level singleton getters:
+Assume class Foo has mostly non-static methods, and provides a static
+getInstance() method that returns a singleton (or default instance).
+* Add an instantiator function for Foo into ServiceWiring.php. The instantiator
+  would do exactly what Foo::getInstance() did. However, it should
+  replace any access to global state with calls to $services->getXxx() to get a
+  service, or $services->getMainConfig()->get() to get a configuration setting.
+* Add a getFoo() method to MediaWikiServices. Don't forget to add the
+  appropriate test cases in MediaWikiServicesTest.
+* Turn Foo::getInstance() into a deprecated alias for
+  MediaWikiServices::getInstance()->getFoo(). Change all calls to
+  Foo::getInstance() to use injection (see above).
+
+Migrate direct service instantiation:
+Assume class Bar calls new Foo().
+* Add an instantiator function for Foo into ServiceWiring.php and add a getFoo()
+  method to MediaWikiServices. Don't forget to add the appropriate test cases
+  in MediaWikiServicesTest.
+* In the instantiator, replace any access to global state with calls
+  to $services->getXxx() to get a service, or $services->getMainConfig()->get()
+  to get a configuration setting.
+* The code in Bar that calls Foo's constructor should be changed to have a Foo
+  instance injected; Eventually, the only code that instantiates Foo is the
+  instantiator in ServiceWiring.php.
+* As an intermediate step, Bar's constructor could initialize the $foo member
+  variable by calling MediaWikiServices::getInstance()->getFoo(). This is
+  acceptable as a stepping stone, but should be replaced by proper injection
+  via a constructor argument. Do not however inject the MediaWikiServices
+  object!
+
+Migrate parameterized helper instantiation:
+Assume class Bar creates some helper object by calling new Foo( $x ),
+and Foo uses a global singleton of the Xyzzy service.
+* Define a FooFactory class (or a FooFactory interface along with a MyFooFactory
+  implementation). FooFactory defines the method newFoo( $x ) or getFoo( $x ),
+  depending on the desired semantics (newFoo would guarantee a fresh instance).
+  When Foo gets refactored to have Xyzzy injected, FooFactory will need a
+  Xyzzy instance, so newFoo() can pass it to new Foo().
+* Add an instantiator function for FooFactory into ServiceWiring.php and add a
+  getFooFactory() method to MediaWikiServices. Don't forget to add the
+  appropriate test cases in MediaWikiServicesTest.
+* The code in Bar that calls Foo's constructor should be changed to have a
+  FooFactory instance injected; Eventually, the only code that instantiates
+  Foo are implementations of FooFactory, and the only code that instantiates
+  FooFactory is the instantiator in ServiceWiring.php.
+* As an intermediate step, Bar's constructor could initialize the $fooFactory
+  member variable by calling MediaWikiServices::getInstance()->getFooFactory().
+  This is acceptable as a stepping stone, but should be replaced by proper
+  injection via a constructor argument. Do not however inject the
+  MediaWikiServices object!
+
+Migrate a handler registry:
+Assume class Bar calls FooRegistry::getFoo( $x ) to get a specialized Foo
+instance for handling $x.
+* Turn getFoo into a non-static method.
+* Add an instantiator function for FooRegistry into ServiceWiring.php and add
+  a getFooRegistry() method to MediaWikiServices. Don't forget to add the
+  appropriate test cases in MediaWikiServicesTest.
+* Change all code that calls FooRegistry::getFoo() statically to call this
+  method on a FooRegistry instance. That is, Bar would have a $fooRegistry
+  member, initialized from a constructor parameter.
+* As an intermediate step, Bar's constructor could initialize the $fooRegistry
+  member variable by calling MediaWikiServices::getInstance()->
+  getFooRegistry(). This is acceptable as a stepping stone, but should be
+  replaced by proper injection via a constructor argument. Do not however
+  inject the MediaWikiServices object!
+
+Migrate deferred service instantiation:
+Assume class Bar calls new Foo(), but only when needed, to avoid the cost of
+instantiating Foo().
+* Define a FooFactory interface and a MyFooFactory implementation of that
+  interface. FooFactory defines the method getFoo() with no parameters.
+* Precede as for the "parameterized helper instantiation" case described above.
+
+Migrate a class with only static methods:
+Assume Foo is a class with only static methods, such as frob(), which
+interacts with global state or system resources.
+* Introduce a FooService interface and a DefaultFoo implementation of that
+  interface. FooService contains the public methods defined by Foo.
+* Add an instantiator function for FooService into ServiceWiring.php and
+  add a getFooService() method to MediaWikiServices. Don't forget to
+  add the appropriate test cases in MediaWikiServicesTest.
+* Add a private static getFooService() method to Foo. That method just
+  calls MediaWikiServices::getInstance()->getFooService().
+* Make all methods in Foo delegate to the FooService returned by
+  getFooService(). That is, Foo::frob() would do self::getFooService()->frob().
+* Deprecate Foo. Inject a FooService into all code that calls methods
+  on Foo, and change any calls to static methods in foo to the methods
+  provided by the FooService interface.
+
+Migrate static hook handler functions (to allow unit testing):
+Assume MyExtHooks::onFoo is a static hook handler function that is called with
+the parameter $x; Further assume MyExt::onFoo needs service Bar, which is
+already known to MediaWikiServices (if not, see above).
+* Create a non-static doFoo( $x ) method in MyExtHooks that has the same
+  signature as onFoo( $x ). Move the code from onFoo() into doFoo(), replacing
+  any access to global or static variables with access to instance member
+  variables.
+* Add a constructor to MyExtHooks that takes a Bar service as a parameter.
+* Add a static method called newFromGlobalState() with no parameters. It should
+  just return new MyExtHooks( MediaWikiServices::getBar() ).
+* The original static handler method onFoo( $x ) is then implemented as
+  self::newFromGlobalState()->doFoo( $x ).
+
+Migrate a "smart record":
+Assume Thingy is a "smart record" that "knows" how to load and store itself.
+For this purpose, Thingy uses wfGetDB().
+* Create a "dumb" value class ThingyRecord that contains all the information
+  that Thingy represents (e.g. the information from a database row). The value
+  object should not know about any service.
+* Create a DAO-style service for loading and storing ThingyRecords, called
+  ThingyStore. It may be useful to split the interfaces for reading and
+  writing, with a single class implementing both interfaces, so we in the
+  end have the ThingyLookup and ThingyStore interfaces, and a SqlThingyStore
+  implementation.
+* Add instantiator functions for ThingyLookup and ThingyStore in
+  ServiceWiring.php. Since we want to use the same instance for both service
+  interfaces, the instantiator for ThingyLookup would return
+  $services->getThingyStore().
+* Add getThingyLookup() and getThingyStore methods to MediaWikiServices.
+  Don't forget to add the appropriate test cases in MediaWikiServicesTest.
+* In the old Thingy class, replace all member variables that represent the
+  record's data with a single ThingyRecord object.
+* In the old Thingy class, replace all calls to static methods or functions,
+  such as wfGetDB(), with calls to the appropriate services, such as
+  LoadBalancer::getConnection().
+* In Thingy's constructor, pull in any services needed, such as the
+  LoadBalancer, by using MediaWikiServices::getInstance(). These services
+  cannot be injected without changing the constructor signature, which
+  is often impractical for "smart records" that get instantiated directly
+  in many places in the code base.
+* Deprecate the old Thingy class. Replace all usages of it with one of the
+  three new classes: loading needs a ThingyLookup, storing needs a ThingyStore,
+  and reading data needs a ThingyRecord.
+
+Migrate lazy loading:
+Assume Thingy is a "smart record" as described above, but requires lazy loading
+of some or all the data it represents.
+* Instead of a plain object, define ThingyRecord to be an interface. Provide a
+  "simple" and "lazy" implementations, called SimpleThingyRecord and
+  LazyThingyRecord. LazyThingyRecord knows about some lower level storage
+  interface, like a LoadBalancer, and uses it to load information on demand.
+* Any direct instantiation of a ThingyRecord would use the SimpleThingyRecord
+  implementation.
+* SqlThingyStore however creates instances of LazyThingyRecord, and injects
+  whatever storage layer service LazyThingyRecord needs to perform lazy loading.
+
+
index e914a3a..8c59e72 100644 (file)
@@ -122,7 +122,7 @@ Lag time of the databases:
        key: $wgDBname:lag_times
        ex: wikidb:lag_times
        stores: array mapping the database id to its lag time
-       expriy: 5 secondes
+       expiry: 5 secondes
        cleared by: nothing
 
 Localisation:
@@ -139,7 +139,7 @@ Message Cache:
        ex: wikidb:messages, wikidb:messages-hash, wikidb:messages-status
        stores: an array where the keys are DB keys and the values are messages
        set in: wfMessage(), Article::editUpdates() and Title::moveTo()
-       expriy: $wgMsgCacheExpiry
+       expiry: $wgMsgCacheExpiry
        cleared by: nothing
 
 Newtalk:
@@ -194,14 +194,14 @@ Revision text:
        ex: wikidb:revisiontext:textid:1012
        stores: text of a revision
        cleared by: nothing
-       expriry: $wgRevisionCacheExpiry
+       expiry: $wgRevisionCacheExpiry
 
 Sessions:
        controlled by: $wgSessionsInObjectCache
        key: $wgBDname:session:$id
        ex: wikidb:session:38d7c5b8d3bfc51egf40c69bc40f8be3
        stores: $SESSION, useful when using a multi-sever wiki
-       expriy: one hour
+       expiry: one hour
        cleared by: session_destroy()
 
 Sidebar:
@@ -210,7 +210,7 @@ Sidebar:
        key: $wgDBname:sidebar
        ex: wikidb:sidebar
        stores: the html output of the sidebar
-       expriy: $wgSidebarCacheExpiry
+       expiry: $wgSidebarCacheExpiry
        cleared by: MessageCache::replace()
 
 Special:Allpages:
index 764592d..93df004 100644 (file)
@@ -137,7 +137,7 @@ class Block {
 
                if ( $options['by'] ) {
                        # Local user
-                       $this->setBlocker( User::newFromID( $options['by'] ) );
+                       $this->setBlocker( User::newFromId( $options['by'] ) );
                } else {
                        # Foreign user
                        $this->setBlocker( $options['byText'] );
@@ -568,7 +568,7 @@ class Block {
                if ( $this->forcedTargetID ) {
                        $uid = $this->forcedTargetID;
                } else {
-                       $uid = $this->target instanceof User ? $this->target->getID() : 0;
+                       $uid = $this->target instanceof User ? $this->target->getId() : 0;
                }
 
                $a = [
@@ -844,7 +844,7 @@ class Block {
                                        'ipb_expiry' => $dbw->timestamp( $this->mExpiry ),
                                ],
                                [ /* WHERE */
-                                       'ipb_address' => (string)$this->getTarget()
+                                       'ipb_id' => $this->getId(),
                                ],
                                __METHOD__
                        );
diff --git a/includes/Collation.php b/includes/Collation.php
deleted file mode 100644 (file)
index 7a3623d..0000000
+++ /dev/null
@@ -1,648 +0,0 @@
-<?php
-/**
- * Database row sorting.
- *
- * 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 class Collation {
-       private static $instance;
-
-       /**
-        * @return Collation
-        */
-       static function singleton() {
-               if ( !self::$instance ) {
-                       global $wgCategoryCollation;
-                       self::$instance = self::factory( $wgCategoryCollation );
-               }
-               return self::$instance;
-       }
-
-       /**
-        * @throws MWException
-        * @param string $collationName
-        * @return Collation
-        */
-       static function factory( $collationName ) {
-               switch ( $collationName ) {
-                       case 'uppercase':
-                               return new UppercaseCollation;
-                       case 'identity':
-                               return new IdentityCollation;
-                       case 'uca-default':
-                               return new IcuCollation( 'root' );
-                       case 'xx-uca-ckb':
-                               return new CollationCkb;
-                       case 'xx-uca-et':
-                               return new CollationEt;
-                       default:
-                               $match = [];
-                               if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
-                                       return new IcuCollation( $match[1] );
-                               }
-
-                               # Provide a mechanism for extensions to hook in.
-                               $collationObject = null;
-                               Hooks::run( 'Collation::factory', [ $collationName, &$collationObject ] );
-
-                               if ( $collationObject instanceof Collation ) {
-                                       return $collationObject;
-                               }
-
-                               // If all else fails...
-                               throw new MWException( __METHOD__ . ": unknown collation type \"$collationName\"" );
-               }
-       }
-
-       /**
-        * Given a string, convert it to a (hopefully short) key that can be used
-        * for efficient sorting.  A binary sort according to the sortkeys
-        * corresponds to a logical sort of the corresponding strings.  Current
-        * code expects that a line feed character should sort before all others, but
-        * has no other particular expectations (and that one can be changed if
-        * necessary).
-        *
-        * @param string $string UTF-8 string
-        * @return string Binary sortkey
-        */
-       abstract function getSortKey( $string );
-
-       /**
-        * Given a string, return the logical "first letter" to be used for
-        * grouping on category pages and so on.  This has to be coordinated
-        * carefully with convertToSortkey(), or else the sorted list might jump
-        * back and forth between the same "initial letters" or other pathological
-        * behavior.  For instance, if you just return the first character, but "a"
-        * sorts the same as "A" based on getSortKey(), then you might get a
-        * list like
-        *
-        * == A ==
-        * * [[Aardvark]]
-        *
-        * == a ==
-        * * [[antelope]]
-        *
-        * == A ==
-        * * [[Ape]]
-        *
-        * etc., assuming for the sake of argument that $wgCapitalLinks is false.
-        *
-        * @param string $string UTF-8 string
-        * @return string UTF-8 string corresponding to the first letter of input
-        */
-       abstract function getFirstLetter( $string );
-}
-
-class UppercaseCollation extends Collation {
-       private $lang;
-
-       function __construct() {
-               // Get a language object so that we can use the generic UTF-8 uppercase
-               // function there
-               $this->lang = Language::factory( 'en' );
-       }
-
-       function getSortKey( $string ) {
-               return $this->lang->uc( $string );
-       }
-
-       function getFirstLetter( $string ) {
-               if ( $string[0] == "\0" ) {
-                       $string = substr( $string, 1 );
-               }
-               return $this->lang->ucfirst( $this->lang->firstChar( $string ) );
-       }
-}
-
-/**
- * Collation class that's essentially a no-op.
- *
- * Does sorting based on binary value of the string.
- * Like how things were pre 1.17.
- */
-class IdentityCollation extends Collation {
-
-       function getSortKey( $string ) {
-               return $string;
-       }
-
-       function getFirstLetter( $string ) {
-               global $wgContLang;
-               // Copied from UppercaseCollation.
-               // I'm kind of unclear on when this could happen...
-               if ( $string[0] == "\0" ) {
-                       $string = substr( $string, 1 );
-               }
-               return $wgContLang->firstChar( $string );
-       }
-}
-
-class IcuCollation extends Collation {
-       const FIRST_LETTER_VERSION = 2;
-
-       /** @var Collator */
-       private $primaryCollator;
-
-       /** @var Collator */
-       private $mainCollator;
-
-       /** @var string */
-       private $locale;
-
-       /** @var Language */
-       protected $digitTransformLanguage;
-
-       /** @var array */
-       private $firstLetterData;
-
-       /**
-        * Unified CJK blocks.
-        *
-        * The same definition of a CJK block must be used for both Collation and
-        * generateCollationData.php. These blocks are omitted from the first
-        * letter data, as an optimisation measure and because the default UCA table
-        * is pretty useless for sorting Chinese text anyway. Japanese and Korean
-        * blocks are not included here, because they are smaller and more useful.
-        */
-       private static $cjkBlocks = [
-               [ 0x2E80, 0x2EFF ], // CJK Radicals Supplement
-               [ 0x2F00, 0x2FDF ], // Kangxi Radicals
-               [ 0x2FF0, 0x2FFF ], // Ideographic Description Characters
-               [ 0x3000, 0x303F ], // CJK Symbols and Punctuation
-               [ 0x31C0, 0x31EF ], // CJK Strokes
-               [ 0x3200, 0x32FF ], // Enclosed CJK Letters and Months
-               [ 0x3300, 0x33FF ], // CJK Compatibility
-               [ 0x3400, 0x4DBF ], // CJK Unified Ideographs Extension A
-               [ 0x4E00, 0x9FFF ], // CJK Unified Ideographs
-               [ 0xF900, 0xFAFF ], // CJK Compatibility Ideographs
-               [ 0xFE30, 0xFE4F ], // CJK Compatibility Forms
-               [ 0x20000, 0x2A6DF ], // CJK Unified Ideographs Extension B
-               [ 0x2A700, 0x2B73F ], // CJK Unified Ideographs Extension C
-               [ 0x2B740, 0x2B81F ], // CJK Unified Ideographs Extension D
-               [ 0x2F800, 0x2FA1F ], // CJK Compatibility Ideographs Supplement
-       ];
-
-       /**
-        * Additional characters (or character groups) to be considered separate
-        * letters for given languages, or to be removed from the list of such
-        * letters (denoted by keys starting with '-').
-        *
-        * These are additions to (or subtractions from) the data stored in the
-        * first-letters-root.ser file (which among others includes full basic latin,
-        * cyrillic and greek alphabets).
-        *
-        * "Separate letter" is a letter that would have a separate heading/section
-        * for it in a dictionary or a phone book in this language. This data isn't
-        * used for sorting (the ICU library handles that), only for deciding which
-        * characters (or character groups) to use as headings.
-        *
-        * Initially generated based on the primary level of Unicode collation
-        * tailorings available at http://developer.mimer.com/charts/tailorings.htm ,
-        * later modified.
-        *
-        * Empty arrays are intended; this signifies that the data for the language is
-        * available and that there are, in fact, no additional letters to consider.
-        */
-       private static $tailoringFirstLetters = [
-               // Verified by native speakers
-               'be' => [ "Ё" ],
-               'be-tarask' => [ "Ё" ],
-               'cy' => [ "Ch", "Dd", "Ff", "Ng", "Ll", "Ph", "Rh", "Th" ],
-               'en' => [],
-               'fa' => [ "آ", "ء", "ه" ],
-               'fi' => [ "Å", "Ä", "Ö" ],
-               'fr' => [],
-               'hu' => [ "Cs", "Dz", "Dzs", "Gy", "Ly", "Ny", "Ö", "Sz", "Ty", "Ü", "Zs" ],
-               'is' => [ "Á", "Ð", "É", "Í", "Ó", "Ú", "Ý", "Þ", "Æ", "Ö", "Å" ],
-               'it' => [],
-               'lv' => [ "Č", "Ģ", "Ķ", "Ļ", "Ņ", "Š", "Ž" ],
-               'pl' => [ "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ],
-               'pt' => [],
-               'ru' => [],
-               'sv' => [ "Å", "Ä", "Ö" ],
-               'sv@collation=standard' => [ "Å", "Ä", "Ö" ],
-               'uk' => [ "Ґ", "Ь" ],
-               'vi' => [ "Ă", "Â", "Đ", "Ê", "Ô", "Ơ", "Ư" ],
-               // Not verified, but likely correct
-               'af' => [],
-               'ast' => [ "Ch", "Ll", "Ñ" ],
-               'az' => [ "Ç", "Ə", "Ğ", "İ", "Ö", "Ş", "Ü" ],
-               'bg' => [],
-               'br' => [ "Ch", "C'h" ],
-               'bs' => [ "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ],
-               'ca' => [],
-               'co' => [],
-               'cs' => [ "Č", "Ch", "Ř", "Š", "Ž" ],
-               'da' => [ "Æ", "Ø", "Å" ],
-               'de' => [],
-               'dsb' => [ "Č", "Ć", "Dź", "Ě", "Ch", "Ł", "Ń", "Ŕ", "Š", "Ś", "Ž", "Ź" ],
-               'el' => [],
-               'eo' => [ "Ĉ", "Ĝ", "Ĥ", "Ĵ", "Ŝ", "Ŭ" ],
-               'es' => [ "Ñ" ],
-               'et' => [ "Š", "Ž", "Õ", "Ä", "Ö", "Ü", "W" ], // added W for CollationEt (xx-uca-et)
-               'eu' => [ "Ñ" ],
-               'fo' => [ "Á", "Ð", "Í", "Ó", "Ú", "Ý", "Æ", "Ø", "Å" ],
-               'fur' => [ "À", "Á", "Â", "È", "Ì", "Ò", "Ù" ],
-               'fy' => [],
-               'ga' => [],
-               'gd' => [],
-               'gl' => [ "Ch", "Ll", "Ñ" ],
-               'hr' => [ "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ],
-               'hsb' => [ "Č", "Dź", "Ě", "Ch", "Ł", "Ń", "Ř", "Š", "Ć", "Ž" ],
-               'kk' => [ "Ү", "І" ],
-               'kl' => [ "Æ", "Ø", "Å" ],
-               'ku' => [ "Ç", "Ê", "Î", "Ş", "Û" ],
-               'ky' => [ "Ё" ],
-               'la' => [],
-               'lb' => [],
-               'lt' => [ "Č", "Š", "Ž" ],
-               'mk' => [],
-               'mo' => [ "Ă", "Â", "Î", "Ş", "Ţ" ],
-               'mt' => [ "Ċ", "Ġ", "Għ", "Ħ", "Ż" ],
-               'nl' => [],
-               'no' => [ "Æ", "Ø", "Å" ],
-               'oc' => [],
-               'rm' => [],
-               'ro' => [ "Ă", "Â", "Î", "Ş", "Ţ" ],
-               'rup' => [ "Ă", "Â", "Î", "Ľ", "Ń", "Ş", "Ţ" ],
-               'sco' => [],
-               'sk' => [ "Ä", "Č", "Ch", "Ô", "Š", "Ž" ],
-               'sl' => [ "Č", "Š", "Ž" ],
-               'smn' => [ "Á", "Č", "Đ", "Ŋ", "Š", "Ŧ", "Ž", "Æ", "Ø", "Å", "Ä", "Ö" ],
-               'sq' => [ "Ç", "Dh", "Ë", "Gj", "Ll", "Nj", "Rr", "Sh", "Th", "Xh", "Zh" ],
-               'sr' => [],
-               'tk' => [ "Ç", "Ä", "Ž", "Ň", "Ö", "Ş", "Ü", "Ý" ],
-               'tl' => [ "Ñ", "Ng" ],
-               'tr' => [ "Ç", "Ğ", "İ", "Ö", "Ş", "Ü" ],
-               'tt' => [ "Ә", "Ө", "Ү", "Җ", "Ң", "Һ" ],
-               'uz' => [ "Ch", "G'", "Ng", "O'", "Sh" ],
-       ];
-
-       const RECORD_LENGTH = 14;
-
-       function __construct( $locale ) {
-               if ( !extension_loaded( 'intl' ) ) {
-                       throw new MWException( 'An ICU collation was requested, ' .
-                               'but the intl extension is not available.' );
-               }
-
-               $this->locale = $locale;
-               // Drop everything after the '@' in locale's name
-               $localeParts = explode( '@', $locale );
-               $this->digitTransformLanguage = Language::factory( $locale === 'root' ? 'en' : $localeParts[0] );
-
-               $this->mainCollator = Collator::create( $locale );
-               if ( !$this->mainCollator ) {
-                       throw new MWException( "Invalid ICU locale specified for collation: $locale" );
-               }
-
-               $this->primaryCollator = Collator::create( $locale );
-               $this->primaryCollator->setStrength( Collator::PRIMARY );
-       }
-
-       function getSortKey( $string ) {
-               // intl extension produces non null-terminated
-               // strings. Appending '' fixes it so that it doesn't generate
-               // a warning on each access in debug php.
-               MediaWiki\suppressWarnings();
-               $key = $this->mainCollator->getSortKey( $string ) . '';
-               MediaWiki\restoreWarnings();
-               return $key;
-       }
-
-       function getPrimarySortKey( $string ) {
-               MediaWiki\suppressWarnings();
-               $key = $this->primaryCollator->getSortKey( $string ) . '';
-               MediaWiki\restoreWarnings();
-               return $key;
-       }
-
-       function getFirstLetter( $string ) {
-               $string = strval( $string );
-               if ( $string === '' ) {
-                       return '';
-               }
-
-               // Check for CJK
-               $firstChar = mb_substr( $string, 0, 1, 'UTF-8' );
-               if ( ord( $firstChar ) > 0x7f && self::isCjk( UtfNormal\Utils::utf8ToCodepoint( $firstChar ) ) ) {
-                       return $firstChar;
-               }
-
-               $sortKey = $this->getPrimarySortKey( $string );
-
-               // Do a binary search to find the correct letter to sort under
-               $min = ArrayUtils::findLowerBound(
-                       [ $this, 'getSortKeyByLetterIndex' ],
-                       $this->getFirstLetterCount(),
-                       'strcmp',
-                       $sortKey );
-
-               if ( $min === false ) {
-                       // Before the first letter
-                       return '';
-               }
-               return $this->getLetterByIndex( $min );
-       }
-
-       function getFirstLetterData() {
-               if ( $this->firstLetterData !== null ) {
-                       return $this->firstLetterData;
-               }
-
-               $cache = wfGetCache( CACHE_ANYTHING );
-               $cacheKey = wfMemcKey(
-                       'first-letters',
-                       $this->locale,
-                       $this->digitTransformLanguage->getCode(),
-                       self::getICUVersion()
-               );
-               $cacheEntry = $cache->get( $cacheKey );
-
-               if ( $cacheEntry && isset( $cacheEntry['version'] )
-                       && $cacheEntry['version'] == self::FIRST_LETTER_VERSION
-               ) {
-                       $this->firstLetterData = $cacheEntry;
-                       return $this->firstLetterData;
-               }
-
-               // Generate data from serialized data file
-
-               if ( isset( self::$tailoringFirstLetters[$this->locale] ) ) {
-                       $letters = wfGetPrecompiledData( "first-letters-root.ser" );
-                       // Append additional characters
-                       $letters = array_merge( $letters, self::$tailoringFirstLetters[$this->locale] );
-                       // Remove unnecessary ones, if any
-                       if ( isset( self::$tailoringFirstLetters['-' . $this->locale] ) ) {
-                               $letters = array_diff( $letters, self::$tailoringFirstLetters['-' . $this->locale] );
-                       }
-                       // Apply digit transforms
-                       $digits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
-                       $letters = array_diff( $letters, $digits );
-                       foreach ( $digits as $digit ) {
-                               $letters[] = $this->digitTransformLanguage->formatNum( $digit, true );
-                       }
-               } else {
-                       $letters = wfGetPrecompiledData( "first-letters-{$this->locale}.ser" );
-                       if ( $letters === false ) {
-                               throw new MWException( "MediaWiki does not support ICU locale " .
-                                       "\"{$this->locale}\"" );
-                       }
-               }
-
-               /* Sort the letters.
-                *
-                * It's impossible to have the precompiled data file properly sorted,
-                * because the sort order changes depending on ICU version. If the
-                * array is not properly sorted, the binary search will return random
-                * results.
-                *
-                * We also take this opportunity to remove primary collisions.
-                */
-               $letterMap = [];
-               foreach ( $letters as $letter ) {
-                       $key = $this->getPrimarySortKey( $letter );
-                       if ( isset( $letterMap[$key] ) ) {
-                               // Primary collision
-                               // Keep whichever one sorts first in the main collator
-                               if ( $this->mainCollator->compare( $letter, $letterMap[$key] ) < 0 ) {
-                                       $letterMap[$key] = $letter;
-                               }
-                       } else {
-                               $letterMap[$key] = $letter;
-                       }
-               }
-               ksort( $letterMap, SORT_STRING );
-
-               /* Remove duplicate prefixes. Basically if something has a sortkey
-                * which is a prefix of some other sortkey, then it is an
-                * expansion and probably should not be considered a section
-                * header.
-                *
-                * For example 'þ' is sometimes sorted as if it is the letters
-                * 'th'. Other times it is its own primary element. Another
-                * example is '₨'. Sometimes its a currency symbol. Sometimes it
-                * is an 'R' followed by an 's'.
-                *
-                * Additionally an expanded element should always sort directly
-                * after its first element due to they way sortkeys work.
-                *
-                * UCA sortkey elements are of variable length but no collation
-                * element should be a prefix of some other element, so I think
-                * this is safe. See:
-                * - https://ssl.icu-project.org/repos/icu/icuhtml/trunk/design/collation/ICU_collation_design.htm
-                * - http://site.icu-project.org/design/collation/uca-weight-allocation
-                *
-                * Additionally, there is something called primary compression to
-                * worry about. Basically, if you have two primary elements that
-                * are more than one byte and both start with the same byte then
-                * the first byte is dropped on the second primary. Additionally
-                * either \x03 or \xFF may be added to mean that the next primary
-                * does not start with the first byte of the first primary.
-                *
-                * This shouldn't matter much, as the first primary is not
-                * changed, and that is what we are comparing against.
-                *
-                * tl;dr: This makes some assumptions about how icu implements
-                * collations. It seems incredibly unlikely these assumptions
-                * will change, but nonetheless they are assumptions.
-                */
-
-               $prev = false;
-               $duplicatePrefixes = [];
-               foreach ( $letterMap as $key => $value ) {
-                       // Remove terminator byte. Otherwise the prefix
-                       // comparison will get hung up on that.
-                       $trimmedKey = rtrim( $key, "\0" );
-                       if ( $prev === false || $prev === '' ) {
-                               $prev = $trimmedKey;
-                               // We don't yet have a collation element
-                               // to compare against, so continue.
-                               continue;
-                       }
-
-                       // Due to the fact the array is sorted, we only have
-                       // to compare with the element directly previous
-                       // to the current element (skipping expansions).
-                       // An element "X" will always sort directly
-                       // before "XZ" (Unless we have "XY", but we
-                       // do not update $prev in that case).
-                       if ( substr( $trimmedKey, 0, strlen( $prev ) ) === $prev ) {
-                               $duplicatePrefixes[] = $key;
-                               // If this is an expansion, we don't want to
-                               // compare the next element to this element,
-                               // but to what is currently $prev
-                               continue;
-                       }
-                       $prev = $trimmedKey;
-               }
-               foreach ( $duplicatePrefixes as $badKey ) {
-                       wfDebug( "Removing '{$letterMap[$badKey]}' from first letters.\n" );
-                       unset( $letterMap[$badKey] );
-                       // This code assumes that unsetting does not change sort order.
-               }
-               $data = [
-                       'chars' => array_values( $letterMap ),
-                       'keys' => array_keys( $letterMap ),
-                       'version' => self::FIRST_LETTER_VERSION,
-               ];
-
-               // Reduce memory usage before caching
-               unset( $letterMap );
-
-               // Save to cache
-               $this->firstLetterData = $data;
-               $cache->set( $cacheKey, $data, $cache::TTL_WEEK );
-               return $data;
-       }
-
-       function getLetterByIndex( $index ) {
-               if ( $this->firstLetterData === null ) {
-                       $this->getFirstLetterData();
-               }
-               return $this->firstLetterData['chars'][$index];
-       }
-
-       function getSortKeyByLetterIndex( $index ) {
-               if ( $this->firstLetterData === null ) {
-                       $this->getFirstLetterData();
-               }
-               return $this->firstLetterData['keys'][$index];
-       }
-
-       function getFirstLetterCount() {
-               if ( $this->firstLetterData === null ) {
-                       $this->getFirstLetterData();
-               }
-               return count( $this->firstLetterData['chars'] );
-       }
-
-       static function isCjk( $codepoint ) {
-               foreach ( self::$cjkBlocks as $block ) {
-                       if ( $codepoint >= $block[0] && $codepoint <= $block[1] ) {
-                               return true;
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Return the version of ICU library used by PHP's intl extension,
-        * or false when the extension is not installed of the version
-        * can't be determined.
-        *
-        * The constant INTL_ICU_VERSION this function refers to isn't really
-        * documented. It is available since PHP 5.3.7 (see PHP bug 54561).
-        * This function will return false on older PHPs.
-        *
-        * @since 1.21
-        * @return string|bool
-        */
-       static function getICUVersion() {
-               return defined( 'INTL_ICU_VERSION' ) ? INTL_ICU_VERSION : false;
-       }
-
-       /**
-        * Return the version of Unicode appropriate for the version of ICU library
-        * currently in use, or false when it can't be determined.
-        *
-        * @since 1.21
-        * @return string|bool
-        */
-       static function getUnicodeVersionForICU() {
-               $icuVersion = IcuCollation::getICUVersion();
-               if ( !$icuVersion ) {
-                       return false;
-               }
-
-               $versionPrefix = substr( $icuVersion, 0, 3 );
-               // Source: http://site.icu-project.org/download
-               $map = [
-                       '50.' => '6.2',
-                       '49.' => '6.1',
-                       '4.8' => '6.0',
-                       '4.6' => '6.0',
-                       '4.4' => '5.2',
-                       '4.2' => '5.1',
-                       '4.0' => '5.1',
-                       '3.8' => '5.0',
-                       '3.6' => '5.0',
-                       '3.4' => '4.1',
-               ];
-
-               if ( isset( $map[$versionPrefix] ) ) {
-                       return $map[$versionPrefix];
-               } else {
-                       return false;
-               }
-       }
-}
-
-/**
- * Workaround for the lack of support of Sorani Kurdish / Central Kurdish language ('ckb') in ICU.
- *
- * Uses the same collation rules as Persian / Farsi ('fa'), but different characters for digits.
- */
-class CollationCkb extends IcuCollation {
-       function __construct() {
-               // This will set $locale and collators, which affect the actual sorting order
-               parent::__construct( 'fa' );
-               // Override the 'fa' language set by parent constructor, which affects #getFirstLetterData()
-               $this->digitTransformLanguage = Language::factory( 'ckb' );
-       }
-}
-
-/**
- * Workaround for incorrect collation of Estonian language ('et') in ICU (bug 54168).
- *
- * 'W' and 'V' should not be considered the same letter for the purposes of collation in modern
- * Estonian. We work around this by replacing 'W' and 'w' with 'ᴡ' U+1D21 'LATIN LETTER SMALL
- * CAPITAL W' for sortkey generation, which is collated like 'W' and is not tailored to have the
- * same primary weight as 'V' in Estonian.
- */
-class CollationEt extends IcuCollation {
-       function __construct() {
-               parent::__construct( 'et' );
-       }
-
-       private static function mangle( $string ) {
-               return str_replace(
-                       [ 'w', 'W' ],
-                       'ᴡ', // U+1D21 'LATIN LETTER SMALL CAPITAL W'
-                       $string
-               );
-       }
-
-       private static function unmangle( $string ) {
-               // Casing data is lost…
-               return str_replace(
-                       'ᴡ', // U+1D21 'LATIN LETTER SMALL CAPITAL W'
-                       'W',
-                       $string
-               );
-       }
-
-       function getSortKey( $string ) {
-               return parent::getSortKey( self::mangle( $string ) );
-       }
-
-       function getFirstLetter( $string ) {
-               return self::unmangle( parent::getFirstLetter( self::mangle( $string ) ) );
-       }
-}
index c04602c..ae2aeaa 100644 (file)
@@ -585,10 +585,9 @@ $wgLockManagers = [];
  * Requires PHP's Exif extension: http://www.php.net/manual/en/ref.exif.php
  *
  * @note FOR WINDOWS USERS:
- * To enable Exif functions, add the following lines to the "Windows
+ * To enable Exif functions, add the following line to the "Windows
  * extensions" section of php.ini:
  * @code{.ini}
- * extension=extensions/php_mbstring.dll
  * extension=extensions/php_exif.dll
  * @endcode
  */
@@ -2288,7 +2287,7 @@ $wgSessionsInObjectCache = true;
 $wgObjectCacheSessionExpiry = 3600;
 
 /**
- * @deprecated since 1.27, MediaWiki\\Session\\SessionManager doesn't use PHP session storage.
+ * @deprecated since 1.27, MediaWiki\Session\SessionManager doesn't use PHP session storage.
  */
 $wgSessionHandler = null;
 
@@ -3081,10 +3080,11 @@ $wgHtml5 = true;
 
 /**
  * Defines the value of the version attribute in the &lt;html&gt; tag, if any.
- * If $wgAllowRdfaAttributes is true, and this evaluates to boolean false
- * (like if it's left at the default null value), it will be auto-initialized
- * to the correct value for RDFa+HTML5.  As such, you should have no reason to
- * ever actually set this to anything.
+ *
+ * If your wiki uses RDFa, set it to the correct value for RDFa+HTML5.
+ * Correct current values are 'HTML+RDFa 1.0' or 'XHTML+RDFa 1.0'.
+ * See also http://www.w3.org/TR/rdfa-in-html/#document-conformance
+ * @since 1.16
  */
 $wgHtml5Version = null;
 
@@ -3105,17 +3105,6 @@ $wgHTMLFormAllowTableFormat = true;
  */
 $wgUseMediaWikiUIEverywhere = false;
 
-/**
- * Enabled RDFa attributes for use in wikitext.
- * NOTE: Interaction with HTML5 is somewhat underspecified.
- */
-$wgAllowRdfaAttributes = false;
-
-/**
- * Enabled HTML5 microdata attributes for use in wikitext.
- */
-$wgAllowMicrodataAttributes = false;
-
 /**
  * Should we try to make our HTML output well-formed XML?  If set to false,
  * output will be a few bytes shorter, and the HTML will arguably be more
@@ -3572,25 +3561,7 @@ $wgResourceLoaderMinifierMaxLineLength = 1000;
  *
  * @deprecated since 1.26: Always declare dependencies.
  */
-$wgIncludeLegacyJavaScript = true;
-
-/**
- * Whether to ensure the mediawiki.util is loaded before other modules.
- *
- * Before MediaWiki 1.19, modules used to load less asynchronous which allowed
- * modules to lack dependencies on 'popular' modules that were likely loaded already.
- *
- * This setting is to aid scripts during migration by providing mediawiki.util
- * unconditionally (which was the most commonly missed dependency). It doesn't
- * cover all missing dependencies obviously but should fix most of them.
- *
- * This should be removed at some point after site/user scripts have been fixed.
- * Enable this if your wiki has a large amount of user/site scripts that are
- * lacking dependencies.
- *
- * @deprecated since 1.26: Always declare dependencies.
- */
-$wgPreloadJavaScriptMwUtil = false;
+$wgIncludeLegacyJavaScript = false;
 
 /**
  * Whether or not to assign configuration variables to the global window object.
@@ -4659,15 +4630,15 @@ $wgAuthenticationTokenVersion = null;
  * @since 1.27
  */
 $wgSessionProviders = [
-       'MediaWiki\\Session\\CookieSessionProvider' => [
-               'class' => 'MediaWiki\\Session\\CookieSessionProvider',
+       MediaWiki\Session\CookieSessionProvider::class => [
+               'class' => MediaWiki\Session\CookieSessionProvider::class,
                'args' => [ [
                        'priority' => 30,
                        'callUserSetCookiesHook' => true,
                ] ],
        ],
-       'MediaWiki\\Session\\BotPasswordSessionProvider' => [
-               'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider',
+       MediaWiki\Session\BotPasswordSessionProvider::class => [
+               'class' => MediaWiki\Session\BotPasswordSessionProvider::class,
                'args' => [ [
                        'priority' => 40,
                ] ],
@@ -5973,7 +5944,7 @@ $wgCachePrefix = false;
 /**
  * Display the new debugging toolbar. This also enables profiling on database
  * queries and other useful output.
- * Will disable file cache.
+ * Will be ignored if $wgUseFileCache or $wgUseSquid is enabled.
  *
  * @since 1.19
  */
@@ -6238,14 +6209,15 @@ $wgGitBin = '/usr/bin/git';
  * %h will be replaced by the short SHA-1 (7 first chars) and %H by the
  * full SHA-1 of the HEAD revision.
  * %r will be replaced with a URL-encoded version of $1.
+ * %R will be replaced with $1 and no URL-encoding
  *
  * @since 1.20
  */
 $wgGitRepositoryViewers = [
        'https://(?:[a-z0-9_]+@)?gerrit.wikimedia.org/r/(?:p/)?(.*)' =>
-               'https://git.wikimedia.org/tree/%r/%H',
+               'https://phabricator.wikimedia.org/r/revision/%R;%H',
        'ssh://(?:[a-z0-9_]+@)?gerrit.wikimedia.org:29418/(.*)' =>
-               'https://git.wikimedia.org/tree/%r/%H',
+               'https://phabricator.wikimedia.org/r/revision/%R;%H',
 ];
 
 /** @} */ # End of maintenance }
@@ -6507,6 +6479,10 @@ $wgUnwatchedPageThreshold = false;
  *   'legend' => 'legend-msg',
  *   // optional (defaults to 'flag'), CSS class to put on changes lists rows
  *   'class' => 'css-class',
+ *   // optional (defaults to 'any'), how top-level flag is determined.  'any'
+ *   // will set the top-level flag if any line contains the flag, 'all' will
+ *   // only be set if all lines contain the flag.
+ *   'grouping' => 'any',
  * );
  * @endcode
  *
@@ -6517,23 +6493,27 @@ $wgRecentChangesFlags = [
                'letter' => 'newpageletter',
                'title' => 'recentchanges-label-newpage',
                'legend' => 'recentchanges-legend-newpage',
+               'grouping' => 'any',
        ],
        'minor' => [
                'letter' => 'minoreditletter',
                'title' => 'recentchanges-label-minor',
                'legend' => 'recentchanges-legend-minor',
                'class' => 'minoredit',
+               'grouping' => 'all',
        ],
        'bot' => [
                'letter' => 'boteditletter',
                'title' => 'recentchanges-label-bot',
                'legend' => 'recentchanges-legend-bot',
                'class' => 'botedit',
+               'grouping' => 'all',
        ],
        'unpatrolled' => [
                'letter' => 'unpatrolledletter',
                'title' => 'recentchanges-label-unpatrolled',
                'legend' => 'recentchanges-legend-unpatrolled',
+               'grouping' => 'any',
        ],
 ];
 
@@ -6573,12 +6553,6 @@ $wgRightsText = null;
  */
 $wgRightsIcon = null;
 
-/**
- * Set this to some HTML to override the rights icon with an arbitrary logo
- * @deprecated since 1.18 Use $wgFooterIcons['copyright']['copyright']
- */
-$wgCopyrightIcon = null;
-
 /**
  * Set this to true if you want detailed copyright information forms on Upload.
  */
@@ -6911,6 +6885,21 @@ $wgAuth = null;
  */
 $wgHooks = [];
 
+/**
+ * List of service wiring files to be loaded by the default instance of MediaWikiServices.
+ * Each file listed here is expected to return an associative array mapping service names
+ * to instantiator functions. Extensions may add wiring files to define their own services.
+ * However, this cannot be used to replace existing services - use the MediaWikiServices
+ * hook for that.
+ *
+ * @see MediaWikiServices
+ * @see ServiceContainer::loadWiringFiles() for details on loading service instantiator functions.
+ * @see docs/injection.txt for an overview of dependency injection in MediaWiki.
+ */
+$wgServiceWiringFiles = [
+       __DIR__ . '/ServiceWiring.php'
+];
+
 /**
  * Maps jobs to their handling classes; extensions
  * can add to this to provide custom jobs
@@ -7218,6 +7207,7 @@ $wgLogActionsHandlers = [
        'move/move' => 'MoveLogFormatter',
        'move/move_redir' => 'MoveLogFormatter',
        'patrol/patrol' => 'PatrolLogFormatter',
+       'patrol/autopatrol' => 'PatrolLogFormatter',
        'protect/modify' => 'ProtectLogFormatter',
        'protect/move_prot' => 'ProtectLogFormatter',
        'protect/protect' => 'ProtectLogFormatter',
@@ -7235,6 +7225,77 @@ $wgLogActionsHandlers = [
        'upload/upload' => 'UploadLogFormatter',
 ];
 
+/**
+ * List of log types that can be filtered by action types
+ *
+ * To each action is associated the list of log_action
+ * subtypes to search for, usually one, but not necessarily so
+ * Extensions may append to this array
+ * @since 1.27
+ */
+$wgActionFilteredLogs = [
+       'block' => [
+               'block' => [ 'block' ],
+               'reblock' => [ 'reblock' ],
+               'unblock' => [ 'unblock' ],
+       ],
+       'contentmodel' => [
+               'change' => [ 'change' ],
+               'new' => [ 'new' ],
+       ],
+       'delete' => [
+               'delete' => [ 'delete' ],
+               'restore' => [ 'restore' ],
+               'event' => [ 'event' ],
+               'revision' => [ 'revision' ],
+       ],
+       'import' => [
+               'interwiki' => [ 'interwiki' ],
+               'upload' => [ 'upload' ],
+       ],
+       'managetags' => [
+               'create' => [ 'create' ],
+               'delete' => [ 'delete' ],
+               'activate' => [ 'activate' ],
+               'deactivate' => [ 'deactivate' ],
+       ],
+       'move' => [
+               'move' => [ 'move' ],
+               'move_redir' => [ 'move_redir' ],
+       ],
+       'newusers' => [
+               'create' => [ 'create', 'newusers' ],
+               'create2' => ['create2' ],
+               'autocreate' => [ 'autocreate' ],
+               'byemail' => [ 'byemail' ],
+       ],
+       'patrol' => [
+               'patrol' => [ 'patrol' ],
+               'autopatrol' => [ 'autopatrol' ],
+       ],
+       'protect' => [
+               'protect' => [ 'protect' ],
+               'modify' => [ 'modify' ],
+               'unprotect' => [ 'unprotect' ],
+               'move_prot' => ['move_prot'],
+       ],
+       'rights' => [
+               'rights' => [ 'rights' ],
+               'autopromote' => [ 'autopromote' ],
+       ],
+       'suppress' => [
+               'event' => [ 'event' ],
+               'revision' => [ 'revision' ],
+               'delete' => [ 'delete' ],
+               'block' => [ 'block' ],
+               'reblock' => [ 'reblock' ],
+       ],
+       'upload' => [
+               'upload' => [ 'upload' ],
+               'overwrite' => [ 'overwrite' ],
+       ],
+];
+
 /**
  * Maintain a log of newusers at Log/newusers?
  */
index 3268700..3522531 100644 (file)
@@ -530,11 +530,12 @@ class EditPage {
                if ( $permErrors ) {
                        wfDebug( __METHOD__ . ": User can't edit\n" );
                        // Auto-block user's IP if the account was "hard" blocked
-                       $user = $wgUser;
-                       DeferredUpdates::addCallableUpdate( function() use ( $user ) {
-                               $user->spreadAnyEditBlock();
-                       } );
-
+                       if ( !wfReadOnly() ) {
+                               $user = $wgUser;
+                               DeferredUpdates::addCallableUpdate( function () use ( $user ) {
+                                       $user->spreadAnyEditBlock();
+                               } );
+                       }
                        $this->displayPermissionsError( $permErrors );
 
                        return;
@@ -1174,7 +1175,7 @@ class EditPage {
         * Get the content of the wanted revision, without section extraction.
         *
         * The result of this function can be used to compare user's input with
-        * section replaced in its context (using WikiPage::replaceSection())
+        * section replaced in its context (using WikiPage::replaceSectionAtRev())
         * to the original text of the edit.
         *
         * This differs from Article::getContent() that when a missing revision is
@@ -1520,7 +1521,7 @@ class EditPage {
                                // is if an extension hook aborted from inside ArticleSave.
                                // Render the status object into $this->hookError
                                // FIXME this sucks, we should just use the Status object throughout
-                               $this->hookError = '<div class="error">' . $status->getWikitext() .
+                               $this->hookError = '<div class="error">' . $status->getWikiText() .
                                        '</div>';
                                return true;
                }
@@ -1735,7 +1736,9 @@ class EditPage {
 
                if ( $wgUser->isBlockedFrom( $this->mTitle, false ) ) {
                        // Auto-block user's IP if the account was "hard" blocked
-                       $wgUser->spreadAnyEditBlock();
+                       if ( !wfReadOnly() ) {
+                               $wgUser->spreadAnyEditBlock();
+                       }
                        # Check block state against master, thus 'false'.
                        $status->setResult( false, self::AS_BLOCKED_PAGE_FOR_USER );
                        return $status;
@@ -1979,7 +1982,7 @@ class EditPage {
                        } elseif ( $this->section != '' ) {
                                # Try to get a section anchor from the section source, redirect
                                # to edited section if header found.
-                               # XXX: Might be better to integrate this into Article::replaceSection
+                               # XXX: Might be better to integrate this into Article::replaceSectionAtRev
                                # for duplicate heading checking and maybe parsing.
                                $hasmatch = preg_match( "/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches );
                                # We can't deal with anchors, includes, html etc in the header for now,
diff --git a/includes/Fallback.php b/includes/Fallback.php
deleted file mode 100644 (file)
index 4c19dca..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-/**
- * Fallback functions for PHP installed without mbstring support.
- *
- * 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
- */
-
-/**
- * Fallback functions for PHP installed without mbstring support
- */
-class Fallback {
-
-       /**
-        * Fallback implementation for mb_substr, hardcoded to UTF-8.
-        * Attempts to be at least _moderately_ efficient; best optimized
-        * for relatively small offset and count values -- about 5x slower
-        * than native mb_string in my testing.
-        *
-        * Larger offsets are still fairly efficient for Latin text, but
-        * can be up to 100x slower than native if the text is heavily
-        * multibyte and we have to slog through a few hundred kb.
-        *
-        * @param string $str
-        * @param int $start
-        * @param string $count
-        *
-        * @return string
-        */
-       public static function mb_substr( $str, $start, $count = 'end' ) {
-               if ( $start != 0 ) {
-                       $split = self::mb_substr_split_unicode( $str, intval( $start ) );
-                       $str = substr( $str, $split );
-               }
-
-               if ( $count !== 'end' ) {
-                       $split = self::mb_substr_split_unicode( $str, intval( $count ) );
-                       $str = substr( $str, 0, $split );
-               }
-
-               return $str;
-       }
-
-       /**
-        * @param string $str
-        * @param int $splitPos
-        * @return int
-        */
-       public static function mb_substr_split_unicode( $str, $splitPos ) {
-               if ( $splitPos == 0 ) {
-                       return 0;
-               }
-
-               $byteLen = strlen( $str );
-
-               if ( $splitPos > 0 ) {
-                       if ( $splitPos > 256 ) {
-                               // Optimize large string offsets by skipping ahead N bytes.
-                               // This will cut out most of our slow time on Latin-based text,
-                               // and 1/2 to 1/3 on East European and Asian scripts.
-                               $bytePos = $splitPos;
-                               while ( $bytePos < $byteLen && $str[$bytePos] >= "\x80" && $str[$bytePos] < "\xc0" ) {
-                                       ++$bytePos;
-                               }
-                               $charPos = mb_strlen( substr( $str, 0, $bytePos ) );
-                       } else {
-                               $charPos = 0;
-                               $bytePos = 0;
-                       }
-
-                       while ( $charPos++ < $splitPos ) {
-                               ++$bytePos;
-                               // Move past any tail bytes
-                               while ( $bytePos < $byteLen && $str[$bytePos] >= "\x80" && $str[$bytePos] < "\xc0" ) {
-                                       ++$bytePos;
-                               }
-                       }
-               } else {
-                       $splitPosX = $splitPos + 1;
-                       $charPos = 0; // relative to end of string; we don't care about the actual char position here
-                       $bytePos = $byteLen;
-                       while ( $bytePos > 0 && $charPos-- >= $splitPosX ) {
-                               --$bytePos;
-                               // Move past any tail bytes
-                               while ( $bytePos > 0 && $str[$bytePos] >= "\x80" && $str[$bytePos] < "\xc0" ) {
-                                       --$bytePos;
-                               }
-                       }
-               }
-
-               return $bytePos;
-       }
-
-       /**
-        * Fallback implementation of mb_strlen, hardcoded to UTF-8.
-        * @param string $str
-        * @param string $enc Optional encoding; ignored
-        * @return int
-        */
-       public static function mb_strlen( $str, $enc = '' ) {
-               $counts = count_chars( $str );
-               $total = 0;
-
-               // Count ASCII bytes
-               for ( $i = 0; $i < 0x80; $i++ ) {
-                       $total += $counts[$i];
-               }
-
-               // Count multibyte sequence heads
-               for ( $i = 0xc0; $i < 0xff; $i++ ) {
-                       $total += $counts[$i];
-               }
-               return $total;
-       }
-
-       /**
-        * Fallback implementation of mb_strpos, hardcoded to UTF-8.
-        * @param string $haystack
-        * @param string $needle
-        * @param string $offset Optional start position
-        * @param string $encoding Optional encoding; ignored
-        * @return int
-        */
-       public static function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
-               $needle = preg_quote( $needle, '/' );
-
-               $ar = [];
-               preg_match( '/' . $needle . '/u', $haystack, $ar, PREG_OFFSET_CAPTURE, $offset );
-
-               if ( isset( $ar[0][1] ) ) {
-                       return $ar[0][1];
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * Fallback implementation of mb_strrpos, hardcoded to UTF-8.
-        * @param string $haystack
-        * @param string $needle
-        * @param string $offset Optional start position
-        * @param string $encoding Optional encoding; ignored
-        * @return int
-        */
-       public static function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
-               $needle = preg_quote( $needle, '/' );
-
-               $ar = [];
-               preg_match_all( '/' . $needle . '/u', $haystack, $ar, PREG_OFFSET_CAPTURE, $offset );
-
-               if ( isset( $ar[0] ) && count( $ar[0] ) > 0 &&
-                       isset( $ar[0][count( $ar[0] ) - 1][1] ) ) {
-                       return $ar[0][count( $ar[0] ) - 1][1];
-               } else {
-                       return false;
-               }
-       }
-}
index c2108f2..158c852 100644 (file)
@@ -39,7 +39,7 @@ class FauxRequest extends WebRequest {
         * @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
-        * @param MediaWiki\\Session\\Session|array|null $session Session, session
+        * @param MediaWiki\Session\Session|array|null $session Session, session
         *  data array, or null
         * @param string $protocol 'http' or 'https'
         * @throws MWException
index 14f3cc1..de7e8c2 100644 (file)
@@ -43,7 +43,7 @@ class GitInfo {
        /**
         * Cached git information.
         */
-       protected $cache = array();
+       protected $cache = [];
 
        /**
         * Map of repo URLs to viewer URLs. Access via static method getViewers().
@@ -215,7 +215,7 @@ class GitInfo {
                                is_executable( $wgGitBin ) &&
                                $this->getHead() !== false
                        ) {
-                               $environment = array( "GIT_DIR" => $this->basedir );
+                               $environment = [ "GIT_DIR" => $this->basedir ];
                                $cmd = wfEscapeShellArg( $wgGitBin ) .
                                        " show -s --format=format:%ct HEAD";
                                $retc = false;
@@ -257,19 +257,17 @@ class GitInfo {
                if ( $url === false ) {
                        return false;
                }
-               if ( substr( $url, -4 ) !== '.git' ) {
-                       $url .= '.git';
-               }
                foreach ( self::getViewers() as $repo => $viewer ) {
                        $pattern = '#^' . $repo . '$#';
                        if ( preg_match( $pattern, $url, $matches ) ) {
                                $viewerUrl = preg_replace( $pattern, $viewer, $url );
                                $headSHA1 = $this->getHeadSHA1();
-                               $replacements = array(
+                               $replacements = [
                                        '%h' => substr( $headSHA1, 0, 7 ),
                                        '%H' => $headSHA1,
                                        '%r' => urlencode( $matches[1] ),
-                               );
+                                       '%R' => $matches[1],
+                               ];
                                return strtr( $viewerUrl, $replacements );
                        }
                }
@@ -396,7 +394,7 @@ class GitInfo {
 
                if ( self::$viewers === false ) {
                        self::$viewers = $wgGitRepositoryViewers;
-                       Hooks::run( 'GitViewers', array( &self::$viewers ) );
+                       Hooks::run( 'GitViewers', [ &self::$viewers ] );
                }
 
                return self::$viewers;
index 3fa91fa..5c42bc2 100644 (file)
@@ -39,59 +39,6 @@ use MediaWiki\Session\SessionManager;
  * PHP extensions may be included here.
  */
 
-if ( !function_exists( 'mb_substr' ) ) {
-       /**
-        * @codeCoverageIgnore
-        * @see Fallback::mb_substr
-        * @return string
-        */
-       function mb_substr( $str, $start, $count = 'end' ) {
-               return Fallback::mb_substr( $str, $start, $count );
-       }
-
-       /**
-        * @codeCoverageIgnore
-        * @see Fallback::mb_substr_split_unicode
-        * @return int
-        */
-       function mb_substr_split_unicode( $str, $splitPos ) {
-               return Fallback::mb_substr_split_unicode( $str, $splitPos );
-       }
-}
-
-if ( !function_exists( 'mb_strlen' ) ) {
-       /**
-        * @codeCoverageIgnore
-        * @see Fallback::mb_strlen
-        * @return int
-        */
-       function mb_strlen( $str, $enc = '' ) {
-               return Fallback::mb_strlen( $str, $enc );
-       }
-}
-
-if ( !function_exists( 'mb_strpos' ) ) {
-       /**
-        * @codeCoverageIgnore
-        * @see Fallback::mb_strpos
-        * @return int
-        */
-       function mb_strpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
-               return Fallback::mb_strpos( $haystack, $needle, $offset, $encoding );
-       }
-}
-
-if ( !function_exists( 'mb_strrpos' ) ) {
-       /**
-        * @codeCoverageIgnore
-        * @see Fallback::mb_strrpos
-        * @return int
-        */
-       function mb_strrpos( $haystack, $needle, $offset = 0, $encoding = '' ) {
-               return Fallback::mb_strrpos( $haystack, $needle, $offset, $encoding );
-       }
-}
-
 // hash_equals function only exists in PHP >= 5.6.0
 // http://php.net/hash_equals
 if ( !function_exists( 'hash_equals' ) ) {
@@ -2990,7 +2937,7 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1,
 
 /**
  * @deprecated since 1.27, PHP's session generation isn't used with
- *  MediaWiki\\Session\\SessionManager
+ *  MediaWiki\Session\SessionManager
  */
 function wfFixSessionID() {
        wfDeprecated( __FUNCTION__, '1.27' );
@@ -2999,7 +2946,7 @@ function wfFixSessionID() {
 /**
  * Reset the session id
  *
- * @deprecated since 1.27, use MediaWiki\\Session\\SessionManager instead
+ * @deprecated since 1.27, use MediaWiki\Session\SessionManager instead
  * @since 1.22
  */
 function wfResetSessionID() {
@@ -3021,7 +2968,7 @@ function wfResetSessionID() {
 /**
  * Initialise php session
  *
- * @deprecated since 1.27, use MediaWiki\\Session\\SessionManager instead.
+ * @deprecated since 1.27, use MediaWiki\Session\SessionManager instead.
  *  Generally, "using" SessionManager will be calling ->getSessionById() or
  *  ::getGlobalSession() (depending on whether you were passing $sessionId
  *  here), then calling $session->persist().
index 87fc012..8673125 100644 (file)
@@ -263,7 +263,7 @@ class HistoryBlobStub {
                                if ( !isset( $parts[1] ) || $parts[1] == '' ) {
                                        return false;
                                }
-                               $row->old_text = ExternalStore::fetchFromUrl( $url );
+                               $row->old_text = ExternalStore::fetchFromURL( $url );
 
                        }
 
index 3b36039..890beb0 100644 (file)
@@ -216,7 +216,7 @@ class Html {
                if ( in_array( $element, self::$voidElements ) ) {
                        if ( $wgWellFormedXml ) {
                                // Silly XML.
-                               return substr( $start, 0, -1 ) . ' />';
+                               return substr( $start, 0, -1 ) . '/>';
                        }
                        return $start;
                } else {
index 5b8122d..206f0f7 100644 (file)
@@ -63,15 +63,9 @@ class HtmlFormatter {
         */
        public function getDoc() {
                if ( !$this->doc ) {
-                       // DOMDocument::loadHTML apparently isn't very good with encodings, so
+                       // DOMDocument::loadHTML isn't very good with encodings, so
                        // convert input to ASCII by encoding everything above 128 as entities.
-                       if ( function_exists( 'mb_convert_encoding' ) ) {
-                               $html = mb_convert_encoding( $this->html, 'HTML-ENTITIES', 'UTF-8' );
-                       } else {
-                               $html = preg_replace_callback( '/[\x{80}-\x{10ffff}]/u', function ( $m ) {
-                                       return '&#' . UtfNormal\Utils::utf8ToCodepoint( $m[0] ) . ';';
-                               }, $this->html );
-                       }
+                       $html = mb_convert_encoding( $this->html, 'HTML-ENTITIES', 'UTF-8' );
 
                        // Workaround for bug that caused spaces before references
                        // to disappear during processing: https://phabricator.wikimedia.org/T55086
@@ -251,13 +245,10 @@ class HtmlFormatter {
                }
                $html = $replacements->replace( $html );
 
-               if ( function_exists( 'mb_convert_encoding' ) ) {
-                       // Just in case the conversion in getDoc() above used named
-                       // entities that aren't known to html_entity_decode().
-                       $html = mb_convert_encoding( $html, 'UTF-8', 'HTML-ENTITIES' );
-               } else {
-                       $html = html_entity_decode( $html, ENT_COMPAT, 'utf-8' );
-               }
+               // Just in case the conversion in getDoc() above used named
+               // entities that aren't known to html_entity_decode().
+               $html = mb_convert_encoding( $html, 'UTF-8', 'HTML-ENTITIES' );
+
                return $html;
        }
 
@@ -290,7 +281,7 @@ class HtmlFormatter {
                        }
                        $html = $this->doc->saveHTML();
 
-                       $html = $this->fixLibXml( $html );
+                       $html = $this->fixLibXML( $html );
                        if ( wfIsWindows() ) {
                                // Cleanup for CRLF misprocessing of unknown origin on Windows.
                                // If this error continues in the future, please track it down in the
index f980a93..3f42038 100644 (file)
@@ -192,6 +192,26 @@ class Http {
                        $uri
                );
        }
+
+       /**
+        * Gets the relevant proxy from $wgHTTPProxy/http_proxy (when set).
+        *
+        * @return mixed The proxy address or an empty string if not set.
+        */
+       public static function getProxy() {
+               global $wgHTTPProxy;
+
+               if ( $wgHTTPProxy ) {
+                       return $wgHTTPProxy;
+               }
+
+               $envHttpProxy = getenv( "http_proxy" );
+               if ( $envHttpProxy ) {
+                       return $envHttpProxy;
+               }
+
+               return "";
+       }
 }
 
 /**
@@ -368,8 +388,6 @@ class MWHttpRequest {
         * @return void
         */
        public function proxySetup() {
-               global $wgHTTPProxy;
-
                // If there is an explicit proxy set and proxies are not disabled, then use it
                if ( $this->proxy && !$this->noProxy ) {
                        return;
@@ -379,10 +397,8 @@ class MWHttpRequest {
                // local URL and proxies are not disabled
                if ( Http::isLocalURL( $this->url ) || $this->noProxy ) {
                        $this->proxy = '';
-               } elseif ( $wgHTTPProxy ) {
-                       $this->proxy = $wgHTTPProxy;
-               } elseif ( getenv( "http_proxy" ) ) {
-                       $this->proxy = getenv( "http_proxy" );
+               } else {
+                       $this->proxy = Http::getProxy();
                }
        }
 
@@ -991,7 +1007,7 @@ class PhpHttpRequest extends MWHttpRequest {
                ];
 
                if ( $this->proxy ) {
-                       $options['http']['proxy'] = $this->urlToTCP( $this->proxy );
+                       $options['http']['proxy'] = $this->urlToTcp( $this->proxy );
                        $options['http']['request_fulluri'] = true;
                }
 
index 43df839..4ba3a75 100644 (file)
@@ -992,7 +992,7 @@ class Linker {
         */
        public static function makeMediaLinkFile( Title $title, $file, $html = '' ) {
                if ( $file && $file->exists() ) {
-                       $url = $file->getURL();
+                       $url = $file->getUrl();
                        $class = 'internal';
                } else {
                        $url = self::getUploadUrl( $title );
index 45a1385..ad02e68 100644 (file)
@@ -246,13 +246,13 @@ class MediaWiki {
                } elseif ( !$this->tryNormaliseRedirect( $title ) ) {
                        // Prevent information leak via Special:MyPage et al (T109724)
                        if ( $title->isSpecialPage() ) {
-                               $specialPage = SpecialPageFactory::getPage( $title->getDBKey() );
+                               $specialPage = SpecialPageFactory::getPage( $title->getDBkey() );
                                if ( $specialPage instanceof RedirectSpecialPage ) {
                                        $specialPage->setContext( $this->context );
                                        if ( $this->config->get( 'HideIdentifiableRedirects' )
                                                && $specialPage->personallyIdentifiableTarget()
                                        ) {
-                                               list( , $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBKey() );
+                                               list( , $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
                                                $target = $specialPage->getRedirect( $subpage );
                                                // target can also be true. We let that case fall through to normal processing.
                                                if ( $target instanceof Title ) {
@@ -830,9 +830,18 @@ class MediaWiki {
                $errno = $errstr = null;
                $info = wfParseUrl( $this->config->get( 'Server' ) );
                MediaWiki\suppressWarnings();
+               $host = $info['host'];
+               $port = 80;
+               if ( isset( $info['scheme'] ) && $info['scheme'] == 'https' ) {
+                       $host = "tls://" . $host;
+                       $port = 443;
+               }
+               if ( isset( $info['port'] ) ) {
+                       $port = $info['port'];
+               }
                $sock = fsockopen(
-                       $info['host'],
-                       isset( $info['port'] ) ? $info['port'] : 80,
+                       $host,
+                       $port,
                        $errno,
                        $errstr,
                        // If it takes more than 100ms to connect to ourselves there
diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php
new file mode 100644 (file)
index 0000000..7b1def9
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+namespace MediaWiki;
+
+use ConfigFactory;
+use GlobalVarConfig;
+use Config;
+use Hooks;
+use LBFactory;
+use LoadBalancer;
+use MediaWiki\Services\ServiceContainer;
+use SiteLookup;
+use SiteStore;
+
+/**
+ * Service locator for MediaWiki core services.
+ *
+ * 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
+ *
+ * @since 1.27
+ */
+
+/**
+ * MediaWikiServices is the service locator for the application scope of MediaWiki.
+ * Its implemented as a simple configurable DI container.
+ * MediaWikiServices acts as a top level factory/registry for top level services, and builds
+ * the network of service objects that defines MediaWiki's application logic.
+ * It acts as an entry point to MediaWiki's dependency injection mechanism.
+ *
+ * Services are defined in the "wiring" array passed to the constructor,
+ * or by calling defineService().
+ *
+ * @see docs/injection.txt for an overview of using dependency injection in the
+ *      MediaWiki code base.
+ */
+class MediaWikiServices extends ServiceContainer {
+
+       /**
+        * Returns the global default instance of the top level service locator.
+        *
+        * The default instance is initialized using the service instantiator functions
+        * defined in ServiceWiring.php.
+        *
+        * @note This should only be called by static functions! The instance returned here
+        * should not be passed around! Objects that need access to a service should have
+        * that service injected into the constructor, never a service locator!
+        *
+        * @return MediaWikiServices
+        */
+       public static function getInstance() {
+               static $instance = null;
+
+               if ( $instance === null ) {
+                       // NOTE: constructing GlobalVarConfig here is not particularly pretty,
+                       // but some information from the global scope has to be injected here,
+                       // even if it's just a file name or database credentials to load
+                       // configuration from.
+                       $config = new GlobalVarConfig();
+                       $instance = new self( $config );
+
+                       // Load the default wiring from the specified files.
+                       $wiringFiles = $config->get( 'ServiceWiringFiles' );
+                       $instance->loadWiringFiles( $wiringFiles );
+
+                       // Provide a traditional hook point to allow extensions to configure services.
+                       Hooks::run( 'MediaWikiServices', [ $instance ] );
+               }
+
+               return $instance;
+       }
+
+       /**
+        * @param Config $config The Config object to be registered as the 'BootstrapConfig' service.
+        *        This has to contain at least the information needed to set up the 'ConfigFactory'
+        *        service.
+        */
+       public function __construct( Config $config ) {
+               parent::__construct();
+
+               // register the given Config object as the bootstrap config service.
+               $this->defineService( 'BootstrapConfig', function() use ( $config ) {
+                       return $config;
+               } );
+       }
+
+       /**
+        * Returns the Config object containing the bootstrap configuration.
+        * Bootstrap configuration would typically include database credentials
+        * and other information that may be needed before the ConfigFactory
+        * service can be instantiated.
+        *
+        * @note This should only be used during bootstrapping, in particular
+        * when creating the MainConfig service. Application logic should
+        * use getMainConfig() to get a Config instances.
+        *
+        * @return Config
+        */
+       public function getBootstrapConfig() {
+               return $this->getService( 'BootstrapConfig' );
+       }
+
+       /**
+        * @return ConfigFactory
+        */
+       public function getConfigFactory() {
+               return $this->getService( 'ConfigFactory' );
+       }
+
+       /**
+        * Returns the Config object that provides configuration for MediaWiki core.
+        * This may or may not be the same object that is returned by getBootstrapConfig().
+        *
+        * @return Config
+        */
+       public function getMainConfig() {
+               return $this->getService( 'MainConfig' );
+       }
+
+       /**
+        * @return SiteLookup
+        */
+       public function getSiteLookup() {
+               return $this->getService( 'SiteLookup' );
+       }
+
+       /**
+        * @return SiteStore
+        */
+       public function getSiteStore() {
+               return $this->getService( 'SiteStore' );
+       }
+
+       ///////////////////////////////////////////////////////////////////////////
+       // NOTE: When adding a service getter here, don't forget to add a test
+       // case for it in MediaWikiServicesTest::provideGetters() and in
+       // MediaWikiServicesTest::provideGetService()!
+       ///////////////////////////////////////////////////////////////////////////
+
+}
index a92056d..441fe9e 100644 (file)
@@ -51,7 +51,7 @@ class MergeHistory {
        /** @var string SQL WHERE condition that selects source revisions to insert into destination */
        protected $timeWhere;
 
-       /** @var MWTimestamp|boolean Timestamp upto which history from the source will be merged */
+       /** @var MWTimestamp|bool Timestamp upto which history from the source will be merged */
        protected $timestampLimit;
 
        /** @var integer Number of revisions merged (for Special:MergeHistory success message) */
@@ -61,7 +61,7 @@ class MergeHistory {
         * MergeHistory constructor.
         * @param Title $source Page from which history will be merged
         * @param Title $dest Page to which history will be merged
-        * @param string|boolean $timestamp Timestamp up to which history from the source will be merged
+        * @param string|bool $timestamp Timestamp up to which history from the source will be merged
         */
        public function __construct( Title $source, Title $dest, $timestamp = false ) {
                // Save the parameters
index 9d5f5e6..fd016fc 100644 (file)
@@ -160,19 +160,18 @@ class Message implements MessageSpecifier, Serializable {
 
        /**
         * In which language to get this message. True, which is the default,
-        * means the current interface language, false content language.
+        * means the current user language, false content language.
         *
         * @var bool
         */
        protected $interface = true;
 
        /**
-        * In which language to get this message. Overrides the $interface
-        * variable.
+        * In which language to get this message. Overrides the $interface setting.
         *
-        * @var Language
+        * @var Language|bool Explicit language object, or false for user language
         */
-       protected $language = null;
+       protected $language = false;
 
        /**
         * @var string The message key. If $keysToTry has more than one element,
@@ -225,18 +224,14 @@ class Message implements MessageSpecifier, Serializable {
 
        /**
         * @since 1.17
-        *
         * @param string|string[]|MessageSpecifier $key Message key, or array of
         * message keys to try and use the first non-empty message for, or a
         * MessageSpecifier to copy from.
         * @param array $params Message parameters.
-        * @param Language $language Optional language of the message, defaults to $wgLang.
-        *
+        * @param Language $language [optional] Language to use (defaults to current user language).
         * @throws InvalidArgumentException
         */
        public function __construct( $key, $params = [], Language $language = null ) {
-               global $wgLang;
-
                if ( $key instanceof MessageSpecifier ) {
                        if ( $params ) {
                                throw new InvalidArgumentException(
@@ -260,7 +255,9 @@ class Message implements MessageSpecifier, Serializable {
                $this->key = reset( $this->keysToTry );
 
                $this->parameters = array_values( $params );
-               $this->language = $language ?: $wgLang;
+               // User language is only resolved in getLanguage(). This helps preserve the
+               // semantic intent of "user language" across serialize() and unserialize().
+               $this->language = $language ?: false;
        }
 
        /**
@@ -271,7 +268,7 @@ class Message implements MessageSpecifier, Serializable {
        public function serialize() {
                return serialize( [
                        'interface' => $this->interface,
-                       'language' => $this->language instanceof StubUserLang ? false : $this->language->getCode(),
+                       'language' => $this->language ? $this->language->getCode() : false,
                        'key' => $this->key,
                        'keysToTry' => $this->keysToTry,
                        'parameters' => $this->parameters,
@@ -287,8 +284,6 @@ class Message implements MessageSpecifier, Serializable {
         * @param string $serialized
         */
        public function unserialize( $serialized ) {
-               global $wgLang;
-
                $data = unserialize( $serialized );
                $this->interface = $data['interface'];
                $this->key = $data['key'];
@@ -296,7 +291,7 @@ class Message implements MessageSpecifier, Serializable {
                $this->parameters = $data['parameters'];
                $this->format = $data['format'];
                $this->useDatabase = $data['useDatabase'];
-               $this->language = $data['language'] ? Language::factory( $data['language'] ) : $wgLang;
+               $this->language = $data['language'] ? Language::factory( $data['language'] ) : false;
                $this->title = $data['title'];
        }
 
@@ -365,7 +360,8 @@ class Message implements MessageSpecifier, Serializable {
         * @return Language
         */
        public function getLanguage() {
-               return $this->language;
+               // Defaults to false which means current user language
+               return $this->language ?: RequestContext::getMain()->getLanguage();
        }
 
        /**
@@ -425,7 +421,7 @@ class Message implements MessageSpecifier, Serializable {
        public function getTitle() {
                global $wgContLang, $wgForceUIMsgAsContentMsg;
 
-               $code = $this->language->getCode();
+               $code = $this->getLanguage()->getCode();
                $title = $this->key;
                if (
                        $wgContLang->getCode() !== $code
@@ -656,23 +652,24 @@ class Message implements MessageSpecifier, Serializable {
 
        /**
         * Request the message in any language that is supported.
+        *
         * As a side effect interface message status is unconditionally
         * turned off.
         *
         * @since 1.17
-        *
         * @param Language|string $lang Language code or Language object.
-        *
         * @return Message $this
         * @throws MWException
         */
        public function inLanguage( $lang ) {
-               if ( $lang instanceof Language || $lang instanceof StubUserLang ) {
+               if ( $lang instanceof Language ) {
                        $this->language = $lang;
                } elseif ( is_string( $lang ) ) {
                        if ( !$this->language instanceof Language || $this->language->getCode() != $lang ) {
                                $this->language = Language::factory( $lang );
                        }
+               } elseif ( $lang instanceof StubUserLang ) {
+                       $this->language = false;
                } else {
                        $type = gettype( $lang );
                        throw new MWException( __METHOD__ . " must be "
@@ -1061,17 +1058,17 @@ class Message implements MessageSpecifier, Serializable {
                        } elseif ( isset( $param['num'] ) ) {
                                // Replace number params always in before step for now.
                                // No support for combined raw and num params
-                               return [ 'before', $this->language->formatNum( $param['num'] ) ];
+                               return [ 'before', $this->getLanguage()->formatNum( $param['num'] ) ];
                        } elseif ( isset( $param['duration'] ) ) {
-                               return [ 'before', $this->language->formatDuration( $param['duration'] ) ];
+                               return [ 'before', $this->getLanguage()->formatDuration( $param['duration'] ) ];
                        } elseif ( isset( $param['expiry'] ) ) {
-                               return [ 'before', $this->language->formatExpiry( $param['expiry'] ) ];
+                               return [ 'before', $this->getLanguage()->formatExpiry( $param['expiry'] ) ];
                        } elseif ( isset( $param['period'] ) ) {
-                               return [ 'before', $this->language->formatTimePeriod( $param['period'] ) ];
+                               return [ 'before', $this->getLanguage()->formatTimePeriod( $param['period'] ) ];
                        } elseif ( isset( $param['size'] ) ) {
-                               return [ 'before', $this->language->formatSize( $param['size'] ) ];
+                               return [ 'before', $this->getLanguage()->formatSize( $param['size'] ) ];
                        } elseif ( isset( $param['bitrate'] ) ) {
-                               return [ 'before', $this->language->formatBitrate( $param['bitrate'] ) ];
+                               return [ 'before', $this->getLanguage()->formatBitrate( $param['bitrate'] ) ];
                        } elseif ( isset( $param['plaintext'] ) ) {
                                return [ 'after', $this->formatPlaintext( $param['plaintext'] ) ];
                        } else {
@@ -1108,7 +1105,7 @@ class Message implements MessageSpecifier, Serializable {
                        $this->title,
                        /*linestart*/true,
                        $this->interface,
-                       $this->language
+                       $this->getLanguage()
                );
 
                return $out instanceof ParserOutput ? $out->getText() : $out;
@@ -1127,7 +1124,7 @@ class Message implements MessageSpecifier, Serializable {
                return MessageCache::singleton()->transform(
                        $string,
                        $this->interface,
-                       $this->language,
+                       $this->getLanguage(),
                        $this->title
                );
        }
@@ -1145,7 +1142,7 @@ class Message implements MessageSpecifier, Serializable {
                        $cache = MessageCache::singleton();
 
                        foreach ( $this->keysToTry as $key ) {
-                               $message = $cache->get( $key, $this->useDatabase, $this->language );
+                               $message = $cache->get( $key, $this->useDatabase, $this->getLanguage() );
                                if ( $message !== false && $message !== '' ) {
                                        break;
                                }
index aedfd8f..a432d44 100644 (file)
@@ -645,7 +645,7 @@ class MimeMagic {
                        throw new MWException(
                                "Seeking $tailLength bytes from EOF failed in " . __METHOD__ );
                }
-               $tail = fread( $f, $tailLength );
+               $tail = $tailLength ? fread( $f, $tailLength ) : '';
                fclose( $f );
 
                wfDebug( __METHOD__ . ": analyzing head and tail of $file for magic numbers.\n" );
index 321b7e3..b9af755 100644 (file)
@@ -238,7 +238,7 @@ class MovePage {
                        $file->load( File::READ_LATEST );
                        if ( $file->exists() ) {
                                $status = $file->move( $this->newTitle );
-                               if ( !$status->isOk() ) {
+                               if ( !$status->isOK() ) {
                                        return $status;
                                }
                        }
index 305359f..c724207 100644 (file)
@@ -460,7 +460,7 @@ class OutputPage extends ContextSource {
         * @param string $script Raw HTML
         */
        function addScript( $script ) {
-               $this->mScripts .= $script . "\n";
+               $this->mScripts .= $script;
        }
 
        /**
@@ -516,7 +516,7 @@ class OutputPage extends ContextSource {
         * @param string $script JavaScript text, no "<script>" tags
         */
        public function addInlineScript( $script ) {
-               $this->mScripts .= Html::inlineScript( "\n$script\n" ) . "\n";
+               $this->mScripts .= Html::inlineScript( $script );
        }
 
        /**
@@ -2315,11 +2315,21 @@ class OutputPage extends ContextSource {
                        // adding of CSS or Javascript by extensions.
                        Hooks::run( 'BeforePageDisplay', [ &$this, &$sk ] );
 
-                       $sk->outputPage();
+                       try {
+                               $sk->outputPage();
+                       } catch ( Exception $e ) {
+                               ob_end_clean(); // bug T129657
+                               throw $e;
+                       }
                }
 
-               // This hook allows last minute changes to final overall output by modifying output buffer
-               Hooks::run( 'AfterFinalPageOutput', [ $this ] );
+               try {
+                       // This hook allows last minute changes to final overall output by modifying output buffer
+                       Hooks::run( 'AfterFinalPageOutput', [ $this ] );
+               } catch ( Exception $e ) {
+                       ob_end_clean(); // bug T129657
+                       throw $e;
+               }
 
                $this->sendCacheControl();
 
@@ -2942,7 +2952,7 @@ class OutputPage extends ContextSource {
         * @return string HTML fragment
         */
        function getHeadScripts() {
-               return $this->getInlineHeadScripts() . "\n" . $this->getExternalHeadScripts();
+               return $this->getInlineHeadScripts() . $this->getExternalHeadScripts();
        }
 
        /**
@@ -3167,7 +3177,7 @@ class OutputPage extends ContextSource {
                        $articleId = $wikiPage->getId();
                }
 
-               $lang = $title->getPageLanguage();
+               $lang = $title->getPageViewLanguage();
 
                // Pre-process information
                $separatorTransTable = $lang->separatorTransformTable();
@@ -3209,7 +3219,8 @@ class OutputPage extends ContextSource {
                        'wgMonthNames' => $lang->getMonthNamesArray(),
                        'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
                        'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(),
-                       'wgRelevantArticleId' => $relevantTitle->getArticleId(),
+                       'wgRelevantArticleId' => $relevantTitle->getArticleID(),
+                       'wgRequestId' => WebRequest::getRequestId(),
                ];
 
                if ( $user->isLoggedIn() ) {
@@ -3624,7 +3635,7 @@ class OutputPage extends ContextSource {
                        # If wanted, and the interface is right-to-left, flip the CSS
                        $style_css = CSSJanus::transform( $style_css, true, false );
                }
-               $this->mInlineStyles .= Html::inlineStyle( $style_css ) . "\n";
+               $this->mInlineStyles .= Html::inlineStyle( $style_css );
        }
 
        /**
@@ -3676,7 +3687,7 @@ class OutputPage extends ContextSource {
                        if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
                                $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
                        }
-                       $otherTags[] = Html::inlineStyle( $previewedCSS ) . "\n";
+                       $otherTags[] = Html::inlineStyle( $previewedCSS );
                } else {
                        // Load the user styles normally
                        $moduleStyles[] = 'user';
@@ -3715,7 +3726,7 @@ class OutputPage extends ContextSource {
                        ResourceLoaderModule::TYPE_STYLES
                );
                // Add normal styles added through addStyle()/addInlineStyle() here
-               $links[] = implode( "\n", $this->buildCssLinksArray() ) . $this->mInlineStyles;
+               $links[] = implode( '', $this->buildCssLinksArray() ) . $this->mInlineStyles;
                // Add marker tag to mark the place where the client-side
                // loader should inject dynamic styles
                // We use a <meta> tag with a made-up name for this because that's valid HTML
index 54176a6..66a8152 100644 (file)
@@ -1301,6 +1301,7 @@ class Preferences {
 
                $htmlForm->setModifiedUser( $user );
                $htmlForm->setId( 'mw-prefs-form' );
+               $htmlForm->setAutocomplete( 'off' );
                $htmlForm->setSubmitText( $context->msg( 'saveprefs' )->text() );
                # Used message keys: 'accesskey-preferences-save', 'tooltip-preferences-save'
                $htmlForm->setSubmitTooltip( 'preferences-save' );
index 3db3744..79cab79 100644 (file)
@@ -1035,19 +1035,6 @@ class Revision implements IDBAccessObject {
                }
        }
 
-       /**
-        * Fetch revision text without regard for view restrictions
-        *
-        * @return string
-        *
-        * @deprecated since 1.21. Instead, use Revision::getContent( Revision::RAW )
-        *                         or Revision::getSerializedData() as appropriate.
-        */
-       public function getRawText() {
-               ContentHandler::deprecated( __METHOD__, "1.21" );
-               return $this->getText( self::RAW );
-       }
-
        /**
         * Fetch original serialized data without regard for view restrictions
         *
@@ -1549,14 +1536,24 @@ class Revision implements IDBAccessObject {
        protected function loadText() {
                // Caching may be beneficial for massive use of external storage
                global $wgRevisionCacheExpiry;
+               static $processCache = null;
+
+               if ( !$processCache ) {
+                       $processCache = new MapCacheLRU( 10 );
+               }
 
                $cache = ObjectCache::getMainWANInstance();
                $textId = $this->getTextId();
                $key = wfMemcKey( 'revisiontext', 'textid', $textId );
+
                if ( $wgRevisionCacheExpiry ) {
+                       if ( $processCache->has( $key ) ) {
+                               return $processCache->get( $key );
+                       }
                        $text = $cache->get( $key );
                        if ( is_string( $text ) ) {
                                wfDebug( __METHOD__ . ": got id $textId from cache\n" );
+                               $processCache->set( $key, $text );
                                return $text;
                        }
                }
@@ -1601,6 +1598,7 @@ class Revision implements IDBAccessObject {
 
                # No negative caching -- negative hits on text rows may be due to corrupted slave servers
                if ( $wgRevisionCacheExpiry && $text !== false ) {
+                       $processCache->set( $key, $text );
                        $cache->set( $key, $text, $wgRevisionCacheExpiry );
                }
 
index d52bc07..d321e9f 100644 (file)
@@ -363,14 +363,14 @@ class Sanitizer {
         * @return array
         */
        public static function getRecognizedTagData( $extratags = [], $removetags = [] ) {
-               global $wgAllowMicrodataAttributes, $wgAllowImageTag;
+               global $wgAllowImageTag;
 
                static $htmlpairsStatic, $htmlsingle, $htmlsingleonly, $htmlnest, $tabletags,
                        $htmllist, $listtags, $htmlsingleallowed, $htmlelementsStatic, $staticInitialised;
 
                // Base our staticInitialised variable off of the global config state so that if the globals
                // are changed (like in the screwed up test system) we will re-initialise the settings.
-               $globalContext = implode( '-', compact( 'wgAllowMicrodataAttributes', 'wgAllowImageTag' ) );
+               $globalContext = $wgAllowImageTag;
                if ( !$staticInitialised || $staticInitialised != $globalContext ) {
                        $htmlpairsStatic = [ # Tags that must be closed
                                'b', 'bdi', 'del', 'i', 'ins', 'u', 'font', 'big', 'small', 'sub', 'sup', 'h1',
@@ -386,10 +386,10 @@ class Sanitizer {
                        $htmlsingleonly = [ # Elements that cannot have close tags
                                'br', 'wbr', 'hr'
                        ];
-                       if ( $wgAllowMicrodataAttributes ) {
-                               $htmlsingle[] = $htmlsingleonly[] = 'meta';
-                               $htmlsingle[] = $htmlsingleonly[] = 'link';
-                       }
+
+                       $htmlsingle[] = $htmlsingleonly[] = 'meta';
+                       $htmlsingle[] = $htmlsingleonly[] = 'link';
+
                        $htmlnest = [ # Tags that can be nested--??
                                'table', 'tr', 'td', 'th', 'div', 'blockquote', 'ol', 'ul',
                                'li', 'dl', 'dt', 'dd', 'font', 'big', 'small', 'sub', 'sup', 'span',
@@ -734,15 +734,13 @@ class Sanitizer {
         * @todo Check for unique id attribute :P
         */
        static function validateAttributes( $attribs, $whitelist ) {
-               global $wgAllowRdfaAttributes, $wgAllowMicrodataAttributes;
-
                $whitelist = array_flip( $whitelist );
                $hrefExp = '/^(' . wfUrlProtocols() . ')[^\s]+$/';
 
                $out = [];
                foreach ( $attribs as $attribute => $value ) {
-                       # allow XML namespace declaration if RDFa is enabled
-                       if ( $wgAllowRdfaAttributes && preg_match( self::XMLNS_ATTRIBUTE_PATTERN, $attribute ) ) {
+                       # Allow XML namespace declaration to allow RDFa
+                       if ( preg_match( self::XMLNS_ATTRIBUTE_PATTERN, $attribute ) ) {
                                if ( !preg_match( self::EVIL_URI_PATTERN, $value ) ) {
                                        $out[$attribute] = $value;
                                }
@@ -817,15 +815,14 @@ class Sanitizer {
                        $out[$attribute] = $value;
                }
 
-               if ( $wgAllowMicrodataAttributes ) {
-                       # itemtype, itemid, itemref don't make sense without itemscope
-                       if ( !array_key_exists( 'itemscope', $out ) ) {
-                               unset( $out['itemtype'] );
-                               unset( $out['itemid'] );
-                               unset( $out['itemref'] );
-                       }
-                       # TODO: Strip itemprop if we aren't descendants of an itemscope or pointed to by an itemref.
+               # itemtype, itemid, itemref don't make sense without itemscope
+               if ( !array_key_exists( 'itemscope', $out ) ) {
+                       unset( $out['itemtype'] );
+                       unset( $out['itemid'] );
+                       unset( $out['itemref'] );
                }
+               # TODO: Strip itemprop if we aren't descendants of an itemscope or pointed to by an itemref.
+
                return $out;
        }
 
@@ -1561,12 +1558,9 @@ class Sanitizer {
         * @return array
         */
        static function setupAttributeWhitelist() {
-               global $wgAllowRdfaAttributes, $wgAllowMicrodataAttributes;
-               static $whitelist, $staticInitialised;
+               static $whitelist;
 
-               $globalContext = implode( '-', compact( 'wgAllowRdfaAttributes', 'wgAllowMicrodataAttributes' ) );
-
-               if ( $whitelist !== null && $staticInitialised == $globalContext ) {
+               if ( $whitelist !== null ) {
                        return $whitelist;
                }
 
@@ -1586,23 +1580,24 @@ class Sanitizer {
                        'aria-labelledby',
                        'aria-owns',
                        'role',
-               ];
 
-               if ( $wgAllowRdfaAttributes ) {
-                       # RDFa attributes as specified in section 9 of
+                       # RDFa
+                       # These attributes are specified in section 9 of
                        # http://www.w3.org/TR/2008/REC-rdfa-syntax-20081014
-                       $common = array_merge( $common, [
-                               'about', 'property', 'resource', 'datatype', 'typeof',
-                       ] );
-               }
+                       'about',
+                       'property',
+                       'resource',
+                       'datatype',
+                       'typeof',
 
-               if ( $wgAllowMicrodataAttributes ) {
-                       # add HTML5 microdata tags as specified by
+                       # Microdata. These are specified by
                        # http://www.whatwg.org/html/microdata.html#the-microdata-model
-                       $common = array_merge( $common, [
-                               'itemid', 'itemprop', 'itemref', 'itemscope', 'itemtype'
-                       ] );
-               }
+                       'itemid',
+                       'itemprop',
+                       'itemref',
+                       'itemscope',
+                       'itemtype',
+               ];
 
                $block = array_merge( $common, [ 'align' ] );
                $tablealign = [ 'align', 'valign' ];
@@ -1773,8 +1768,6 @@ class Sanitizer {
                        'link' => [ 'itemprop', 'href' ],
                ];
 
-               $staticInitialised = $globalContext;
-
                return $whitelist;
        }
 
diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php
new file mode 100644 (file)
index 0000000..d8709b9
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Default wiring for MediaWiki services.
+ *
+ * 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 file is loaded by MediaWiki\MediaWikiServices::getInstance() during the
+ * bootstrapping of the dependency injection framework.
+ *
+ * This file returns an array that associates service name with instantiator functions
+ * that create the default instances for the services used by MediaWiki core.
+ * For every service that MediaWiki core requires, an instantiator must be defined in
+ * this file.
+ *
+ * @note As of version 1.27, MediaWiki is only beginning to use dependency injection.
+ * The services defined here do not yet fully represent all services used by core,
+ * much of the code still relies on global state for this accessing services.
+ *
+ * @since 1.27
+ *
+ * @see docs/injection.txt for an overview of using dependency injection in the
+ *      MediaWiki code base.
+ */
+
+use MediaWiki\MediaWikiServices;
+
+return [
+       'SiteStore' => function( MediaWikiServices $services ) {
+               $loadBalancer = wfGetLB(); // TODO: use LB from MediaWikiServices
+               $rawSiteStore = new DBSiteStore( $loadBalancer );
+
+               // TODO: replace wfGetCache with a CacheFactory service.
+               // TODO: replace wfIsHHVM with a capabilities service.
+               $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING );
+
+               return new CachingSiteStore( $rawSiteStore, $cache );
+       },
+
+       'SiteLookup' => function( MediaWikiServices $services ) {
+               // Use the default SiteStore as the SiteLookup implementation for now
+               return $services->getSiteStore();
+       },
+
+       'ConfigFactory' => function( MediaWikiServices $services ) {
+               // Use the bootstrap config to initialize the ConfigFactory.
+               $registry = $services->getBootstrapConfig()->get( 'ConfigRegistry' );
+               $factory = new ConfigFactory();
+
+               foreach ( $registry as $name => $callback ) {
+                       $factory->register( $name, $callback );
+               }
+               return $factory;
+       },
+
+       'MainConfig' => function( MediaWikiServices $services ) {
+               // Use the 'main' config from the ConfigFactory service.
+               return $services->getConfigFactory()->makeConfig( 'main' );
+       },
+
+       ///////////////////////////////////////////////////////////////////////////
+       // NOTE: When adding a service here, don't forget to add a getter function
+       // in the MediaWikiServices class. The convenience getter should just call
+       // $this->getService( 'FooBarService' ).
+       ///////////////////////////////////////////////////////////////////////////
+
+];
diff --git a/includes/Services/ServiceContainer.php b/includes/Services/ServiceContainer.php
new file mode 100644 (file)
index 0000000..e3cda2e
--- /dev/null
@@ -0,0 +1,222 @@
+<?php
+namespace MediaWiki\Services;
+
+use InvalidArgumentException;
+use RuntimeException;
+use Wikimedia\Assert\Assert;
+
+/**
+ * Generic service container.
+ *
+ * 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
+ *
+ * @since 1.27
+ */
+
+/**
+ * ServiceContainer provides a generic service to manage named services using
+ * lazy instantiation based on instantiator callback functions.
+ *
+ * Services managed by an instance of ServiceContainer may or may not implement
+ * a common interface.
+ *
+ * @note When using ServiceContainer to manage a set of services, consider
+ * creating a wrapper or a subclass that provides access to the services via
+ * getter methods with more meaningful names and more specific return type
+ * declarations.
+ *
+ * @see docs/injection.txt for an overview of using dependency injection in the
+ *      MediaWiki code base.
+ */
+class ServiceContainer {
+
+       /**
+        * @var object[]
+        */
+       private $services = [];
+
+       /**
+        * @var callable[]
+        */
+       private $serviceInstantiators = [];
+
+       /**
+        * @var array
+        */
+       private $extraInstantiationParams;
+
+       /**
+        * @param array $extraInstantiationParams Any additional parameters to be passed to the
+        * instantiator function when creating a service. This is typically used to provide
+        * access to additional ServiceContainers or Config objects.
+        */
+       public function __construct( array $extraInstantiationParams = [] ) {
+               $this->extraInstantiationParams = $extraInstantiationParams;
+       }
+
+       /**
+        * @param array $wiringFiles A list of PHP files to load wiring information from.
+        * Each file is loaded using PHP's include mechanism. Each file is expected to
+        * return an associative array that maps service names to instantiator functions.
+        */
+       public function loadWiringFiles( array $wiringFiles ) {
+               foreach ( $wiringFiles as $file ) {
+                       // the wiring file is required to return an array of instantiators.
+                       $wiring = require $file;
+
+                       Assert::postcondition(
+                               is_array( $wiring ),
+                               "Wiring file $file is expected to return an array!"
+                       );
+
+                       $this->applyWiring( $wiring );
+               }
+       }
+
+       /**
+        * Registers multiple services (aka a "wiring").
+        *
+        * @param array $serviceInstantiators An associative array mapping service names to
+        *        instantiator functions.
+        */
+       public function applyWiring( array $serviceInstantiators ) {
+               Assert::parameterElementType( 'callable', $serviceInstantiators, '$serviceInstantiators' );
+
+               foreach ( $serviceInstantiators as $name => $instantiator ) {
+                       $this->defineService( $name, $instantiator );
+               }
+       }
+
+       /**
+        * Returns true if a service is defined for $name, that is, if a call to getService( $name )
+        * would return a service instance.
+        *
+        * @param string $name
+        *
+        * @return bool
+        */
+       public function hasService( $name ) {
+               return isset( $this->serviceInstantiators[$name] );
+       }
+
+       /**
+        * @return string[]
+        */
+       public function getServiceNames() {
+               return array_keys( $this->serviceInstantiators );
+       }
+
+       /**
+        * Define a new service. The service must not be known already.
+        *
+        * @see getService().
+        * @see replaceService().
+        *
+        * @param string $name The name of the service to register, for use with getService().
+        * @param callable $instantiator Callback that returns a service instance.
+        *        Will be called with this MediaWikiServices instance as the only parameter.
+        *        Any extra instantiation parameters provided to the constructor will be
+        *        passed as subsequent parameters when invoking the instantiator.
+        *
+        * @throws RuntimeException if there is already a service registered as $name.
+        */
+       public function defineService( $name, callable $instantiator ) {
+               Assert::parameterType( 'string', $name, '$name' );
+
+               if ( $this->hasService( $name ) ) {
+                       throw new RuntimeException( 'Service already defined: ' . $name );
+               }
+
+               $this->serviceInstantiators[$name] = $instantiator;
+       }
+
+       /**
+        * Replace an already defined service.
+        *
+        * @see defineService().
+        *
+        * @note This causes any previously instantiated instance of the service to be discarded.
+        *
+        * @param string $name The name of the service to register.
+        * @param callable $instantiator Callback function that returns a service instance.
+        *        Will be called with this MediaWikiServices instance as the only parameter.
+        *        The instantiator must return a service compatible with the originally defined service.
+        *        Any extra instantiation parameters provided to the constructor will be
+        *        passed as subsequent parameters when invoking the instantiator.
+        *
+        * @throws RuntimeException if $name is not a known service.
+        */
+       public function redefineService( $name, callable $instantiator ) {
+               Assert::parameterType( 'string', $name, '$name' );
+
+               if ( !$this->hasService( $name ) ) {
+                       throw new RuntimeException( 'Service not defined: ' . $name );
+               }
+
+               if ( isset( $this->services[$name] ) ) {
+                       throw new RuntimeException( 'Cannot redefine a service that is already in use: ' . $name );
+               }
+
+               $this->serviceInstantiators[$name] = $instantiator;
+       }
+
+       /**
+        * Returns a service object of the kind associated with $name.
+        * Services instances are instantiated lazily, on demand.
+        * This method may or may not return the same service instance
+        * when called multiple times with the same $name.
+        *
+        * @note Rather than calling this method directly, it is recommended to provide
+        * getters with more meaningful names and more specific return types, using
+        * a subclass or wrapper.
+        *
+        * @see redefineService().
+        *
+        * @param string $name The service name
+        *
+        * @throws InvalidArgumentException if $name is not a known service.
+        * @return object The service instance
+        */
+       public function getService( $name ) {
+               if ( !isset( $this->services[$name] ) ) {
+                       $this->services[$name] = $this->createService( $name );
+               }
+
+               return $this->services[$name];
+       }
+
+       /**
+        * @param string $name
+        *
+        * @throws InvalidArgumentException if $name is not a known service.
+        * @return object
+        */
+       private function createService( $name ) {
+               if ( isset( $this->serviceInstantiators[$name] ) ) {
+                       $service = call_user_func_array(
+                               $this->serviceInstantiators[$name],
+                               array_merge( [ $this ], $this->extraInstantiationParams )
+                       );
+               } else {
+                       throw new InvalidArgumentException( 'Unknown service: ' . $name );
+               }
+
+               return $service;
+       }
+
+}
index f26d789..d7f1189 100644 (file)
@@ -119,20 +119,15 @@ if ( $wgRightsIcon ) {
        );
 }
 
-if ( isset( $wgFooterIcons['copyright'] )
-       && isset( $wgFooterIcons['copyright']['copyright'] )
+if ( isset( $wgFooterIcons['copyright']['copyright'] )
        && $wgFooterIcons['copyright']['copyright'] === []
 ) {
-       if ( $wgCopyrightIcon ) {
-               $wgFooterIcons['copyright']['copyright'] = $wgCopyrightIcon;
-       } elseif ( $wgRightsIcon || $wgRightsText ) {
+       if ( $wgRightsIcon || $wgRightsText ) {
                $wgFooterIcons['copyright']['copyright'] = [
                        'url' => $wgRightsUrl,
                        'src' => $wgRightsIcon,
                        'alt' => $wgRightsText,
                ];
-       } else {
-               unset( $wgFooterIcons['copyright']['copyright'] );
        }
 }
 
@@ -443,15 +438,6 @@ $wgHtml5 = true;
 $wgXhtmlDefaultNamespace = 'http://www.w3.org/1999/xhtml';
 $wgJsMimeType = 'text/javascript';
 
-if ( !$wgHtml5Version && $wgAllowRdfaAttributes ) {
-       // see http://www.w3.org/TR/rdfa-in-html/#document-conformance
-       if ( $wgMimeType == 'application/xhtml+xml' ) {
-               $wgHtml5Version = 'XHTML+RDFa 1.0';
-       } else {
-               $wgHtml5Version = 'HTML+RDFa 1.0';
-       }
-}
-
 // Blacklisted file extensions shouldn't appear on the "allowed" list
 $wgFileExtensions = array_values( array_diff( $wgFileExtensions, $wgFileBlacklist ) );
 
@@ -610,7 +596,7 @@ if ( !$wgPasswordSender ) {
        $wgPasswordSender = 'apache@' . $wgServerName;
 }
 if ( !$wgNoReplyAddress ) {
-       $wgNoReplyAddress = $wgNoReplyAddress;
+       $wgNoReplyAddress = $wgPasswordSender;
 }
 
 if ( $wgSecureLogin && substr( $wgServer, 0, 2 ) !== '//' ) {
@@ -729,7 +715,7 @@ if ( !is_object( $wgAuth ) ) {
 // Set up the session
 $ps_session = Profiler::instance()->scopedProfileIn( $fname . '-session' );
 /**
- * @var MediaWiki\\Session\\SessionId|null $wgInitialSessionId The persistent
+ * @var MediaWiki\Session\SessionId|null $wgInitialSessionId The persistent
  * session ID (if any) loaded at startup
  */
 $wgInitialSessionId = null;
index 580f7cc..acd5262 100644 (file)
@@ -36,9 +36,6 @@ class SiteStats {
        /** @var int[] */
        private static $pageCount = [];
 
-       /** @var int[] */
-       private static $groupMemberCounts = [];
-
        static function recache() {
                self::load( true );
        }
@@ -289,8 +286,10 @@ class SiteStatsInit {
        public function __construct( $database = false ) {
                if ( $database instanceof IDatabase ) {
                        $this->db = $database;
+               } elseif ( $database ) {
+                       $this->db = wfGetDB( DB_MASTER );
                } else {
-                       $this->db = wfGetDB( $database ? DB_MASTER : DB_SLAVE );
+                       $this->db = wfGetDB( DB_SLAVE, 'vslow' );
                }
        }
 
index 211afda..0b4d048 100644 (file)
@@ -149,7 +149,6 @@ class StubObject {
                }
 
                if ( get_class( $GLOBALS[$this->global] ) != $this->class ) {
-                       $fname = __METHOD__ . '-' . $this->global;
                        $caller = wfGetCaller( $level );
                        if ( ++$recursionLevel > 2 ) {
                                throw new MWException( "Unstub loop detected on call of "
index 6420dc7..20142a7 100644 (file)
@@ -38,7 +38,7 @@ class TemplateParser {
 
        /**
         * @param string $templateDir
-        * @param boolean $forceRecompile
+        * @param bool $forceRecompile
         */
        public function __construct( $templateDir = null, $forceRecompile = false ) {
                $this->templateDir = $templateDir ?: __DIR__ . '/templates';
index 0ac3e46..f4a6894 100644 (file)
@@ -145,7 +145,7 @@ class Title implements LinkTarget {
        /** @var bool The (string) language code of the page's language and content code. */
        private $mPageLanguage = false;
 
-       /** @var string|boolean|null The page language code from the database, null if not saved in
+       /** @var string|bool|null The page language code from the database, null if not saved in
         * the database or false if not loaded, yet. */
        private $mDbPageLanguage = false;
 
@@ -572,57 +572,6 @@ class Title implements LinkTarget {
                return $title;
        }
 
-       /**
-        * Extract a redirect destination from a string and return the
-        * Title, or null if the text doesn't contain a valid redirect
-        * This will only return the very next target, useful for
-        * the redirect table and other checks that don't need full recursion
-        *
-        * @param string $text Text with possible redirect
-        * @return Title The corresponding Title
-        * @deprecated since 1.21, use Content::getRedirectTarget instead.
-        */
-       public static function newFromRedirect( $text ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-
-               $content = ContentHandler::makeContent( $text, null, CONTENT_MODEL_WIKITEXT );
-               return $content->getRedirectTarget();
-       }
-
-       /**
-        * Extract a redirect destination from a string and return the
-        * Title, or null if the text doesn't contain a valid redirect
-        * This will recurse down $wgMaxRedirects times or until a non-redirect target is hit
-        * in order to provide (hopefully) the Title of the final destination instead of another redirect
-        *
-        * @param string $text Text with possible redirect
-        * @return Title
-        * @deprecated since 1.21, use Content::getUltimateRedirectTarget instead.
-        */
-       public static function newFromRedirectRecurse( $text ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-
-               $content = ContentHandler::makeContent( $text, null, CONTENT_MODEL_WIKITEXT );
-               return $content->getUltimateRedirectTarget();
-       }
-
-       /**
-        * Extract a redirect destination from a string and return an
-        * array of Titles, or null if the text doesn't contain a valid redirect
-        * The last element in the array is the final destination after all redirects
-        * have been resolved (up to $wgMaxRedirects times)
-        *
-        * @param string $text Text with possible redirect
-        * @return Title[] Array of Titles, with the destination last
-        * @deprecated since 1.21, use Content::getRedirectChain instead.
-        */
-       public static function newFromRedirectArray( $text ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-
-               $content = ContentHandler::makeContent( $text, null, CONTENT_MODEL_WIKITEXT );
-               return $content->getRedirectChain();
-       }
-
        /**
         * Get the prefixed DB key associated with an ID
         *
@@ -2452,8 +2401,8 @@ class Title implements LinkTarget {
 
        /**
         * Can $user perform $action on this page? This is an internal function,
-        * which checks ONLY that previously checked by userCan (i.e. it leaves out
-        * checks on wfReadOnly() and blocks)
+        * with multiple levels of checks depending on performance needs; see $rigor below.
+        * It does not check wfReadOnly().
         *
         * @param string $action Action that permission needs to be checked for
         * @param User $user User to check
@@ -3570,9 +3519,9 @@ class Title implements LinkTarget {
 
                // If we are looking at a css/js user subpage, purge the action=raw.
                if ( $this->isJsSubpage() ) {
-                       $urls[] = $this->getInternalUrl( 'action=raw&ctype=text/javascript' );
+                       $urls[] = $this->getInternalURL( 'action=raw&ctype=text/javascript' );
                } elseif ( $this->isCssSubpage() ) {
-                       $urls[] = $this->getInternalUrl( 'action=raw&ctype=text/css' );
+                       $urls[] = $this->getInternalURL( 'action=raw&ctype=text/css' );
                }
 
                Hooks::run( 'TitleSquidURLs', [ $this, &$urls ] );
@@ -4627,7 +4576,7 @@ class Title implements LinkTarget {
         * to true in LocalSettings.php, otherwise returns false. If there is no language saved in
         * the db, it will return NULL.
         *
-        * @return string|null|boolean
+        * @return string|null|bool
         */
        private function getDbPageLanguageCode() {
                global $wgPageLanguageUseDB;
index f2633d9..0495536 100644 (file)
@@ -18,7 +18,6 @@
  * @file
  * @ingroup Watchlist
  */
-use Wikimedia\Assert\Assert;
 
 /**
  * Representation of a pair of user and title for watchlist entries.
@@ -180,23 +179,31 @@ class WatchedItem {
         */
        public static function batchAddWatch( array $items ) {
                // wfDeprecated( __METHOD__, '1.27' );
-               $userTargetCombinations = [];
+               if ( !$items ) {
+                       return false;
+               }
+
+               $targets = [];
+               $users = [];
                /** @var WatchedItem $watchedItem */
                foreach ( $items as $watchedItem ) {
-                       if ( $watchedItem->checkRights && !$watchedItem->getUser()->isAllowed( 'editmywatchlist' ) ) {
+                       $user = $watchedItem->getUser();
+                       if ( $watchedItem->checkRights && !$user->isAllowed( 'editmywatchlist' ) ) {
                                continue;
                        }
-                       $userTargetCombinations[] = [
-                               $watchedItem->getUser(),
-                               $watchedItem->getTitle()->getSubjectPage()
-                       ];
-                       $userTargetCombinations[] = [
-                               $watchedItem->getUser(),
-                               $watchedItem->getTitle()->getTalkPage()
-                       ];
+                       $userId = $user->getId();
+                       $users[$userId] = $user;
+                       $targets[$userId][] = $watchedItem->getTitle()->getSubjectPage();
+                       $targets[$userId][] = $watchedItem->getTitle()->getTalkPage();
                }
+
                $store = WatchedItemStore::getDefaultInstance();
-               return $store->addWatchBatch( $userTargetCombinations );
+               $success = true;
+               foreach ( $users as $userId => $user ) {
+                       $success &= $store->addWatchBatchForUser( $user, $targets[$userId] );
+               }
+
+               return $success;
        }
 
        /**
index 1aed8e0..8ae7932 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
 use Wikimedia\Assert\Assert;
 
 /**
@@ -10,7 +11,10 @@ use Wikimedia\Assert\Assert;
  *
  * @since 1.27
  */
-class WatchedItemStore {
+class WatchedItemStore implements StatsdAwareInterface {
+
+       const SORT_DESC = 'DESC';
+       const SORT_ASC = 'ASC';
 
        /**
         * @var LoadBalancer
@@ -18,10 +22,18 @@ class WatchedItemStore {
        private $loadBalancer;
 
        /**
-        * @var BagOStuff
+        * @var HashBagOStuff
         */
        private $cache;
 
+       /**
+        * @var array[] Looks like $cacheIndex[Namespace ID][Target DB Key][User Id] => 'key'
+        * The index is needed so that on mass changes all relevant items can be un-cached.
+        * For example: Clearing a users watchlist of all items or updating notification timestamps
+        *              for all users watching a single target.
+        */
+       private $cacheIndex = [];
+
        /**
         * @var callable|null
         */
@@ -32,25 +44,44 @@ class WatchedItemStore {
         */
        private $revisionGetTimestampFromIdCallback;
 
+       /**
+        * @var StatsdDataFactoryInterface
+        */
+       private $stats;
+
        /**
         * @var self|null
         */
        private static $instance;
 
-       public function __construct( LoadBalancer $loadBalancer, BagOStuff $cache ) {
+       /**
+        * @param LoadBalancer $loadBalancer
+        * @param HashBagOStuff $cache
+        */
+       public function __construct(
+               LoadBalancer $loadBalancer,
+               HashBagOStuff $cache
+       ) {
                $this->loadBalancer = $loadBalancer;
                $this->cache = $cache;
+               $this->stats = new NullStatsdDataFactory();
                $this->deferredUpdatesAddCallableUpdateCallback = [ 'DeferredUpdates', 'addCallableUpdate' ];
                $this->revisionGetTimestampFromIdCallback = [ 'Revision', 'getTimestampFromId' ];
        }
 
+       public function setStatsdDataFactory( StatsdDataFactoryInterface $stats ) {
+               $this->stats = $stats;
+       }
+
        /**
         * Overrides the DeferredUpdates::addCallableUpdate callback
         * This is intended for use while testing and will fail if MW_PHPUNIT_TEST is not defined.
         *
         * @param callable $callback
+        *
         * @see DeferredUpdates::addCallableUpdate for callback signiture
         *
+        * @return ScopedCallback to reset the overridden value
         * @throws MWException
         */
        public function overrideDeferredUpdatesAddCallableUpdateCallback( $callback ) {
@@ -60,7 +91,12 @@ class WatchedItemStore {
                        );
                }
                Assert::parameterType( 'callable', $callback, '$callback' );
+
+               $previousValue = $this->deferredUpdatesAddCallableUpdateCallback;
                $this->deferredUpdatesAddCallableUpdateCallback = $callback;
+               return new ScopedCallback( function() use ( $previousValue ) {
+                       $this->deferredUpdatesAddCallableUpdateCallback = $previousValue;
+               } );
        }
 
        /**
@@ -70,6 +106,7 @@ class WatchedItemStore {
         * @param callable $callback
         * @see Revision::getTimestampFromId for callback signiture
         *
+        * @return ScopedCallback to reset the overridden value
         * @throws MWException
         */
        public function overrideRevisionGetTimestampFromIdCallback( $callback ) {
@@ -79,24 +116,38 @@ class WatchedItemStore {
                        );
                }
                Assert::parameterType( 'callable', $callback, '$callback' );
+
+               $previousValue = $this->revisionGetTimestampFromIdCallback;
                $this->revisionGetTimestampFromIdCallback = $callback;
+               return new ScopedCallback( function() use ( $previousValue ) {
+                       $this->revisionGetTimestampFromIdCallback = $previousValue;
+               } );
        }
 
        /**
         * Overrides the default instance of this class
         * This is intended for use while testing and will fail if MW_PHPUNIT_TEST is not defined.
         *
-        * @param WatchedItemStore $store
+        * If this method is used it MUST also be called with null after a test to ensure a new
+        * default instance is created next time getDefaultInstance is called.
+        *
+        * @param WatchedItemStore|null $store
         *
+        * @return ScopedCallback to reset the overridden value
         * @throws MWException
         */
-       public static function overrideDefaultInstance( WatchedItemStore $store ) {
+       public static function overrideDefaultInstance( WatchedItemStore $store = null ) {
                if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
                        throw new MWException(
                                'Cannot override ' . __CLASS__ . 'default instance in operation.'
                        );
                }
+
+               $previousValue = self::$instance;
                self::$instance = $store;
+               return new ScopedCallback( function() use ( $previousValue ) {
+                       self::$instance = $previousValue;
+               } );
        }
 
        /**
@@ -108,6 +159,7 @@ class WatchedItemStore {
                                wfGetLB(),
                                new HashBagOStuff( [ 'maxKeys' => 100 ] )
                        );
+                       self::$instance->setStatsdDataFactory( RequestContext::getMain()->getStats() );
                }
                return self::$instance;
        }
@@ -121,14 +173,29 @@ class WatchedItemStore {
        }
 
        private function cache( WatchedItem $item ) {
-               $this->cache->set(
-                       $this->getCacheKey( $item->getUser(), $item->getLinkTarget() ),
-                       $item
-               );
+               $user = $item->getUser();
+               $target = $item->getLinkTarget();
+               $key = $this->getCacheKey( $user, $target );
+               $this->cache->set( $key, $item );
+               $this->cacheIndex[$target->getNamespace()][$target->getDBkey()][$user->getId()] = $key;
+               $this->stats->increment( 'WatchedItemStore.cache' );
        }
 
        private function uncache( User $user, LinkTarget $target ) {
                $this->cache->delete( $this->getCacheKey( $user, $target ) );
+               unset( $this->cacheIndex[$target->getNamespace()][$target->getDBkey()][$user->getId()] );
+               $this->stats->increment( 'WatchedItemStore.uncache' );
+       }
+
+       private function uncacheLinkTarget( LinkTarget $target ) {
+               if ( !isset( $this->cacheIndex[$target->getNamespace()][$target->getDBkey()] ) ) {
+                       return;
+               }
+               $this->stats->increment( 'WatchedItemStore.uncacheLinkTarget' );
+               foreach ( $this->cacheIndex[$target->getNamespace()][$target->getDBkey()] as $key ) {
+                       $this->stats->increment( 'WatchedItemStore.uncacheLinkTarget.items' );
+                       $this->cache->delete( $key );
+               }
        }
 
        /**
@@ -158,6 +225,233 @@ class WatchedItemStore {
                ];
        }
 
+       /**
+        * @param int $slaveOrMaster DB_MASTER or DB_SLAVE
+        *
+        * @return DatabaseBase
+        * @throws MWException
+        */
+       private function getConnection( $slaveOrMaster ) {
+               return $this->loadBalancer->getConnection( $slaveOrMaster, [ 'watchlist' ] );
+       }
+
+       /**
+        * @param DatabaseBase $connection
+        *
+        * @throws MWException
+        */
+       private function reuseConnection( $connection ) {
+               $this->loadBalancer->reuseConnection( $connection );
+       }
+
+       /**
+        * Count the number of individual items that are watched by the user.
+        * If a subject and corresponding talk page are watched this will return 2.
+        *
+        * @param User $user
+        *
+        * @return int
+        */
+       public function countWatchedItems( User $user ) {
+               $dbr = $this->getConnection( DB_SLAVE );
+               $return = (int)$dbr->selectField(
+                       'watchlist',
+                       'COUNT(*)',
+                       [
+                               'wl_user' => $user->getId()
+                       ],
+                       __METHOD__
+               );
+               $this->reuseConnection( $dbr );
+
+               return $return;
+       }
+
+       /**
+        * @param LinkTarget $target
+        *
+        * @return int
+        */
+       public function countWatchers( LinkTarget $target ) {
+               $dbr = $this->getConnection( DB_SLAVE );
+               $return = (int)$dbr->selectField(
+                       'watchlist',
+                       'COUNT(*)',
+                       [
+                               'wl_namespace' => $target->getNamespace(),
+                               'wl_title' => $target->getDBkey(),
+                       ],
+                       __METHOD__
+               );
+               $this->reuseConnection( $dbr );
+
+               return $return;
+       }
+
+       /**
+        * Number of page watchers who also visited a "recent" edit
+        *
+        * @param LinkTarget $target
+        * @param mixed $threshold timestamp accepted by wfTimestamp
+        *
+        * @return int
+        * @throws DBUnexpectedError
+        * @throws MWException
+        */
+       public function countVisitingWatchers( LinkTarget $target, $threshold ) {
+               $dbr = $this->getConnection( DB_SLAVE );
+               $visitingWatchers = (int)$dbr->selectField(
+                       'watchlist',
+                       'COUNT(*)',
+                       [
+                               'wl_namespace' => $target->getNamespace(),
+                               'wl_title' => $target->getDBkey(),
+                               'wl_notificationtimestamp >= ' .
+                               $dbr->addQuotes( $dbr->timestamp( $threshold ) ) .
+                               ' OR wl_notificationtimestamp IS NULL'
+                       ],
+                       __METHOD__
+               );
+               $this->reuseConnection( $dbr );
+
+               return $visitingWatchers;
+       }
+
+       /**
+        * @param LinkTarget[] $targets
+        * @param array $options Allowed keys:
+        *        'minimumWatchers' => int
+        *
+        * @return array multi dimensional like $return[$namespaceId][$titleString] = int $watchers
+        *         All targets will be present in the result. 0 either means no watchers or the number
+        *         of watchers was below the minimumWatchers option if passed.
+        */
+       public function countWatchersMultiple( array $targets, array $options = [] ) {
+               $dbOptions = [ 'GROUP BY' => [ 'wl_namespace', 'wl_title' ] ];
+
+               $dbr = $this->getConnection( DB_SLAVE );
+
+               if ( array_key_exists( 'minimumWatchers', $options ) ) {
+                       $dbOptions['HAVING'] = 'COUNT(*) >= ' . (int)$options['minimumWatchers'];
+               }
+
+               $lb = new LinkBatch( $targets );
+               $res = $dbr->select(
+                       'watchlist',
+                       [ 'wl_title', 'wl_namespace', 'watchers' => 'COUNT(*)' ],
+                       [ $lb->constructSet( 'wl', $dbr ) ],
+                       __METHOD__,
+                       $dbOptions
+               );
+
+               $this->reuseConnection( $dbr );
+
+               $watchCounts = [];
+               foreach ( $targets as $linkTarget ) {
+                       $watchCounts[$linkTarget->getNamespace()][$linkTarget->getDBkey()] = 0;
+               }
+
+               foreach ( $res as $row ) {
+                       $watchCounts[$row->wl_namespace][$row->wl_title] = (int)$row->watchers;
+               }
+
+               return $watchCounts;
+       }
+
+       /**
+        * Number of watchers of each page who have visited recent edits to that page
+        *
+        * @param array $targetsWithVisitThresholds array of pairs (LinkTarget $target, mixed $threshold),
+        *        $threshold is:
+        *        - a timestamp of the recent edit if $target exists (format accepted by wfTimestamp)
+        *        - null if $target doesn't exist
+        * @param int|null $minimumWatchers
+        * @return array multi-dimensional like $return[$namespaceId][$titleString] = $watchers,
+        *         where $watchers is an int:
+        *         - if the page exists, number of users watching who have visited the page recently
+        *         - if the page doesn't exist, number of users that have the page on their watchlist
+        *         - 0 means there are no visiting watchers or their number is below the minimumWatchers
+        *         option (if passed).
+        */
+       public function countVisitingWatchersMultiple(
+               array $targetsWithVisitThresholds,
+               $minimumWatchers = null
+       ) {
+               $dbr = $this->getConnection( DB_SLAVE );
+
+               $conds = $this->getVisitingWatchersCondition( $dbr, $targetsWithVisitThresholds );
+
+               $dbOptions = [ 'GROUP BY' => [ 'wl_namespace', 'wl_title' ] ];
+               if ( $minimumWatchers !== null ) {
+                       $dbOptions['HAVING'] = 'COUNT(*) >= ' . (int)$minimumWatchers;
+               }
+               $res = $dbr->select(
+                       'watchlist',
+                       [ 'wl_namespace', 'wl_title', 'watchers' => 'COUNT(*)' ],
+                       $conds,
+                       __METHOD__,
+                       $dbOptions
+               );
+
+               $this->reuseConnection( $dbr );
+
+               $watcherCounts = [];
+               foreach ( $targetsWithVisitThresholds as list( $target ) ) {
+                       /* @var LinkTarget $target */
+                       $watcherCounts[$target->getNamespace()][$target->getDBkey()] = 0;
+               }
+
+               foreach ( $res as $row ) {
+                       $watcherCounts[$row->wl_namespace][$row->wl_title] = (int)$row->watchers;
+               }
+
+               return $watcherCounts;
+       }
+
+       /**
+        * Generates condition for the query used in a batch count visiting watchers.
+        *
+        * @param IDatabase $db
+        * @param array $targetsWithVisitThresholds array of pairs (LinkTarget, last visit threshold)
+        * @return string
+        */
+       private function getVisitingWatchersCondition(
+               IDatabase $db,
+               array $targetsWithVisitThresholds
+       ) {
+               $missingTargets = [];
+               $namespaceConds = [];
+               foreach ( $targetsWithVisitThresholds as list( $target, $threshold ) ) {
+                       if ( $threshold === null ) {
+                               $missingTargets[] = $target;
+                               continue;
+                       }
+                       /* @var LinkTarget $target */
+                       $namespaceConds[$target->getNamespace()][] = $db->makeList( [
+                               'wl_title = ' . $db->addQuotes( $target->getDBkey() ),
+                               $db->makeList( [
+                                       'wl_notificationtimestamp >= ' . $db->addQuotes( $db->timestamp( $threshold ) ),
+                                       'wl_notificationtimestamp IS NULL'
+                               ], LIST_OR )
+                       ], LIST_AND );
+               }
+
+               $conds = [];
+               foreach ( $namespaceConds as $namespace => $pageConds ) {
+                       $conds[] = $db->makeList( [
+                               'wl_namespace = ' . $namespace,
+                               '(' . $db->makeList( $pageConds, LIST_OR ) . ')'
+                       ], LIST_AND );
+               }
+
+               if ( $missingTargets ) {
+                       $lb = new LinkBatch( $missingTargets );
+                       $conds[] = $lb->constructSet( 'wl', $db );
+               }
+
+               return $db->makeList( $conds, LIST_OR );
+       }
+
        /**
         * Get an item (may be cached)
         *
@@ -167,10 +461,16 @@ class WatchedItemStore {
         * @return WatchedItem|false
         */
        public function getWatchedItem( User $user, LinkTarget $target ) {
+               if ( $user->isAnon() ) {
+                       return false;
+               }
+
                $cached = $this->getCached( $user, $target );
                if ( $cached ) {
+                       $this->stats->increment( 'WatchedItemStore.getWatchedItem.cached' );
                        return $cached;
                }
+               $this->stats->increment( 'WatchedItemStore.getWatchedItem.load' );
                return $this->loadWatchedItem( $user, $target );
        }
 
@@ -188,14 +488,14 @@ class WatchedItemStore {
                        return false;
                }
 
-               $dbr = $this->loadBalancer->getConnection( DB_SLAVE, [ 'watchlist' ] );
+               $dbr = $this->getConnection( DB_SLAVE );
                $row = $dbr->selectRow(
                        'watchlist',
                        'wl_notificationtimestamp',
                        $this->dbCond( $user, $target ),
                        __METHOD__
                );
-               $this->loadBalancer->reuseConnection( $dbr );
+               $this->reuseConnection( $dbr );
 
                if ( !$row ) {
                        return false;
@@ -211,6 +511,54 @@ class WatchedItemStore {
                return $item;
        }
 
+       /**
+        * @param User $user
+        * @param array $options Allowed keys:
+        *        'forWrite' => bool defaults to false
+        *        'sort' => string optional sorting by namespace ID and title
+        *                     one of the self::SORT_* constants
+        *
+        * @return WatchedItem[]
+        */
+       public function getWatchedItemsForUser( User $user, array $options = [] ) {
+               $options += [ 'forWrite' => false ];
+
+               $dbOptions = [];
+               if ( array_key_exists( 'sort', $options ) ) {
+                       Assert::parameter(
+                               ( in_array( $options['sort'], [ self::SORT_ASC, self::SORT_DESC ] ) ),
+                               '$options[\'sort\']',
+                               'must be SORT_ASC or SORT_DESC'
+                       );
+                       $dbOptions['ORDER BY'] = [
+                               "wl_namespace {$options['sort']}",
+                               "wl_title {$options['sort']}"
+                       ];
+               }
+               $db = $this->getConnection( $options['forWrite'] ? DB_MASTER : DB_SLAVE );
+
+               $res = $db->select(
+                       'watchlist',
+                       [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
+                       [ 'wl_user' => $user->getId() ],
+                       __METHOD__,
+                       $dbOptions
+               );
+               $this->reuseConnection( $db );
+
+               $watchedItems = [];
+               foreach ( $res as $row ) {
+                       // todo these could all be cached at some point?
+                       $watchedItems[] = new WatchedItem(
+                               $user,
+                               new TitleValue( (int)$row->wl_namespace, $row->wl_title ),
+                               $row->wl_notificationtimestamp
+                       );
+               }
+
+               return $watchedItems;
+       }
+
        /**
         * Must be called separately for Subject & Talk namespaces
         *
@@ -223,6 +571,61 @@ class WatchedItemStore {
                return (bool)$this->getWatchedItem( $user, $target );
        }
 
+       /**
+        * @param User $user
+        * @param LinkTarget[] $targets
+        *
+        * @return array multi-dimensional like $return[$namespaceId][$titleString] = $timestamp,
+        *         where $timestamp is:
+        *         - string|null value of wl_notificationtimestamp,
+        *         - false if $target is not watched by $user.
+        */
+       public function getNotificationTimestampsBatch( User $user, array $targets ) {
+               $timestamps = [];
+               foreach ( $targets as $target ) {
+                       $timestamps[$target->getNamespace()][$target->getDBkey()] = false;
+               }
+
+               if ( $user->isAnon() ) {
+                       return $timestamps;
+               }
+
+               $targetsToLoad = [];
+               foreach ( $targets as $target ) {
+                       $cachedItem = $this->getCached( $user, $target );
+                       if ( $cachedItem ) {
+                               $timestamps[$target->getNamespace()][$target->getDBkey()] =
+                                       $cachedItem->getNotificationTimestamp();
+                       } else {
+                               $targetsToLoad[] = $target;
+                       }
+               }
+
+               if ( !$targetsToLoad ) {
+                       return $timestamps;
+               }
+
+               $dbr = $this->getConnection( DB_SLAVE );
+
+               $lb = new LinkBatch( $targetsToLoad );
+               $res = $dbr->select(
+                       'watchlist',
+                       [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
+                       [
+                               $lb->constructSet( 'wl', $dbr ),
+                               'wl_user' => $user->getId(),
+                       ],
+                       __METHOD__
+               );
+               $this->reuseConnection( $dbr );
+
+               foreach ( $res as $row ) {
+                       $timestamps[(int)$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp;
+               }
+
+               return $timestamps;
+       }
+
        /**
         * Must be called separately for Subject & Talk namespaces
         *
@@ -230,30 +633,30 @@ class WatchedItemStore {
         * @param LinkTarget $target
         */
        public function addWatch( User $user, LinkTarget $target ) {
-               $this->addWatchBatch( [ [ $user, $target ] ] );
+               $this->addWatchBatchForUser( $user, [ $target ] );
        }
 
        /**
-        * @param array[] $userTargetCombinations array of arrays containing [0] => User [1] => LinkTarget
+        * @param User $user
+        * @param LinkTarget[] $targets
         *
         * @return bool success
         */
-       public function addWatchBatch( array $userTargetCombinations ) {
+       public function addWatchBatchForUser( User $user, array $targets ) {
                if ( $this->loadBalancer->getReadOnlyReason() !== false ) {
                        return false;
                }
+               // Only loggedin user can have a watchlist
+               if ( $user->isAnon() ) {
+                       return false;
+               }
+
+               if ( !$targets ) {
+                       return true;
+               }
 
                $rows = [];
-               foreach ( $userTargetCombinations as list( $user, $target ) ) {
-                       /**
-                        * @var User $user
-                        * @var LinkTarget $target
-                        */
-
-                       // Only loggedin user can have a watchlist
-                       if ( $user->isAnon() ) {
-                               continue;
-                       }
+               foreach ( $targets as $target ) {
                        $rows[] = [
                                'wl_user' => $user->getId(),
                                'wl_namespace' => $target->getNamespace(),
@@ -263,17 +666,13 @@ class WatchedItemStore {
                        $this->uncache( $user, $target );
                }
 
-               if ( !$rows ) {
-                       return false;
-               }
-
-               $dbw = $this->loadBalancer->getConnection( DB_MASTER, [ 'watchlist' ] );
+               $dbw = $this->getConnection( DB_MASTER );
                foreach ( array_chunk( $rows, 100 ) as $toInsert ) {
                        // Use INSERT IGNORE to avoid overwriting the notification timestamp
                        // if there's already an entry for this page
                        $dbw->insert( 'watchlist', $toInsert, __METHOD__, 'IGNORE' );
                }
-               $this->loadBalancer->reuseConnection( $dbw );
+               $this->reuseConnection( $dbw );
 
                return true;
        }
@@ -297,7 +696,7 @@ class WatchedItemStore {
 
                $this->uncache( $user, $target );
 
-               $dbw = $this->loadBalancer->getConnection( DB_MASTER, [ 'watchlist' ] );
+               $dbw = $this->getConnection( DB_MASTER );
                $dbw->delete( 'watchlist',
                        [
                                'wl_user' => $user->getId(),
@@ -306,7 +705,7 @@ class WatchedItemStore {
                        ], __METHOD__
                );
                $success = (bool)$dbw->affectedRows();
-               $this->loadBalancer->reuseConnection( $dbw );
+               $this->reuseConnection( $dbw );
 
                return $success;
        }
@@ -320,7 +719,7 @@ class WatchedItemStore {
         * @return int[] Array of user IDs the timestamp has been updated for
         */
        public function updateNotificationTimestamp( User $editor, LinkTarget $target, $timestamp ) {
-               $dbw = $this->loadBalancer->getConnection( DB_MASTER, [ 'watchlist' ] );
+               $dbw = $this->getConnection( DB_MASTER );
                $res = $dbw->select( [ 'watchlist' ],
                        [ 'wl_user' ],
                        [
@@ -350,11 +749,12 @@ class WatchedItemStore {
                                                        'wl_title' => $target->getDBkey(),
                                                ], $fname
                                        );
+                                       $this->uncacheLinkTarget( $target );
                                }
                        );
                }
 
-               $this->loadBalancer->reuseConnection( $dbw );
+               $this->reuseConnection( $dbw );
 
                return $watchers;
        }
@@ -457,6 +857,44 @@ class WatchedItemStore {
                return $notificationTimestamp;
        }
 
+       /**
+        * @param User $user
+        * @param int $unreadLimit
+        *
+        * @return int|bool The number of unread notifications
+        *                  true if greater than or equal to $unreadLimit
+        */
+       public function countUnreadNotifications( User $user, $unreadLimit = null ) {
+               $queryOptions = [];
+               if ( $unreadLimit !== null ) {
+                       $unreadLimit = (int)$unreadLimit;
+                       $queryOptions['LIMIT'] = $unreadLimit;
+               }
+
+               $dbr = $this->getConnection( DB_SLAVE );
+               $rowCount = $dbr->selectRowCount(
+                       'watchlist',
+                       '1',
+                       [
+                               'wl_user' => $user->getId(),
+                               'wl_notificationtimestamp IS NOT NULL',
+                       ],
+                       __METHOD__,
+                       $queryOptions
+               );
+               $this->reuseConnection( $dbr );
+
+               if ( !isset( $unreadLimit ) ) {
+                       return $rowCount;
+               }
+
+               if ( $rowCount >= $unreadLimit ) {
+                       return true;
+               }
+
+               return $rowCount;
+       }
+
        /**
         * Check if the given title already is watched by the user, and if so
         * add a watch for the new title.
@@ -489,7 +927,7 @@ class WatchedItemStore {
         * @param LinkTarget $newTarget
         */
        public function duplicateEntry( LinkTarget $oldTarget, LinkTarget $newTarget ) {
-               $dbw = $this->loadBalancer->getConnection( DB_MASTER, [ 'watchlist' ] );
+               $dbw = $this->getConnection( DB_MASTER );
 
                $result = $dbw->select(
                        'watchlist',
@@ -528,7 +966,7 @@ class WatchedItemStore {
                        );
                }
 
-               $this->loadBalancer->reuseConnection( $dbw );
+               $this->reuseConnection( $dbw );
        }
 
 }
index 812a320..b18d59c 100644 (file)
@@ -23,6 +23,8 @@
  * @file
  */
 
+use MediaWiki\Session\Session;
+use MediaWiki\Session\SessionId;
 use MediaWiki\Session\SessionManager;
 
 /**
@@ -66,7 +68,7 @@ class WebRequest {
        protected $protocol;
 
        /**
-        * @var \\MediaWiki\\Session\\SessionId|null Session ID to use for this
+        * @var SessionId|null Session ID to use for this
         *  request. We can't save the session directly due to reference cycles not
         *  working too well (slow GC in Zend and never collected in HHVM).
         */
@@ -246,6 +248,25 @@ class WebRequest {
                return microtime( true ) - $this->requestTime;
        }
 
+       /**
+        * Get the unique request ID.
+        * This is either the value of the UNIQUE_ID envvar (if present) or a
+        * randomly-generated 24-character string.
+        *
+        * @return string
+        * @since 1.27
+        */
+       public static function getRequestId() {
+               static $reqId;
+
+               if ( !$reqId ) {
+                       $reqId = isset( $_SERVER['UNIQUE_ID'] )
+                               ? $_SERVER['UNIQUE_ID'] : wfRandomString( 24 );
+               }
+
+               return $reqId;
+       }
+
        /**
         * Get the current URL protocol (http or https)
         * @return string
@@ -651,7 +672,7 @@ class WebRequest {
         * @since 1.27
         * @note For performance, keep the session locally if you will be making
         *  much use of it instead of calling this method repeatedly.
-        * @return MediaWiki\\Session\\Session
+        * @return Session
         */
        public function getSession() {
                if ( $this->sessionId !== null ) {
@@ -669,18 +690,18 @@ class WebRequest {
        /**
         * Set the session for this request
         * @since 1.27
-        * @private For use by MediaWiki\\Session classes only
-        * @param MediaWiki\\Session\\SessionId $sessionId
+        * @private For use by MediaWiki\Session classes only
+        * @param SessionId $sessionId
         */
-       public function setSessionId( MediaWiki\Session\SessionId $sessionId ) {
+       public function setSessionId( SessionId $sessionId ) {
                $this->sessionId = $sessionId;
        }
 
        /**
         * Get the session id for this request, if any
         * @since 1.27
-        * @private For use by MediaWiki\\Session classes only
-        * @return MediaWiki\\Session\\SessionId|null
+        * @private For use by MediaWiki\Session classes only
+        * @return SessionId|null
         */
        public function getSessionId() {
                return $this->sessionId;
@@ -691,7 +712,7 @@ class WebRequest {
         * This does not necessarily mean that the user is logged in!
         *
         * @deprecated since 1.27, use
-        *  \\MediaWiki\\Session\\SessionManager::singleton()->getPersistedSessionId()
+        *  \MediaWiki\Session\SessionManager::singleton()->getPersistedSessionId()
         *  instead.
         * @return bool
         */
index dca0f32..cf97984 100644 (file)
@@ -73,13 +73,8 @@ class WikiMap {
         * @return WikiReference|null WikiReference object or null if the wiki was not found
         */
        private static function getWikiWikiReferenceFromSites( $wikiID ) {
-               static $siteStore = null;
-               if ( !$siteStore ) {
-                       // Replace once T114471 got fixed and don't do the caching here.
-                       $siteStore = SiteSQLStore::newInstance();
-               }
-
-               $site = $siteStore->getSite( $wikiID );
+               $siteLookup = \MediaWiki\MediaWikiServices::getInstance()->getSiteLookup();
+               $site = $siteLookup->getSite( $wikiID );
 
                if ( !$site instanceof MediaWikiSite ) {
                        // Abort if not a MediaWikiSite, as this is about Wikis
@@ -221,10 +216,10 @@ class WikiReference {
         * @return string relative URL, without the server part.
         */
        private function getLocalUrl( $page, $fragmentId = null ) {
-               $page = wfUrlEncode( str_replace( ' ', '_', $page ) );
+               $page = wfUrlencode( str_replace( ' ', '_', $page ) );
 
                if ( is_string( $fragmentId ) && $fragmentId !== '' ) {
-                       $page .= '#' . wfUrlEncode( $fragmentId );
+                       $page .= '#' . wfUrlencode( $fragmentId );
                }
 
                return str_replace( '$1', $page, $this->mPath );
index ead8efa..839d7b2 100644 (file)
@@ -96,6 +96,9 @@ abstract class Action {
                $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
 
                if ( is_string( $classOrCallable ) ) {
+                       if ( !class_exists( $classOrCallable ) ) {
+                               return false;
+                       }
                        $obj = new $classOrCallable( $page, $context );
                        return $obj;
                }
index 87d269a..f7c30b7 100644 (file)
@@ -677,39 +677,17 @@ class InfoAction extends FormlessAction {
 
                                $setOpts += Database::getCacheSetOptions( $dbr, $dbrWatchlist );
 
-                               $result = [];
+                               $watchedItemStore = WatchedItemStore::getDefaultInstance();
 
-                               // Number of page watchers
-                               $watchers = (int)$dbrWatchlist->selectField(
-                                       'watchlist',
-                                       'COUNT(*)',
-                                       [
-                                               'wl_namespace' => $title->getNamespace(),
-                                               'wl_title' => $title->getDBkey(),
-                                       ],
-                                       $fname
-                               );
-                               $result['watchers'] = $watchers;
+                               $result = [];
+                               $result['watchers'] = $watchedItemStore->countWatchers( $title );
 
                                if ( $config->get( 'ShowUpdatedMarker' ) ) {
-                                       // Threshold: last visited about 26 weeks before latest edit
                                        $updated = wfTimestamp( TS_UNIX, $page->getTimestamp() );
-                                       $age = $config->get( 'WatchersMaxAge' );
-                                       $threshold = $dbrWatchlist->timestamp( $updated - $age );
-                                       // Number of page watchers who also visited a "recent" edit
-                                       $visitingWatchers = (int)$dbrWatchlist->selectField(
-                                               'watchlist',
-                                               'COUNT(*)',
-                                               [
-                                                       'wl_namespace' => $title->getNamespace(),
-                                                       'wl_title' => $title->getDBkey(),
-                                                       'wl_notificationtimestamp >= ' .
-                                                               $dbrWatchlist->addQuotes( $threshold ) .
-                                                               ' OR wl_notificationtimestamp IS NULL'
-                                               ],
-                                               $fname
+                                       $result['visitingWatchers'] = $watchedItemStore->countVisitingWatchers(
+                                               $title,
+                                               $updated - $config->get( 'WatchersMaxAge' )
                                        );
-                                       $result['visitingWatchers'] = $visitingWatchers;
                                }
 
                                // Total number of edits
@@ -842,7 +820,7 @@ class InfoAction extends FormlessAction {
                                : $user->getUserPage();
 
                        $hiddenPrefs = $this->context->getConfig()->get( 'HiddenPrefs' );
-                       if ( $user->getID() == 0 ) {
+                       if ( $user->getId() == 0 ) {
                                $anon_ips[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
                        } elseif ( !in_array( 'realname', $hiddenPrefs ) && $user->getRealName() ) {
                                $real_names[] = Linker::link( $page, htmlspecialchars( $user->getRealName() ) );
index 508bbe0..576533d 100644 (file)
@@ -66,6 +66,10 @@ class PurgeAction extends FormAction {
                }
 
                if ( $user->isAllowed( 'purge' ) ) {
+                       // This will update the database immediately, even on HTTP GET.
+                       // Lots of uses may exist for this feature, so just ignore warnings.
+                       Profiler::instance()->getTransactionProfiler()->resetExpectations();
+
                        $this->redirectParams = wfArrayToCgi( array_diff_key(
                                $this->getRequest()->getQueryValues(),
                                [ 'title' => null, 'action' => null ]
index 85dee2b..1c20229 100644 (file)
@@ -437,7 +437,7 @@ abstract class ApiBase extends ContextSource {
         *    RFC 7232 § 2.2 for semantics.
         *  - etag: Return an entity-tag representing the state of all resources involved
         *    in the request. Quotes must be included. See RFC 7232 § 2.3 for semantics.
-        * @return string|boolean|null As described above, or null if no value is available.
+        * @return string|bool|null As described above, or null if no value is available.
         */
        public function getConditionalRequestData( $condition ) {
                return null;
@@ -2524,123 +2524,6 @@ abstract class ApiBase extends ContextSource {
         * @{
         */
 
-       /// @deprecated since 1.24
-       const PROP_ROOT = 'ROOT';
-       /// @deprecated since 1.24
-       const PROP_LIST = 'LIST';
-       /// @deprecated since 1.24
-       const PROP_TYPE = 0;
-       /// @deprecated since 1.24
-       const PROP_NULLABLE = 1;
-
-       /**
-        * Formerly used to fetch a list of possible properites in the result,
-        * somehow organized with respect to the prop parameter that causes them to
-        * be returned. The specific semantics of the return value was never
-        * specified. Since this was never possible to be accurately updated, it
-        * has been removed.
-        *
-        * @deprecated since 1.24
-        * @return array|bool
-        */
-       protected function getResultProperties() {
-               wfDeprecated( __METHOD__, '1.24' );
-               return false;
-       }
-
-       /**
-        * @see self::getResultProperties()
-        * @deprecated since 1.24
-        * @return array|bool
-        */
-       public function getFinalResultProperties() {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
-       /**
-        * @see self::getResultProperties()
-        * @deprecated since 1.24
-        */
-       protected static function addTokenProperties( &$props, $tokenFunctions ) {
-               wfDeprecated( __METHOD__, '1.24' );
-       }
-
-       /**
-        * @see self::getPossibleErrors()
-        * @deprecated since 1.24
-        * @return array
-        */
-       public function getRequireOnlyOneParameterErrorMessages( $params ) {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
-       /**
-        * @see self::getPossibleErrors()
-        * @deprecated since 1.24
-        * @return array
-        */
-       public function getRequireMaxOneParameterErrorMessages( $params ) {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
-       /**
-        * @see self::getPossibleErrors()
-        * @deprecated since 1.24
-        * @return array
-        */
-       public function getRequireAtLeastOneParameterErrorMessages( $params ) {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
-       /**
-        * @see self::getPossibleErrors()
-        * @deprecated since 1.24
-        * @return array
-        */
-       public function getTitleOrPageIdErrorMessage() {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
-       /**
-        * This formerly attempted to return a list of all possible errors returned
-        * by the module. However, this was impossible to maintain in many cases
-        * since errors could come from other areas of MediaWiki and in some cases
-        * from arbitrary extension hooks. Since a partial list claiming to be
-        * comprehensive is unlikely to be useful, it was removed.
-        *
-        * @deprecated since 1.24
-        * @return array
-        */
-       public function getPossibleErrors() {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
-       /**
-        * @see self::getPossibleErrors()
-        * @deprecated since 1.24
-        * @return array
-        */
-       public function getFinalPossibleErrors() {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
-       /**
-        * @see self::getPossibleErrors()
-        * @deprecated since 1.24
-        * @return array
-        */
-       public function parseErrors( $errors ) {
-               wfDeprecated( __METHOD__, '1.24' );
-               return [];
-       }
-
        /**
         * Returns the description string for this module
         *
index f09c6f2..07642c4 100644 (file)
@@ -397,7 +397,13 @@ class ApiMain extends ApiBase {
                if ( $this->mInternalMode ) {
                        $this->executeAction();
                } else {
+                       $start = microtime( true );
                        $this->executeActionWithErrorHandling();
+                       if ( $this->isWriteMode() && $this->getRequest()->wasPosted() ) {
+                               $timeMs = 1000 * max( 0, microtime( true ) - $start );
+                               $this->getStats()->timing(
+                                       'api.' . $this->getModuleName() . '.executeTiming', $timeMs );
+                       }
                }
        }
 
@@ -711,7 +717,7 @@ class ApiMain extends ApiBase {
 
        /**
         * Send caching headers
-        * @param boolean $isError Whether an error response is being output
+        * @param bool $isError Whether an error response is being output
         * @since 1.26 added $isError parameter
         */
        protected function sendCacheHeaders( $isError ) {
@@ -871,7 +877,7 @@ class ApiMain extends ApiBase {
 
                        $errMessage = [
                                'code' => 'internal_api_error_' . get_class( $e ),
-                               'info' => '[' . MWExceptionHandler::getLogId( $e ) . '] ' . $info,
+                               'info' => '[' . WebRequest::getRequestId() . '] ' . $info,
                        ];
                }
                return $errMessage;
@@ -1367,7 +1373,7 @@ class ApiMain extends ApiBase {
                        'ip' => $request->getIP(),
                        'userAgent' => $this->getUserAgent(),
                        'wiki' => wfWikiID(),
-                       'timeSpentBackend' => round( $time * 1000 ),
+                       'timeSpentBackend' => (int) round( $time * 1000 ),
                        'hadError' => $e !== null,
                        'errorCodes' => [],
                        'params' => [],
@@ -1401,8 +1407,8 @@ class ApiMain extends ApiBase {
                }
 
                wfDebugLog( 'api', $msg, 'private' );
-               // ApiRequest channel is for structured data consumers
-               wfDebugLog( 'ApiRequest', '', 'private', $logCtx );
+               // ApiAction channel is for structured data consumers
+               wfDebugLog( 'ApiAction', '', 'private', $logCtx );
        }
 
        /**
@@ -1750,8 +1756,8 @@ class ApiMain extends ApiBase {
                // Use parent to make default message for the main module
                $msg = parent::makeHelpMsg();
 
-               $astriks = str_repeat( '*** ', 14 );
-               $msg .= "\n\n$astriks Modules  $astriks\n\n";
+               $asterisks = str_repeat( '*** ', 14 );
+               $msg .= "\n\n$asterisks Modules  $asterisks\n\n";
 
                foreach ( $this->mModuleMgr->getNames( 'action' ) as $name ) {
                        $module = $this->mModuleMgr->getModule( $name );
@@ -1764,7 +1770,7 @@ class ApiMain extends ApiBase {
                        $msg .= "\n";
                }
 
-               $msg .= "\n$astriks Permissions $astriks\n\n";
+               $msg .= "\n$asterisks Permissions $asterisks\n\n";
                foreach ( self::$mRights as $right => $rightMsg ) {
                        $rightsMsg = $this->msg( $rightMsg['msg'], $rightMsg['params'] )
                                ->useDatabase( false )
@@ -1775,7 +1781,7 @@ class ApiMain extends ApiBase {
                                "\nGranted to:\n  " . str_replace( '*', 'all', implode( ', ', $groups ) ) . "\n\n";
                }
 
-               $msg .= "\n$astriks Formats  $astriks\n\n";
+               $msg .= "\n$asterisks Formats  $asterisks\n\n";
                foreach ( $this->mModuleMgr->getNames( 'format' ) as $name ) {
                        $module = $this->mModuleMgr->getModule( $name );
                        $msg .= self::makeHelpMsgHeader( $module, 'format' );
@@ -1810,53 +1816,6 @@ class ApiMain extends ApiBase {
                return "* $paramName={$module->getModuleName()} $modulePrefix*";
        }
 
-       /**
-        * Check whether the user wants us to show version information in the API help
-        * @return bool
-        * @deprecated since 1.21, always returns false
-        */
-       public function getShowVersions() {
-               wfDeprecated( __METHOD__, '1.21' );
-
-               return false;
-       }
-
-       /**
-        * Add or overwrite a module in this ApiMain instance. Intended for use by extending
-        * classes who wish to add their own modules to their lexicon or override the
-        * behavior of inherent ones.
-        *
-        * @deprecated since 1.21, Use getModuleManager()->addModule() instead.
-        * @param string $name The identifier for this module.
-        * @param ApiBase $class The class where this module is implemented.
-        */
-       protected function addModule( $name, $class ) {
-               $this->getModuleManager()->addModule( $name, 'action', $class );
-       }
-
-       /**
-        * Add or overwrite an output format for this ApiMain. Intended for use by extending
-        * classes who wish to add to or modify current formatters.
-        *
-        * @deprecated since 1.21, Use getModuleManager()->addModule() instead.
-        * @param string $name The identifier for this format.
-        * @param ApiFormatBase $class The class implementing this format.
-        */
-       protected function addFormat( $name, $class ) {
-               $this->getModuleManager()->addModule( $name, 'format', $class );
-       }
-
-       /**
-        * Returns the list of supported formats in form ( 'format' => 'ClassName' )
-        *
-        * @since 1.18
-        * @deprecated since 1.21, Use getModuleManager()'s methods instead.
-        * @return array
-        */
-       public function getFormats() {
-               return $this->getModuleManager()->getNamesWithClasses( 'format' );
-       }
-
        /**@}*/
 
 }
index 6bab762..f278989 100644 (file)
@@ -747,14 +747,6 @@ class ApiPageSet extends ApiBase {
                }
        }
 
-       /**
-        * Do not use, does nothing, will be removed
-        * @deprecated since 1.21
-        */
-       public function finishPageSetGeneration() {
-               wfDeprecated( __METHOD__, '1.21' );
-       }
-
        /**
         * This method populates internal variables with page information
         * based on the given array of title strings.
index 36b62f5..64bb9ba 100644 (file)
@@ -24,6 +24,7 @@
  *
  * @file
  */
+use MediaWiki\Logger\LoggerFactory;
 
 /**
  * API interface for page purging
@@ -75,6 +76,17 @@ class ApiPurge extends ApiBase {
                                                $enableParserCache
                                        );
 
+                                       # Logging to better see expensive usage patterns
+                                       if ( $forceRecursiveLinkUpdate ) {
+                                               LoggerFactory::getInstance( 'RecursiveLinkPurge' )->info(
+                                                       "Recursive link purge enqueued for {title}",
+                                                       [
+                                                               'user' => $this->getUser()->getName(),
+                                                               'title' => $title->getPrefixedText()
+                                                       ]
+                                               );
+                                       }
+
                                        # Update the links tables
                                        $updates = $content->getSecondaryDataUpdates(
                                                $title, null, $forceRecursiveLinkUpdate, $p_result );
index 4336907..733ea2c 100644 (file)
@@ -552,6 +552,26 @@ class ApiQuery extends ApiBase {
                return implode( "\n", $moduleDescriptions );
        }
 
+       public function isReadMode() {
+               // We need to make an exception for ApiQueryTokens so login tokens can
+               // be fetched on private wikis. Restrict that exception as much as
+               // possible: no other modules allowed, and no pageset parameters
+               // either. We do allow the 'rawcontinue' and 'indexpageids' parameters
+               // since frameworks might add these unconditionally and they can't
+               // expose anything here.
+               $params = array_filter(
+                       array_diff_key(
+                               $this->extractRequestParams() + $this->getPageSet()->extractRequestParams(),
+                               [ 'rawcontinue' => 1, 'indexpageids' => 1 ]
+                       )
+               );
+               if ( $params === [ 'meta' => [ 'tokens' ] ] ) {
+                       return false;
+               }
+
+               return true;
+       }
+
        protected function getExamplesMessages() {
                return [
                        'action=query&prop=revisions&meta=siteinfo&' .
index 404fc19..9b05537 100644 (file)
@@ -66,6 +66,9 @@ class ApiQueryExtLinksUsage extends ApiQueryGeneratorBase {
                        $this->addWhereFld( 'page_namespace', $params['namespace'] );
                }
 
+               // Normalize query to match the normalization applied for the externallinks table
+               $query = Parser::normalizeLinkUrl( $query );
+
                $whereQuery = $this->prepareUrlQuerySearchString( $query, $protocol );
 
                if ( $whereQuery !== null ) {
index ea7818c..ea1b94e 100644 (file)
@@ -448,12 +448,12 @@ class ApiQueryInfo extends ApiQueryBase {
                        ApiResult::setIndexedTagName( $pageInfo['restrictiontypes'], 'rt' );
                }
 
-               if ( $this->fld_watched ) {
-                       $pageInfo['watched'] = isset( $this->watched[$ns][$dbkey] );
+               if ( $this->fld_watched && $this->watched !== null ) {
+                       $pageInfo['watched'] = $this->watched[$ns][$dbkey];
                }
 
                if ( $this->fld_watchers ) {
-                       if ( isset( $this->watchers[$ns][$dbkey] ) ) {
+                       if ( $this->watchers !== null && $this->watchers[$ns][$dbkey] !== 0 ) {
                                $pageInfo['watchers'] = $this->watchers[$ns][$dbkey];
                        } elseif ( $this->showZeroWatchers ) {
                                $pageInfo['watchers'] = 0;
@@ -461,7 +461,7 @@ class ApiQueryInfo extends ApiQueryBase {
                }
 
                if ( $this->fld_visitingwatchers ) {
-                       if ( isset( $this->visitingwatchers[$ns][$dbkey] ) ) {
+                       if ( $this->visitingwatchers !== null && $this->visitingwatchers[$ns][$dbkey] !== 0 ) {
                                $pageInfo['visitingwatchers'] = $this->visitingwatchers[$ns][$dbkey];
                        } elseif ( $this->showZeroWatchers ) {
                                $pageInfo['visitingwatchers'] = 0;
@@ -470,7 +470,7 @@ class ApiQueryInfo extends ApiQueryBase {
 
                if ( $this->fld_notificationtimestamp ) {
                        $pageInfo['notificationtimestamp'] = '';
-                       if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) {
+                       if ( $this->notificationtimestamps[$ns][$dbkey] ) {
                                $pageInfo['notificationtimestamp'] =
                                        wfTimestamp( TS_ISO_8601, $this->notificationtimestamps[$ns][$dbkey] );
                        }
@@ -758,30 +758,23 @@ class ApiQueryInfo extends ApiQueryBase {
 
                $this->watched = [];
                $this->notificationtimestamps = [];
-               $db = $this->getDB();
 
-               $lb = new LinkBatch( $this->everything );
+               $store = WatchedItemStore::getDefaultInstance();
+               $timestamps = $store->getNotificationTimestampsBatch( $user, $this->everything );
 
-               $this->resetQueryParams();
-               $this->addTables( [ 'watchlist' ] );
-               $this->addFields( [ 'wl_title', 'wl_namespace' ] );
-               $this->addFieldsIf( 'wl_notificationtimestamp', $this->fld_notificationtimestamp );
-               $this->addWhere( [
-                       $lb->constructSet( 'wl', $db ),
-                       'wl_user' => $user->getId()
-               ] );
-
-               $res = $this->select( __METHOD__ );
-
-               foreach ( $res as $row ) {
-                       if ( $this->fld_watched ) {
-                               $this->watched[$row->wl_namespace][$row->wl_title] = true;
-                       }
-                       if ( $this->fld_notificationtimestamp ) {
-                               $this->notificationtimestamps[$row->wl_namespace][$row->wl_title] =
-                                       $row->wl_notificationtimestamp;
+               if ( $this->fld_watched ) {
+                       foreach ( $timestamps as $namespaceId => $dbKeys ) {
+                               $this->watched[$namespaceId] = array_map(
+                                       function( $x ) {
+                                               return $x !== false;
+                                       },
+                                       $dbKeys
+                               );
                        }
                }
+               if ( $this->fld_notificationtimestamp ) {
+                       $this->notificationtimestamps = $timestamps;
+               }
        }
 
        /**
@@ -799,28 +792,17 @@ class ApiQueryInfo extends ApiQueryBase {
                        return;
                }
 
-               $this->watchers = [];
                $this->showZeroWatchers = $canUnwatchedpages;
-               $db = $this->getDB();
-
-               $lb = new LinkBatch( $this->everything );
 
-               $this->resetQueryParams();
-               $this->addTables( [ 'watchlist' ] );
-               $this->addFields( [ 'wl_title', 'wl_namespace', 'count' => 'COUNT(*)' ] );
-               $this->addWhere( [
-                       $lb->constructSet( 'wl', $db )
-               ] );
-               $this->addOption( 'GROUP BY', [ 'wl_namespace', 'wl_title' ] );
+               $countOptions = [];
                if ( !$canUnwatchedpages ) {
-                       $this->addOption( 'HAVING', "COUNT(*) >= $unwatchedPageThreshold" );
+                       $countOptions['minimumWatchers'] = $unwatchedPageThreshold;
                }
 
-               $res = $this->select( __METHOD__ );
-
-               foreach ( $res as $row ) {
-                       $this->watchers[$row->wl_namespace][$row->wl_title] = (int)$row->count;
-               }
+               $this->watchers = WatchedItemStore::getDefaultInstance()->countWatchersMultiple(
+                       $this->everything,
+                       $countOptions
+               );
        }
 
        /**
@@ -842,14 +824,7 @@ class ApiQueryInfo extends ApiQueryBase {
 
                $this->showZeroWatchers = $canUnwatchedpages;
 
-               // Assemble a WHERE condition to find:
-               // * if the page exists, number of users watching who have
-               //   visited the page recently
-               // * if the page doesn't exist, number of users that have
-               //   the page on their watchlist
-               $whereStrings = [];
-
-               // For pages that exist
+               $titlesWithThresholds = [];
                if ( $this->titles ) {
                        $lb = new LinkBatch( $this->titles );
 
@@ -864,55 +839,38 @@ class ApiQueryInfo extends ApiQueryBase {
                        $this->addOption( 'GROUP BY', [ 'page_namespace', 'page_title' ] );
                        $timestampRes = $this->select( __METHOD__ );
 
-                       // Assemble SQL WHERE condition to find number of page watchers who also
-                       // visited a "recent" edit (last visited about 26 weeks before latest edit)
                        $age = $config->get( 'WatchersMaxAge' );
                        $timestamps = [];
                        foreach ( $timestampRes as $row ) {
                                $revTimestamp = wfTimestamp( TS_UNIX, (int)$row->rev_timestamp );
-                               $threshold = $db->timestamp( $revTimestamp - $age );
-                               $timestamps[$row->page_namespace][$row->page_title] = $threshold;
-                       }
-
-                       foreach ( $timestamps as $ns_key => $namespace ) {
-                               $pageStrings = [];
-                               foreach ( $namespace as $pg_key => $threshold ) {
-                                       $pageStrings[] = "wl_title = '$pg_key' AND" .
-                                               ' (wl_notificationtimestamp >= ' .
-                                               $db->addQuotes( $threshold ) .
-                                               ' OR wl_notificationtimestamp IS NULL)';
-                               }
-                               $whereStrings[] = "wl_namespace = '$ns_key' AND (" .
-                                       $db->makeList( $pageStrings, LIST_OR ) . ')';
+                               $timestamps[$row->page_namespace][$row->page_title] = $revTimestamp - $age;
                        }
+                       $titlesWithThresholds = array_map(
+                               function( LinkTarget $target ) use ( $timestamps ) {
+                                       return [
+                                               $target, $timestamps[$target->getNamespace()][$target->getDBkey()]
+                                       ];
+                               },
+                               $this->titles
+                       );
                }
 
-               // For nonexistant pages
                if ( $this->missing ) {
-                       $lb = new LinkBatch( $this->missing );
-                       $whereStrings[] = $lb->constructSet( 'wl', $db );
-               }
-
-               // Make the actual string and do the query
-               $whereString = $db->makeList( $whereStrings, LIST_OR );
-
-               $this->resetQueryParams();
-               $this->addTables( [ 'watchlist' ] );
-               $this->addFields( [
-                       'wl_namespace',
-                       'wl_title',
-                       'count' => 'COUNT(*)'
-               ] );
-               $this->addWhere( [ $whereString ] );
-               $this->addOption( 'GROUP BY', [ 'wl_namespace', 'wl_title' ] );
-               if ( !$canUnwatchedpages ) {
-                       $this->addOption( 'HAVING', "COUNT(*) >= $unwatchedPageThreshold" );
-               }
-
-               $res = $this->select( __METHOD__ );
-               foreach ( $res as $row ) {
-                       $this->visitingwatchers[$row->wl_namespace][$row->wl_title] = (int)$row->count;
-               }
+                       $titlesWithThresholds = array_merge(
+                               $titlesWithThresholds,
+                               array_map(
+                                       function( LinkTarget $target ) {
+                                               return [ $target, null ];
+                                       },
+                                       $this->missing
+                               )
+                       );
+               }
+
+               $this->visitingwatchers = WatchedItemStore::getDefaultInstance()->countVisitingWatchersMultiple(
+                       $titlesWithThresholds,
+                       !$canUnwatchedpages ? $unwatchedPageThreshold : null
+               );
        }
 
        public function getCacheMode( $params ) {
index 6d1540b..b039a1e 100644 (file)
@@ -32,6 +32,10 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
        }
 
        public function execute() {
+               if ( !$this->getUser()->isLoggedIn() ) {
+                       $this->dieUsage( 'You must be logged-in to have an upload stash', 'notloggedin' );
+               }
+
                $params = $this->extractRequestParams();
                $modulePrefix = $this->getModulePrefix();
 
index cc829aa..de5a377 100644 (file)
@@ -59,7 +59,7 @@ class ApiQueryTokens extends ApiQueryBase {
         * @return (string|array)[] Returning a string will use that as the salt
         *  for User::getEditTokenObject() to fetch the token, which will give a
         *  LoggedOutEditToken (always "+\\") for anonymous users. Returning an
-        *  array will use it as parameters to MediaWiki\\Session\\Session::getToken(),
+        *  array will use it as parameters to MediaWiki\Session\Session::getToken(),
         *  which will always return a full token even for anonymous users.
         */
        public static function getTokenTypeSalts() {
@@ -84,14 +84,14 @@ class ApiQueryTokens extends ApiQueryBase {
        /**
         * Get a token from a salt
         * @param User $user
-        * @param MediaWiki\\Session\\Session $session
+        * @param MediaWiki\Session\Session $session
         * @param string|array $salt A string will be used as the salt for
         *  User::getEditTokenObject() to fetch the token, which will give a
         *  LoggedOutEditToken (always "+\\") for anonymous users. An array will
-        *  be used as parameters to MediaWiki\\Session\\Session::getToken(), which
+        *  be used as parameters to MediaWiki\Session\Session::getToken(), which
         *  will always return a full token even for anonymous users. An array will
         *  also persist the session.
-        * @return MediaWiki\\Session\\Token
+        * @return MediaWiki\Session\Token
         */
        public static function getToken( User $user, MediaWiki\Session\Session $session, $salt ) {
                if ( is_array( $salt ) ) {
index 9e7e62e..0fc443a 100644 (file)
@@ -225,23 +225,15 @@ class ApiQueryUserInfo extends ApiQueryBase {
                }
 
                if ( isset( $this->prop['unreadcount'] ) ) {
-                       $dbr = $this->getQuery()->getNamedDB( 'watchlist', DB_SLAVE, 'watchlist' );
-
-                       $count = $dbr->selectRowCount(
-                               'watchlist',
-                               '1',
-                               [
-                                       'wl_user' => $user->getId(),
-                                       'wl_notificationtimestamp IS NOT NULL',
-                               ],
-                               __METHOD__,
-                               [ 'LIMIT' => self::WL_UNREAD_LIMIT ]
+                       $unreadNotifications = WatchedItemStore::getDefaultInstance()->countUnreadNotifications(
+                               $user,
+                               self::WL_UNREAD_LIMIT
                        );
 
-                       if ( $count >= self::WL_UNREAD_LIMIT ) {
+                       if ( $unreadNotifications === true ) {
                                $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
                        } else {
-                               $vals['unreadcount'] = $count;
+                               $vals['unreadcount'] = $unreadNotifications;
                        }
                }
 
index 3436320..5d5c829 100644 (file)
@@ -1150,7 +1150,7 @@ class ApiResult implements ApiSerializable {
         * the API.
         *
         * @param array $vars
-        * @param boolean $forceHash
+        * @param bool $forceHash
         * @return array
         */
        public static function addMetadataToResultVars( $vars, $forceHash = true ) {
index 79fe9cf..5072c66 100644 (file)
@@ -45,6 +45,7 @@
        "apihelp-emailuser-description": "مراسلة المستخدم",
        "apihelp-expandtemplates-param-title": "عنوان الصفحة.",
        "apihelp-feedrecentchanges-param-tagfilter": "فلتر بالوسم.",
+       "apihelp-feedrecentchanges-example-simple": " اظهر التغييرات الحديثة",
        "apihelp-feedrecentchanges-example-30days": "أظهر التغييرات الأخيرة في 30 يوم.",
        "apihelp-feedwatchlist-example-all6hrs": "اظهر كل التغييرات في اخر 6 ساعات",
        "apihelp-filerevert-param-comment": "تعليق الرفع.",
index a7e5754..0d19545 100644 (file)
@@ -5,7 +5,7 @@
                        "Enolp"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentación]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Llista d'alderique]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anuncios de la API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Fallos y solicitúes]\n</div>\n<strong>Estau:</strong> Toles carauterístiques qu'apaecen nesta páxina tendríen de funcionar, pero la API inda ta en desendolcu activu, y puede camudar en cualquier momentu. Suscríbete a la [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ llista de corréu mediawiki-api-announce] p'avisos sobro anovamientos.\n\n<strong>Solicitúes incorreutes:</strong> Cuando s'unvíen solicitúes incorreutes a la API, unvíase una cabecera HTTP cola clave \"MediaWiki-API-Error\" y, darréu, tanto'l valor de la cabecera como'l códigu d'error devueltu pondránse al mesmu valor. Pa más información, consulta [[mw:API:Errors_and_warnings|API: Errores y avisos]].",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentación]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Llista d'alderique]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anuncios de la API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Fallos y solicitúes]\n</div>\n<strong>Estau:</strong> Toles carauterístiques qu'apaecen nesta páxina tendríen de funcionar, pero la API inda ta en desendolcu activu, y puede camudar en cualquier momentu. Suscríbete a la [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ llista de corréu mediawiki-api-announce] p'avisos sobro anovamientos.\n\n<strong>Solicitúes incorreutes:</strong> Cuando s'unvíen solicitúes incorreutes a la API, unvíase una cabecera HTTP cola clave \"MediaWiki-API-Error\" y, darréu, tanto'l valor de la cabecera como'l códigu d'error devueltu pondránse al mesmu valor. Pa más información, consulta [[mw:API:Errors_and_warnings|API: Errores y avisos]].\n\n<strong>Pruebes:</strong> Pa facilitar les pruebes de solicitúes API, consulta [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Qué aición facer.",
        "apihelp-main-param-format": "El formatu de la salida.",
        "apihelp-block-description": "Bloquiar a un usuariu.",
index bda2291..0e8b437 100644 (file)
 {
        "@metadata": {
                "authors": [
-                       "Рустам Нурыев"
+                       "Рустам Нурыев",
+                       "Азат Хәлилов",
+                       "Sagan",
+                       "Айсар",
+                       "Янмурза Баки",
+                       "Айбикә",
+                       "Лилиә",
+                       "Lizalizaufa",
+                       "Гульчатай",
+                       "Ilmira",
+                       "Гизатуллина",
+                       "Танзиля Кутлугильдина"
                ]
        },
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Документация]]\n* [[mw:API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почта таратыу]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce  API яңылыҡтары]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R  Хаталар һәм яуаптар]\n</div>\n<strong>Статус:</strong> Был биттә  күрһәтелгән бар функциялар ҙа эшләргә тейеш,  шулай ҙа  API әүҙем эшкәртеү хәлендә тора һәм теләгән бер ваҡытта үҙгәрергә мөмкин. Яңыртылыуҙарҙы һәр саҡ белеп торор өсөн [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почта таратыу mediawiki-api-announce], ошоға яҙыл.\n\n<strong>Хаталы һоратыуҙар:</strong> Әгәр API хаталы һоратыу алһа,     HTTP баш һүҙе   «MediaWiki-API-Error» асҡысы менән кире ҡайтарыла,  бынан һуң баш һүҙҙең мәғәнәһе һәм хата  коды кире ебәреләсәк һәм кире шул уҡ мәғәнәлә кире ҡуйыласаҡ. Киңерәк мәғлүмәтте ошонан ҡара  [[mw:API:Errors_and_warnings|API:Хаталар һәм иҫкәртеүҙәр]].\n\n<strong>Тестлау:</strong>   API-һоратыуҙарҙы тестлау уңайлы булһын өсөн ҡара. [[Special:ApiSandbox]]",
+       "apihelp-main-param-action": "Үтәлергә тейеш булған ғәмәлдәр.",
+       "apihelp-main-param-format": "Мәғлүмәттәр сығарыу форматы.",
+       "apihelp-main-param-smaxage": "Cache-Control HTTP-баш һүҙҙең <code>s-maxage</code>  мәғәнәһен бирелгән секунд эсендә билдәләй.",
+       "apihelp-main-param-maxage": "Cache-Control HTTP-баш һүҙҙең <code>s-maxage</code>  мәғәнәһен бирелгән секунд эсендә билдәләй.",
+       "apihelp-main-param-assert": "Әгәр <kbd>user</kbd>бирелһә ҡулланыусы танылған икәненә, йәки <kbd>bot</kbd>бирелһә ҡол хоҡуғына эйә икәненә ышанырға",
+       "apihelp-main-param-requestid": "Бында бирелгән һәр мәғәнә яуапҡа индереләсәк. Һорауҙарҙы айырыу өсөн файҙаланылырға мөмкин",
+       "apihelp-main-param-servedby": "Һөҙөмтәләргә һорауҙы эшкәрткән хост исемен индерергә",
+       "apihelp-main-param-curtimestamp": "Һөҙөмтәләргә ваҡытлыса тамға ҡуйырға.",
+       "apihelp-main-param-origin": "API мөрәжәғәт иткәндә AJAX-һорау (CORS) кросс-домены ҡулланһағыҙ, параметрға тәүге домен мәғәнәһен бирегеҙ. Ул алдағы һорауҙа булырға һәм шул рәүешле URI-һорауҙың (POST түгел) бер өлөшө булырға тейеш. Ул атамалағы бер сығанаҡҡа  <code>Origin<code> тап килергә тейеш, мәҫәлән, <kbd>https://ru.wikipedia.org</kbd> йәки <kbd>https://meta.wikimedia.org</kbd>. Әгәр ҙә параметр атамаға <code>Origin<code> тура килмәһә, яуап 403 хата коды менән кире ҡайтарыла. Әгәр параметр <code>Origin</code> атамаға тура килһә, һәм сығанаҡ рөхсәт ителгән исемлектә икән, <code>Access-Control-Allow-Origin</code> тигән атама ҡуйыласаҡ.",
+       "apihelp-block-description": "Ҡатнашыусыны бикләү",
+       "apihelp-block-param-user": "Һеҙ бикләргә теләгән ҡатнашыусының IP адресы йәки  IP диапозоны.",
+       "apihelp-block-param-expiry": "Ғәмәлдән сығыу ваҡыты. Ул сағыштырмаса булыуы мөмкин(мәҫәлән <kbd>5 ай</kbd> йәки <kbd>2 аҙна</kbd>) йәки абсолют (мәҫәлән <kbd>2014-09-18T12:34:56Z</kbd>). Әгәр саманан тыш ҡуйылһа <kbd>сикһеҙ</kbd>, <kbd>билдәләнмәгән</kbd>, йәки <kbd>һис ҡасан</kbd>,  блок ғәмәлдән сыҡмай.",
+       "apihelp-block-param-reason": "Бикләү сәбәбе.",
+       "apihelp-block-param-anononly": "Аноним ҡатнашыусыларҙы бикләү (йәғни IP адресынан төҙәтеүҙе тыйыу).",
+       "apihelp-block-param-nocreate": "Яңы иҫәп яҙыуҙарын булдырыуҙы тыйыу.",
+       "apihelp-block-param-autoblock": "Был ҡатнашыусы ҡулланған һуңғы IP адрестарҙы һәм артабан үҙгәртеү өсөн ҡулланрға тырышҡан IP адрестарҙы бикләргә",
+       "apihelp-block-param-noemail": "Ҡулланыусының Вики аша электрон почта ебәреүен тыйыу. (Талап итә <code>blockemail</code> хоҡуғын).",
+       "apihelp-block-param-hidename": "Бикләү журналында ҡулланыусы исемен йәшерергә. (Хоҡуҡ талап ителә<code>hideuser</code>)",
+       "apihelp-block-param-allowusertalk": "Ҡатнашыусыларға үҙҙәренең биттәрен мөхәррирләргә мөмкинлек бирә (<var> менән бәйләнгән. [[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
+       "apihelp-block-param-reblock": "Әгәр ҡатнашыусы бикләнгән булһа, ғәмәлдәге бикләүгә күсереп яҙырға.",
+       "apihelp-block-param-watchuser": "Битте йәки IP-ҡатнашыусыны һәм фекер алышыу битен күҙәтеү аҫтына аларға.",
+       "apihelp-block-example-ip-simple": "Блок IP-адрес <KBD> 192.0.2.5 </ KBD> өс көн эсендә  <KBD> Беренсе удар </ KBD>.",
+       "apihelp-block-example-user-complex": "Ҡулланыусыны ябыу <KBD> Вандал </ KBD>  уйланылған  билдәһеҙ мөҙҙәткә  <KBD> Вандаллыҡ </ KBD>, шулай уҡ яңы иҫәп булдырыуға юл ҡуймау һәм электрон почтаға ебәреү.",
+       "apihelp-checktoken-description": "\n<kbd>-нан Маркерҙың дөрөҫлөгөн тикшерегеҙ [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
+       "apihelp-checktoken-param-type": "Тамға тибы һынау үтә.",
+       "apihelp-checktoken-param-token": "Тикшереү токены.",
+       "apihelp-checktoken-param-maxtokenage": "Токендың максималь йәше (секундтарҙа)",
+       "apihelp-checktoken-example-simple": "<kbd>csrf</kbd>-токендың яраҡлығын тикшерергә",
+       "apihelp-clearhasmsg-description": "Ағымдағы ҡуллыныусының <code>hasmsg</code> флагын таҙарта",
+       "apihelp-clearhasmsg-example-1": "Ағымдағы ҡуллыныусының <code>hasmsg</code> флагын таҙарта",
+       "apihelp-compare-description": "\nТикшереү һаны, биттең баш һүҙе, йәки бит өсөн идентификатор баштан аҙаҡҡаса икеһе өсөн дә  ҡабул ителергә тейеш",
+       "apihelp-compare-param-fromtitle": "Сағыштырыу өсөн беренсе баш һүҙ",
+       "apihelp-compare-param-fromid": "Сағыштырыу өсөн беренсе идентификатор.",
+       "apihelp-compare-param-fromrev": "Сағыштырыу өсөн беренсе редакция.",
+       "apihelp-compare-param-totitle": "Сағыштырыу өсөн икенсе баш һүҙ",
+       "apihelp-compare-param-toid": "Сағыштырыу өсөн икенсе идентификатор.",
+       "apihelp-compare-param-torev": "Сағыштырыу өсөн икенсе версия.",
+       "apihelp-compare-example-1": "1-се һәм 2-се версиялар араһында айырма эшләү",
+       "apihelp-createaccount-description": "Ҡатнашыусыларҙың яңы иҫәп яҙыуҙарын булдырыу.",
+       "apihelp-createaccount-param-name": "Ҡатнашыусы исеме.",
+       "apihelp-createaccount-param-password": "Серһүҙ (ignored if <var>$1mailpassword</var> is set).",
+       "apihelp-createaccount-param-domain": "Тышҡы аутентификация домены (өҫтәмә).",
+       "apihelp-createaccount-param-token": "Беренсе ғариза буйынса алынған токендың иҫәп яҙмаһын булдырыу",
+       "apihelp-createaccount-param-email": "Ҡатнашыусының электрон почта адресы (өҫтәмә).",
+       "apihelp-createaccount-param-realname": "Ҡатнашыусының ысын исеме(өҫтәмә)",
+       "apihelp-createaccount-param-mailpassword": "Әгәр ҙә теләһә ниндәй мәғәнә ҡуйылһа, осраҡлы серһүҙ ҡулланыусыға ебәреләсәк",
+       "apihelp-createaccount-param-reason": "Журналға яҙыу өсөн иҫәп яҙмаһын булдырыуға өҫтәмә сәбәп",
+       "apihelp-createaccount-param-language": "Тел кодын ҡулланыусы өсөн һүҙһеҙ ҡуйырға (мотлаҡ түгел, эсенә алғандағында тел  һүҙһеҙ файҙаланыла)",
+       "apihelp-createaccount-example-pass": "<kbd>test123</kbd> серһүҙле <kbd>testuser</kbd> ҡулланыусыһын булдырыу.",
+       "apihelp-createaccount-example-mail": "<kbd>testmailuser</kbd> ҡулланыусыһын һәм электрон почтаны булдырыу, осраҡлы серһеҙ яһау",
+       "apihelp-delete-description": "Битте юйырға.",
+       "apihelp-delete-param-title": "Биттең баш һүҙен юйырға. <var>$1биттәрҙән</var> бергә файҙаланыу  мөмкин түгел.",
+       "apihelp-delete-param-pageid": "Бит идентифакторы юйылыу өсөн биттәр.  <var>$1title</var> менән бергә ҡулланыла алмайҙар",
+       "apihelp-delete-param-reason": "Юйылыу сәбәбе. Әгәр ул  ҡуйылмаған булһа, билдәләнмәгән сәбәп менән автоматик рәүештә юйыласаҡ.",
+       "apihelp-delete-param-tags": "Юйҙырылғандар журналындағы яҙмаларға  мөрәжәғәт итер өсөн, билдәләрҙе үҙгәртергә.",
+       "apihelp-delete-param-watch": "Ҡулланыусының ағымдағы күҙәтеү исемлегенә бит өҫтәргә.",
+       "apihelp-delete-param-watchlist": "Ағымдағы ҡулланыусының теҙмәһенән битте һүҙһеҙ өҫтәргә йәки юйырға, һылтанмаларҙы файҙаланығыҙ йәки сәғәтте алмаштырмаҫҡа.",
+       "apihelp-delete-param-unwatch": "Ҡулланыусының ағымдағы күҙәтеү исемлегенән битте юйырға.",
+       "apihelp-delete-param-oldimage": "\nБында нисек  ҡаралғанса, юйыу өсөн иҫке һүрәтләмәнең исеме [[Special:ApiHelp/query+imageinfo|action=query&prop=imageinfo&iiprop=archivename]]",
+       "apihelp-delete-example-simple": "Юйырға: <kbd>Main Page</kbd>.",
+       "apihelp-delete-example-reason": "Юйырға <kbd>Main Page</kbd> сәбәп <kbd>Preparing for move</kbd>.",
+       "apihelp-disabled-description": "Был модуль һүндерелгән.",
+       "apihelp-edit-description": "Биттәрҙе төҙөргә һәм мөхәррирләргә.",
+       "apihelp-edit-param-title": "Мөхәриррләү өсөн биттең исеме.<var>$1биттәрҙән</var> бергә файҙаланыу  мөмкин түгел.",
+       "apihelp-edit-param-pageid": "Бит идентифакторын мөхәррирләү өсөн биттәр.  <var>$1title</var> менән бергә ҡулланыла алмайҙар",
+       "apihelp-edit-param-section": "Номерҙы айырыу. <KBD> 0 </ KBD> өҫкө секция өсөн, <KBD> яңы </ KBD> яңынан бүлеү өсөн.",
+       "apihelp-edit-param-sectiontitle": "Яңы бүлек өсөн баш исем.",
+       "apihelp-edit-param-text": "Биттең йөкмәткеһе.",
+       "apihelp-edit-param-summary": "Һығымтаны мөхәррирләргә. Шулай уҡ бүлектең  $1section = яңы $1sectiontitle исеме ҡуйылмаған",
+       "apihelp-edit-param-tags": "Яңынан ҡарау  өсөн, билдәләрҙе үҙгәртергә.",
+       "apihelp-edit-param-minor": "Әҙ генә үҙгәртеүҙәр.",
+       "apihelp-edit-param-notminor": "Ҙур ғына үҙгәреш (ғәҙәттә, «әҙ»ҙән күберәк төҙәтеү).",
+       "apihelp-edit-param-bot": "Төҙәтеүҙе бот яһаған тип билдәләү.",
+       "apihelp-edit-param-basetimestamp": "База тикшереү билдәһе тышҡы ҡаршылыҡтарҙы  белеү өсөн файҙаланыла. \n\n[[Special:ApiHelp/query+revisions|action=query&prop=revisions&rvprop=timestamp]] ярҙамында алынырға мөмкин",
+       "apihelp-edit-param-starttimestamp": "Билдә, мөхәриррләү процессы башланған саҡта,  мөхәриррләү ҡаршылыҡтары беленгәндә файҙаланыла. Тура килгән ғәмәл <вар> [[Special:ApiHelp/main|curtimestamp]] ярҙамы менән мөхәриррләү процессы  башында  алынырға мөмкин (мәҫәлән, мөхәриррләү бите эстәлеген тейәгәндә)",
+       "apihelp-edit-param-recreate": "Шул уҡ ваҡытта юйыласаҡ бит тураһындағы бар хаталарҙы ҡапларға.",
+       "apihelp-edit-param-createonly": "Булған битте мөхәррирләмәҫкә.",
+       "apihelp-edit-param-nocreate": "Сик күрһәтелмәһә, хаталарҙы ташларға.",
+       "apihelp-edit-param-watch": "Ҡулланыусының ағымдағы күҙәтеү исемлегенә бит өҫтәргә.",
+       "apihelp-edit-param-unwatch": "Ҡулланыусының ағымдағы күҙәтеү исемлегенән битте юйырға.",
+       "apihelp-edit-param-watchlist": "Ағымдағы ҡулланыусының теҙмәһенән битте һүҙһеҙ өҫтәргә йәки юйырға, һылтанмаларҙы файҙаланығыҙ йәки сәғәтте алмаштырмағыҙ.",
+       "apihelp-edit-param-md5": "\n\nMD5-хэш параметрының $1 text, йәки  $1 prepend тексы  һәм $1 appendtext параметрҙары  бәйләнгән. \nҠуйылған булһа, әгәр хэш дөрөҫ булмаһа, мөхәррирләү эшләнмәйәсәк.",
+       "apihelp-edit-param-prependtext": "Был тексты биттең башына өҫтәгеҙ. $1text алмаштыра.",
+       "apihelp-edit-param-appendtext": "Был тексты биттең аҙағынаса өҫтәгеҙ.$1text алмаштыра.\n$1section -ды файҙаланығыҙ = яңы, яңы бүлек өҫтәү өсөн, ә был параметрға түгел.",
+       "apihelp-edit-param-undo": "Был версияны кире алырға. $1text,$1prependtext,$1appendtext алмаштыра.",
+       "apihelp-edit-param-undoafter": "$1undo- нан алып барлыҡ үҙгәртеүҙәрҙе кире алырға. Әгәр ул ҡуйылмаған булһа, бер тикшереүҙе кире алыу ҙа етә.",
+       "apihelp-edit-param-redirect": "Автоматик йүнәлтәүҙе рөхсәт итергә.",
+       "apihelp-edit-param-contentformat": "Текстҡа ҡуйыу өсөн йөкмәткенең сериализация форматы.",
+       "apihelp-edit-param-contentmodel": "Яңы йөкмәткенең контент моделе.",
+       "apihelp-edit-param-token": "Маркер һуңғы параметр сифатында ебәрелергә тейеш, йәки, һәрхәлдә $1text параметрынан һуң.",
+       "apihelp-edit-example-edit": "Битте мөхәррирләү",
+       "apihelp-edit-example-prepend": "Бит башына тылсымлы һүҙ ҡуйырға <kbd>_&#95;NOTOC_&#95;</kbd>.",
+       "apihelp-edit-example-undo": " 13579-ҙан 13585-кә тиклем төҙәтеүҙәрҙе кире алырға",
+       "apihelp-emailuser-description": "Ҡатнашыусыға хат",
+       "apihelp-emailuser-param-target": "Ҡатнашыусы электрон хат ебәрә",
+       "apihelp-emailuser-param-subject": "Теманың баш һүҙе",
+       "apihelp-emailuser-param-text": "Хат эстәлеге",
+       "apihelp-emailuser-param-ccme": "Был хәбәрҙең копияһын миңә ебәрергә",
+       "apihelp-emailuser-example-email": "Ҡатнашыусыға хат ебәрергә <kbd>WikiSysop</kbd>текст <kbd>Content</kbd>.",
+       "apihelp-expandtemplates-description": "wikitext ҡалыптарын аса.",
+       "apihelp-expandtemplates-param-title": "Бит баш һүҙе",
+       "apihelp-expandtemplates-param-text": "Конвертлау өсөн викитекст",
+       "apihelp-expandtemplates-param-revid": "<nowiki>{{REVISIONID}}</nowiki> һәм шуға оҡшаған  алмаштар өсөн ID-ны яңынан ҡарау",
+       "apihelp-expandtemplates-param-prop": "\nАлыу өсөн, мәғлүмәттең ҡайһы өлөшө\n\nИғтибар итегеҙ, әгәр бер ғәмәл дә һайланмаһа, ул саҡта һөҙөмтә  вики- текстан торасаҡ, тик сығыу элекке форматта.",
+       "apihelp-expandtemplates-paramvalue-prop-wikitext": "Киңәйтелгән викитекст",
+       "apihelp-expandtemplates-paramvalue-prop-categories": "Бар категориялар ҙа вики текста  күрһәтелмәй индерелгән мәғлүмәттәрҙе күрһәтә",
+       "apihelp-expandtemplates-paramvalue-prop-properties": "Вики-текстағы  билдәле киңәйтелгән тылсымлы һүҙҙәрҙең биттәре үҙенсәлеге.",
+       "apihelp-expandtemplates-paramvalue-prop-ttl": "Максималь ваҡыт үткәндән һуң һөҙөмтә кэштары яраҡһыҙ тип табылырға тейеш.",
+       "apihelp-expandtemplates-paramvalue-prop-jsconfigvars": "Бит өсөн үҙенсәлекле  JavaScript үҙгәреүсән конфигурациялар бирә.",
+       "apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "JavaScriptтың JSON юлы һымаҡ үҙенсәлекле биттәренә  алышына торған конфигурация бирә.",
+       "apihelp-expandtemplates-paramvalue-prop-parsetree": "XML керетелә торған мәғлүмәт ағасы (шәжәрәһе).",
+       "apihelp-expandtemplates-param-includecomments": "Сыҡҡанда HTML комментарийҙарына  индереү кәрәкме?",
+       "apihelp-expandtemplates-example-simple": "Вики-тексты асығыҙ <kbd><nowiki>{{Project:Sandbox}}</nowiki></kbd>.",
+       "apihelp-feedcontributions-description": "Һеҙҙең исемгә килгән тәҡдимдәргә ҡайтыу",
+       "apihelp-feedcontributions-param-feedformat": "Мәғлүмәттәр сығарыу форматы.",
+       "apihelp-feedcontributions-param-year": "Йылдан башлап (һәм элегерәк):",
+       "apihelp-feedcontributions-param-month": "Айҙан башлап (һәм элегерәк):",
+       "apihelp-feedcontributions-param-deletedonly": "Юйылған төҙәтеүҙәрҙе генә күрһәтергә.",
        "apihelp-feedcontributions-param-toponly": "Һуңғы өлгө булған төҙәтеүҙәрҙе генә күрһәтергә",
+       "apihelp-feedcontributions-param-newonly": "Яңы бит яһаған төҙәтеүҙәрҙе генә күрһәтергә",
        "apihelp-feedcontributions-param-showsizediff": "Өлгәоәр араһыдағы күләм айырмаһын күрһәтергә",
+       "apihelp-feedcontributions-example-simple": "Ҡулланыусының өлөшөн күрһәтергә <kbd>Example</kbd>.",
+       "apihelp-feedrecentchanges-description": "Каналдың һуңғы үҙгәрештәрен кире ҡайтарырға.",
+       "apihelp-feedrecentchanges-param-feedformat": "Мәғлүмәттәр сығарыу форматы.",
+       "apihelp-feedrecentchanges-param-invert": "Һайланғандан башҡа исемдәр арауығы",
+       "apihelp-feedrecentchanges-param-limit": "Ҡайтарылған һөҙөмтәләрҙең максималь һаны.",
        "apihelp-feedrecentchanges-param-from": "Теге ваҡыттын булған үҙгәрештәрҙе күрһәтергә",
+       "apihelp-feedrecentchanges-param-hideminor": "Бәләкәй төҙәтеүҙәрҙе йәшерергә",
+       "apihelp-feedrecentchanges-param-hidebots": "Робот эшләгән төҙәтеүҙәрҙе йәшерергә",
+       "apihelp-feedrecentchanges-param-hideanons": "Аноним ҡатнашыусылар төҙәтеүен йәшерергә",
+       "apihelp-feedrecentchanges-param-hideliu": "Теркәлгән ҡатнашыусылар өлөшөн йәшерергә",
+       "apihelp-feedrecentchanges-param-hidepatrolled": "Патрулләнгән төҙәтеүҙәрҙе йәшерергә",
+       "apihelp-feedrecentchanges-param-hidemyself": "Ағымдаға ҡатнашыусы эшләгән үҙгәртеүҙәрҙе йәшерергә.",
+       "apihelp-feedrecentchanges-param-tagfilter": "Тэг буйынса һөҙгөс",
        "apihelp-feedrecentchanges-param-target": "Был биттән һылтанған биттәрҙә һуңғы үҙгәртеүҙәрҙе күрһәтергә",
+       "apihelp-feedrecentchanges-param-showlinkedto": "Киреһенсә, был биткә һылтанма яһаған биттәрҙәге үҙгәртеүҙәрҙе күрһәтергә",
+       "apihelp-feedrecentchanges-param-categories": "Бар категория биттәрендәге үҙгәрештәрҙе генә күрһәтергә",
+       "apihelp-feedrecentchanges-param-categories_any": "Был категориянан башҡа теләһә ҡайһы категориялар биттәрендәге үҙгәрештәрҙе генә күрһәтергә",
        "apihelp-feedrecentchanges-example-simple": "Һуңғы үҙгәртеүҙәрҙе күрһәтергә.",
-       "apihelp-feedwatchlist-example-default": "Күҙәтеү каналын күрһәтергә"
+       "apihelp-feedrecentchanges-example-30days": "30 көн арауығындағы һуңғы үҙгәртеүҙәрҙе күрһәтергә.",
+       "apihelp-feedwatchlist-description": "Күҙәтеү каналын ҡайтара",
+       "apihelp-feedwatchlist-param-feedformat": "Мәғлүмәттәр сығарыу форматы.",
+       "apihelp-feedwatchlist-param-hours": "Был моменттан һуң күп сәғәт эсендә биттәр исемлеге үҙгәртелгән.",
+       "apihelp-feedwatchlist-param-linktosections": "Мөмкин булһа, үҙгәртеүҙәр булған бүлеккә тура һылтанма.",
+       "apihelp-feedwatchlist-example-default": "Күҙәтеү каналын күрһәтергә",
+       "apihelp-feedwatchlist-example-all6hrs": "Күҙәтеү биттәрендәге һуңғы 6 сәғәт эсендәге барлыҡ үҙгәрештәрҙе күрһәтергә.",
+       "apihelp-filerevert-description": "Файлды иҫке версияға ҡайтарырға.",
+       "apihelp-filerevert-param-filename": "Префиксһыҙ файл исеме",
+       "apihelp-filerevert-param-comment": "Комментарий тейәргә",
+       "apihelp-filerevert-example-revert": "Кире <kbd>Wiki.png</kbd> юрауға <kbd>2011-03-05T15:27:40Z</kbd> ҡайтырға.",
+       "apihelp-help-description": "Күрһәтелгән модулдәр өсөн белешмәне тасуирлау.",
+       "apihelp-help-param-modules": " Белешмәләр тасуирлау өсөн (күрһәткестәр <var>action</var> һәм <var>format</var> дәүмәленә, йәки <kbd>main</kbd>). Модулдәрҙе a <kbd>+</kbd> ярҙамында күрһәтә алаһығыҙ.",
+       "apihelp-help-param-submodules": "Модуль исеменән субмодулдәр өсөн ярҙам индерә",
+       "apihelp-help-param-recursivesubmodules": "Рекурсив рәүешле субмодулдәр өсөн ярҙам индерә.",
+       "apihelp-help-param-helpformat": "Һөҙөмтәгә ярҙам форматы",
+       "apihelp-help-example-main": "Төп модулгә ярҙам",
+       "apihelp-help-example-submodules": "<kbd>action=query</kbd> һәм уның барлыҡ субмодулдәренә ярҙам итегеҙ",
+       "apihelp-help-example-recursive": "Бар белешмә бер бүлектә.",
+       "apihelp-help-example-help": "Модулдең үҙ ярҙамына ярҙам итеү",
+       "apihelp-help-example-query": "Подмодулдәрҙең ике һорауына ярҙам итергә.",
+       "apihelp-imagerotate-description": "Бер йәки бер нисә һүрәтте бороу.",
+       "apihelp-imagerotate-param-rotation": "Һүрәтте сәғәт йөрөшө буйынса нисә градусҡа борорға.",
+       "apihelp-imagerotate-example-simple": "<kbd>File:Example.png</kbd> на <kbd>90</kbd> градусҡа борорға.",
+       "apihelp-imagerotate-example-generator": "Бар һүрәттәрҙе лә <kbd>Category:Flip</kbd> на <kbd>180</kbd> градусҡа борорға.",
+       "apihelp-import-param-summary": "Йомғаҡты импортлау.",
+       "apihelp-import-param-xml": "Тултырылған XML-файл.",
+       "apihelp-import-param-interwikisource": "Интервики-импорт өсөн: Викинан импорт.",
+       "apihelp-import-param-interwikipage": "Интервики-импорт өсөн: битте импортлау.",
+       "apihelp-import-example-import": "Импортларға [[meta:Help:ParserFunctions]]  100 исемдәр арауығында тулы тарихы менән.",
+       "apihelp-login-param-name": "Ҡатнашыусы исеме.",
+       "apihelp-login-param-password": "Серһүҙ.",
+       "apihelp-login-param-domain": "Домен (мотлаҡ түгел).",
+       "apihelp-login-param-token": "Беренсе һорау ваҡытынла алынған логин маркер",
+       "apihelp-login-example-gettoken": "Системаға инеү маркерын алыу.",
+       "apihelp-login-example-login": "Танылыу.",
+       "apihelp-logout-description": "Сығырға һәм сессия мәғлүмәтен юйырға.",
+       "apihelp-logout-example-logout": "Ағымдағы ҡулланыусының киткән саҡта инеүе",
+       "apihelp-managetags-description": "Тегтарҙы үҙгәртеү менән бәйле идара итеү мәсьәләләрен хәл итеү",
+       "apihelp-managetags-param-reason": "\nБилдәне булдырыу, юйҙырыу, активациялау һәм деактивациялау өсөн мотлаҡ булмаған сәбәп",
+       "apihelp-mergehistory-description": "Үҙгәртеүҙәр тарихын берләштереү.",
+       "apihelp-mergehistory-param-from": "Тарихты берләштергән бит атамаһы. <var>$1fromid</var> менән бергә ҡуланыуы мөмкин түгел.",
+       "apihelp-mergehistory-param-fromid": "Тарихты берләштергән бит атамаһы. <var>$1fromid</var> менән бергә ҡуланыуы мөмкин түгел.",
+       "apihelp-mergehistory-param-to": "Тарихты берләштергән бит атамаһы. <var>$1fromid</var> менән бергә ҡуланыуы мөмкин түгел.",
+       "apihelp-mergehistory-param-toid": "Тарихты берләштергән бит атамаһы. <var>$1fromid</var> менән бергә ҡуланыуы мөмкин түгел.",
+       "apihelp-mergehistory-param-reason": "Тарихты берләштереү сәбәбе",
+       "apihelp-move-description": "Биттең исемен үҙгәртергә",
+       "apihelp-move-param-from": "Мөхәриррләү өсөн биттең исеме.<var>$1биттәрҙән</var> бергә файҙаланыу мөмкин түгел.",
+       "apihelp-move-param-fromid": "Бит идентифакторын мөхәррирләү өсөн биттәр.  <var>$1title</var> менән бергә ҡулланыла алмайҙар.",
+       "apihelp-move-param-to": "Исемен үҙгәртергә тейешле биттең баш һүҙе",
+       "apihelp-move-param-reason": "Үҙгәртеү сәбәбе",
+       "apihelp-move-param-movetalk": "Фекер алышыу бите булһа, исемен үҙгәртергә.",
+       "apihelp-move-param-movesubpages": "Мөмкин булһа, ярҙамсы биттең исемен үҙгәртергә.",
+       "apihelp-move-param-noredirect": "Йүнәлтеүҙәр ҡуймаҫҡа",
+       "apihelp-move-param-watch": "Ағымдағы ҡулланыусының күҙәтеү битенә бит һәм йүнәлтеү өҫтәргә.",
+       "apihelp-move-param-unwatch": "Ағымдағы ҡулланыусының күҙәтеү битендә битте һәм йүнәлтеүҙе юйырға.",
+       "apihelp-move-param-watchlist": "Ағымдағы ҡулланыусының теҙмәһенән битте һүҙһеҙ өҫтәргә йәки юйырға, һылтанмаларҙы файҙаланығыҙ йәки сәғәтте алмаштырмаҫҡа.",
+       "apihelp-move-param-ignorewarnings": "Бөтә иҫкәрмәләргә иғтибар итмәҫкә",
+       "apihelp-move-example-move": "Исемен үҙгәртергә <kbd>Badtitle</kbd>  <kbd>Goodtitle</kbd> йүнәлтеү ҡуймаҫҡа.",
+       "apihelp-opensearch-description": "OpenSearch протоколын ҡулланып вики эҙләү.",
+       "apihelp-opensearch-param-search": "Эҙләү юлы.",
+       "apihelp-opensearch-param-limit": "Ҡайтарылған һөҙөмтәләрҙең максималь һаны.",
+       "apihelp-opensearch-param-namespace": "Эҙләү өсөн исемдәр арауығы",
+       "apihelp-opensearch-param-format": "Мәғлүмәттәр сығарыу форматы.",
+       "apihelp-opensearch-example-te": "<KBD> Te </ KBD> менән башланған биттәрҙе табырға.",
+       "apihelp-options-param-reset": "Килешеү буйынса көйләүҙәргә күсергә.",
+       "apihelp-options-example-reset": "Бөтә көйләүҙәрҙе ташларға",
+       "apihelp-paraminfo-description": "API модуле тураһында мәғлүмәт алырға.",
+       "apihelp-paraminfo-param-helpformat": "Белешмә юлы форматы.",
+       "apihelp-parse-param-prop": "Ҡайһы мәғлүмәтте алырға:",
+       "apihelp-parse-paramvalue-prop-langlinks": "Вики-текстың синтаксик анализында тышҡы ссылкалар бирә.",
+       "apihelp-parse-paramvalue-prop-links": "Вики-текстың синтаксик анализында тышҡы ссылкалар бирә.",
+       "apihelp-parse-paramvalue-prop-templates": "Вики-текстың синтаксик анализ ҡалыбын бирә.",
+       "apihelp-parse-paramvalue-prop-images": "Вики-текстың синтаксик анализында һәрәттәр бирә.",
+       "apihelp-parse-paramvalue-prop-externallinks": "Вики-текстың синтаксик анализында тышҡы ссылкалар бирә.",
+       "apihelp-parse-paramvalue-prop-sections": "Вики-текстың синтаксик анализында секциялар бирә.",
+       "apihelp-parse-paramvalue-prop-revid": "Тикшерелгән биттәргә версиялар идентификаторын өҫтәй.",
+       "apihelp-parse-paramvalue-prop-displaytitle": "Вики-текстың синтаксик анализына исем ҡуя.",
+       "apihelp-parse-paramvalue-prop-headitems": "<код> & ЛТ -ҡа һалыу өсөн элементтар бирә; башы & GT; биттең </ код>",
+       "apihelp-parse-paramvalue-prop-headhtml": "Айырылған <код> & лт бирә; & баштары GТ; биттең </ код>.",
+       "apihelp-parse-paramvalue-prop-jsconfigvars": "Бит өсөн үҙенсәлекле  JavaScript үҙгәреүсән конфигурациялар бирә.",
+       "apihelp-parse-paramvalue-prop-encodedjsconfigvars": "JavaScriptтың JSON юлы һымаҡ үҙенсәлекле биттәренә  алышына торған конфигурация бирә.",
+       "apihelp-parse-paramvalue-prop-iwlinks": "Вики-текстың синтаксик анализында интервиктарға һылтанма бирә.",
+       "apihelp-parse-paramvalue-prop-wikitext": "Һығымта яҺау өсөн тәүге вики-тексты күрһәтә",
+       "apihelp-parse-paramvalue-prop-properties": "Вики-текстың синтаксик анализында билдәләнгән төрлө сифаттарҙы бирә.",
+       "apihelp-parse-paramvalue-prop-limitreportdata": "Структура һымаҡ итеп төплө отчет бирә. $1disablelimitreport</ вар> <алышыныусы> ҡуйылған ваҡытта бер ниндәй мәғлүмәт тә бирмәй.",
+       "apihelp-parse-paramvalue-prop-limitreporthtml": "Төплө отчеттың HTML версияһын бирә. <переменная>$1disablelimitreport </ вар> ҡуйылған булһа,бер мәғлүмәт тә бирмәй.",
+       "apihelp-parse-param-disablepp": "Урынына <var>$1disablelimitreport</var> ҡулланырға.",
+       "apihelp-parse-param-preview": "Алдан ҡарау режимында синтаксик анализ",
+       "apihelp-parse-example-page": "Битте тикшереү.",
+       "apihelp-parse-example-text": "Тикшереү: wikitext.",
+       "apihelp-parse-example-summary": "Һығымтаны тикшереү.",
+       "apihelp-patrol-param-rcid": "Яңы ID үҙгәртеүҙәрҙе патрулләү өсөн",
+       "apihelp-patrol-param-revid": "ID мөхәррирҙе патулләү",
+       "apihelp-patrol-param-tags": "Юйҙырылғандар журналындағы яҙмаларға  мөрәжәғәт итер өсөн, билдәләрҙе үҙгәртергә.",
+       "apihelp-patrol-example-rcid": "Һуңғы үҙгәрештәрҙе ҡарау.",
+       "apihelp-patrol-example-revid": "Яңынан ҡарау.",
+       "apihelp-protect-description": "Битте һаҡлау кимәлен үҙгәртергә",
+       "apihelp-protect-param-title": "Бит атамаһы. $1pageid менән бергә ҡулланылмай.",
+       "apihelp-protect-param-reason": "(ООН) һағы сәбәптәре.",
+       "apihelp-protect-param-tags": "Юйҙырылғандар журналындағы яҙмаларға  мөрәжәғәт итер өсөн, билдәләрҙе үҙгәртергә.",
+       "apihelp-protect-param-watchlist": "Ағымдағы ҡулланыусының теҙмәһенән битте һүҙһеҙ өҫтәргә йәки юйырға, һылтанмаларҙы файҙаланығыҙ йәки сәғәтте алмаштырмаҫҡа.",
+       "apihelp-protect-example-protect": "Битте һаҡларға.",
+       "apihelp-protect-example-unprotect": "<kbd>всех</kbd> өсөн сикләүҙәр ҡуйып,биттән һаҡлауҙы алырға.",
+       "apihelp-protect-example-unprotect2": "Бер ниндәй сикләүҙәр ҡуймай биттән һаҡлауҙы алырға.",
+       "apihelp-purge-param-forcelinkupdate": "Таблицалар бәйләнешен яңыртыу.",
+       "apihelp-purge-param-forcerecursivelinkupdate": "Һылтанманы һәм таблицаны яңыртығыҙ һәм был битте шаблон итеп ҡулланған башҡа биттәр өсөн һылтанмаларҙы ла яңыртығыҙ.",
+       "apihelp-query-param-list": "Ниндәй исемлекте ҡулланырға",
+       "apihelp-query-param-meta": "Ниндәй матамәғлүмәт ҡулланырға",
+       "apihelp-query+allcategories-description": "Бөтә категорияларҙы иҫәпләргә",
+       "apihelp-query+allcategories-param-from": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allcategories-param-to": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allcategories-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+allcategories-param-dir": "Сортлау йүнәлештәре.",
+       "apihelp-query+allcategories-param-limit": "Нисә категорияны кире ҡайтарырға",
+       "apihelp-query+allcategories-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+allcategories-paramvalue-prop-size": "Категорияларға биттәр һаны өҫтәү",
+       "apihelp-query+allcategories-example-size": "Биттәр һаны буйынса мәғлүмәтле категориялар исемлеге.",
+       "apihelp-query+allcategories-example-generator": "<kbd>исемлек</kbd> категориялар битенән мәғлүмәт алырға.",
+       "apihelp-query+alldeletedrevisions-description": "Бар мөхәррирләү исемлеге ҡулланыусы тарафынан юйылған.",
+       "apihelp-query+alldeletedrevisions-paraminfo-useronly": "<var>$3ҡулланыусының</var> менән генә ҡулланыла ала.",
+       "apihelp-query+alldeletedrevisions-param-end": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+alldeletedrevisions-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+alldeletedrevisions-param-user": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+alldeletedrevisions-param-namespace": "Бары тик был исемдәр арауығындағы биттәр исемлеге.",
+       "apihelp-query+alldeletedrevisions-example-ns-main": "Төп исемдәр арауығында юйылған тәүге 50 үҙгәртеү исемлеге.",
+       "apihelp-query+allfileusages-description": "Юйылғандар менән бергә барлыҡ файлдар тәртибе исемлеге.",
+       "apihelp-query+allfileusages-param-from": "Һанауҙы башлау өсөн файл атамаһы.",
+       "apihelp-query+allfileusages-param-to": "Һанауҙы туҡтатыу файлы атамаһы.",
+       "apihelp-query+allfileusages-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+allfileusages-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+allfileusages-paramvalue-prop-title": "Файл атамаһына ҡуша.",
+       "apihelp-query+allfileusages-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+allfileusages-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+allfileusages-example-unique": "Атамаларҙың уҙенсәлекле файлдары исемлеге.",
+       "apihelp-query+allfileusages-example-unique-generator": "Төшөп ҡалғандарҙы айырып, барлыҡ исем-һылтанмаларҙы алырға.",
+       "apihelp-query+allimages-description": "Бер-бер артлы бөтә образдарҙы һанап сығырға.",
+       "apihelp-query+allimages-param-sort": "Сортировкалау үҙенсәлектәре.",
+       "apihelp-query+allimages-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+allimages-param-minsize": "Һүрәттәр лимиты (байттарҙа).",
+       "apihelp-query+allimages-param-maxsize": "Бар һүрәттәр лимиты (байттарҙа).",
+       "apihelp-query+allimages-param-limit": "Кире ҡайтыу өсөн образдар һаны.",
+       "apihelp-query+allimages-example-B": "<kbd>Б</kbd> хәрефенән башланған файлдар исемлеген күрһәтергә.",
+       "apihelp-query+allimages-example-generator": "<kbd>Б</kbd> хәрефенән башланған файлдар исемлеген күрһәтергә.",
+       "apihelp-query+alllinks-description": "Бирелгән исемдәр арауығына йүнәлткән барлыҡ һылтанмаларҙы һанап сығырға.",
+       "apihelp-query+alllinks-param-from": "Һанауҙы башлау өсөн һылтанма атамаһы.",
+       "apihelp-query+alllinks-param-to": "Һанауҙы туҡтатыу һылтанмаһы атамаһы.",
+       "apihelp-query+alllinks-param-prefix": "Был мәғәнәнән башланған бәйләнешле бар атамаларҙы эҙләргә.",
+       "apihelp-query+alllinks-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+alllinks-paramvalue-prop-title": "Һылтанма атамаһын ҡуша.",
+       "apihelp-query+alllinks-param-namespace": "Һанау өсөн исемдәр арауығы.",
+       "apihelp-query+alllinks-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+alllinks-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+alllinks-example-unique": "Атамаларҙың уҙенсәлекле файлдары исемлеге.",
+       "apihelp-query+alllinks-example-unique-generator": "Төшөп ҡалғандарҙы айырып, барлыҡ исем-һылтанмаларҙы алырға.",
+       "apihelp-query+alllinks-example-generator": "Һылтанмалы биттәр бар.",
+       "apihelp-query+allmessages-description": "Был сайттан хәбәр ҡайтарыу.",
+       "apihelp-query+allmessages-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+allmessages-param-args": "Аргументтар Хәбәрҙәрҙә биреләсәк.",
+       "apihelp-query+allpages-param-from": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allpages-param-to": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allpages-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+allpages-param-namespace": "Һанау өсөн исемдәр арауығы.",
+       "apihelp-query+allpages-param-minsize": "Һүрәттәр лимиты (байттарҙа).",
+       "apihelp-query+allpages-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+allpages-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+allpages-example-B": "<kbd>Б</kbd> хәрефенән башланған файлдар исемлеген күрһәтергә.",
+       "apihelp-query+allpages-example-generator": "<kbd>Б</kbd> хәрефенән башланған файлдар исемлеген күрһәтергә.",
+       "apihelp-query+allredirects-param-from": "Һанауҙы туҡтатыу файлы атамаһы.",
+       "apihelp-query+allredirects-param-to": "Һанауҙы туҡтатыу файлы атамаһы.",
+       "apihelp-query+allredirects-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+allredirects-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+allredirects-param-namespace": "Һанау өсөн исемдәр арауығы.",
+       "apihelp-query+allredirects-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+allredirects-example-generator": "Һылтанмалы биттәр бар.",
+       "apihelp-query+allrevisions-param-start": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allrevisions-param-end": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allrevisions-param-user": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+allrevisions-param-excludeuser": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+alltransclusions-example-generator": "Һылтанмалы биттәр бар.",
+       "apihelp-query+allusers-param-from": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allusers-param-to": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+allusers-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+allusers-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+backlinks-param-title": "Мөхәриррләү өсөн биттең исеме.<var>$1биттәрҙән</var> бергә файҙаланыу  мөмкин түгел.",
+       "apihelp-query+backlinks-param-pageid": "Бит идентифакторын мөхәррирләү өсөн биттәр.  <var>$1title</var> менән бергә ҡулланыла алмайҙар",
+       "apihelp-query+backlinks-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+blocks-param-start": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+blocks-param-end": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+blocks-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+blocks-example-simple": "Берләшмә исемлеге",
+       "apihelp-query+categories-param-limit": "Нисә категорияны кире ҡайтарырға",
+       "apihelp-query+categories-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+categorymembers-param-pageid": "Бит идентифакторы юйылыу өсөн биттәр.  <var>$1title</var> менән бергә ҡулланыла алмайҙар",
+       "apihelp-query+categorymembers-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+categorymembers-param-limit": "Кире ҡайтарылған белдереүҙәрҙең иң күп һаны",
+       "apihelp-query+categorymembers-param-sort": "Сортҡа бүлеү үҙенсәлеге",
+       "apihelp-query+contributors-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+deletedrevisions-param-user": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+deletedrevisions-param-excludeuser": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+deletedrevs-param-start": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+deletedrevs-param-end": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+deletedrevs-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+deletedrevs-param-user": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+duplicatefiles-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+duplicatefiles-example-generated": "Поиск дубликатов всех файлов.",
+       "apihelp-query+embeddedin-param-title": "Мөхәриррләү өсөн биттең исеме.<var>$1биттәрҙән</var> бергә файҙаланыу  мөмкин түгел.",
+       "apihelp-query+embeddedin-param-pageid": "Бит идентифакторын мөхәррирләү өсөн биттәр.  <var>$1title</var> менән бергә ҡулланыла алмайҙар",
+       "apihelp-query+embeddedin-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+embeddedin-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+exturlusage-param-limit": "Күпме һылтанмаларҙы кире ҡайтарырға.",
+       "apihelp-query+filearchive-param-from": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+filearchive-param-to": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+filearchive-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+filearchive-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+fileusage-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+fileusage-param-limit": "Күпме һылтанмаларҙы кире ҡайтарырға.",
+       "apihelp-query+imageinfo-param-prop": "Ҡайһы мәғлүмәтте алырға:",
+       "apihelp-query+imageinfo-paramvalue-prop-mediatype": "Файл атамаһына ҡуша.",
+       "apihelp-query+images-param-limit": "Күпме һылтанмаларҙы кире ҡайтарырға.",
+       "apihelp-query+images-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+imageusage-param-title": "Мөхәриррләү өсөн биттең исеме.<var>$1биттәрҙән</var> бергә файҙаланыу  мөмкин түгел.",
+       "apihelp-query+imageusage-param-pageid": "Бит идентифакторын мөхәррирләү өсөн биттәр.  <var>$1title</var> менән бергә ҡулланыла алмайҙар",
+       "apihelp-query+imageusage-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+info-paramvalue-prop-protection": "Битте һаҡлау кимәлен үҙгәртергә",
+       "apihelp-query+iwbacklinks-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+iwbacklinks-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+iwbacklinks-paramvalue-prop-iwtitle": "Файл атамаһына ҡуша.",
+       "apihelp-query+iwlinks-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+langbacklinks-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+langbacklinks-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+links-param-limit": "Күпме һылтанмаларҙы кире ҡайтарырға.",
+       "apihelp-query+links-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+linkshere-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+logevents-description": "Журналдарҙан ваҡиға алыу.",
+       "apihelp-query+logevents-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+logevents-param-start": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+logevents-param-end": "Иҫәп күсереү тамамланған ваҡыт билдәһе",
+       "apihelp-query+logevents-example-simple": " Һуңғы теркәлгән ваҡиғалар исемлеге.",
+       "apihelp-query+pagepropnames-param-limit": "Кире ҡайтарылған белдереүҙәрҙең иң күп һаны",
+       "apihelp-query+pagepropnames-example-simple": "Тәүге 10 исем сифатын алыу.",
+       "apihelp-query+pageswithprop-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+pageswithprop-param-limit": "Кире ҡайтарылған белдереүҙәрҙең иң күп һаны",
+       "apihelp-query+pageswithprop-param-dir": "Ниндәй йүнәлешкә айырырға",
+       "apihelp-query+prefixsearch-param-search": "Эҙләү юлы.",
+       "apihelp-query+prefixsearch-param-namespace": "Эҙләү өсөн исемдәр арауығы",
+       "apihelp-query+prefixsearch-param-limit": "Ҡайтарылған һөҙөмтәләрҙең максималь һаны.",
+       "apihelp-query+prefixsearch-param-offset": "Төшөрөп ҡалдырыу өсөн һөҙөмтә иҫәбе",
+       "apihelp-query+protectedtitles-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+protectedtitles-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+querypage-param-limit": "Төшөрөп ҡалдырыу өсөн һөҙөмтә иҫәбе",
+       "apihelp-query+recentchanges-param-start": "Иҫәп күсереү башланған ваҡыт билдәһе",
+       "apihelp-query+recentchanges-param-end": "Иҫәп күсереү тамамланған ваҡыт билдәһе",
+       "apihelp-query+recentchanges-param-user": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+recentchanges-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+recentchanges-param-type": "Ниндәй төрҙәр үҙгәртеүҙе күрһәтергө",
+       "apihelp-query+recentchanges-example-simple": "Һуңғы үҙгәртеүҙәрҙе күрһәтергә.",
+       "apihelp-query+redirects-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+redirects-param-limit": "Күпме һылтанмаларҙы кире ҡайтарырға.",
+       "apihelp-query+revisions-example-last5": "Һуңғы 5 <kbd>Main Page</kbd> версияны  алырға.",
+       "apihelp-query+revisions-example-first5": "Тәүге 5 <kbd>Main Page</kbd> версияны алырға.",
+       "apihelp-query+search-param-info": "Ниндәй матамәғлүмәт ҡулланырға",
+       "apihelp-query+search-param-prop": "Ниндәй үҙенсәлекте ҡайтарырға",
+       "apihelp-query+search-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+tags-description": "Үҙгәртелгән тамғалар исемлеге.",
+       "apihelp-query+tags-param-limit": "Кире ҡайтарылған белдереүҙәрҙең иң күп һаны",
+       "apihelp-query+tags-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+tags-example-simple": "Аңлайышлы тамғалар бите",
+       "apihelp-query+templates-param-limit": "Күпме һылтанмаларҙы кире ҡайтарырға.",
+       "apihelp-query+templates-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+transcludedin-param-prop": "Ниндәй үҙенсәлек алырға:",
+       "apihelp-query+transcludedin-param-limit": "Күпме һылтанмаларҙы кире ҡайтарырға.",
+       "apihelp-query+usercontribs-description": "Ҡулланыусының бөтә төҙәтеүҙәрен алыу",
+       "apihelp-query+usercontribs-param-limit": "Кире ҡайтарылған белдереүҙәрҙең иң күп һаны"
 }
index 3108e5b..3b5201a 100644 (file)
@@ -1,7 +1,8 @@
 {
        "@metadata": {
                "authors": [
-                       "Red Winged Duck"
+                       "Red Winged Duck",
+                       "Renessaince"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Дакумэнтацыя]]\n* [[mw:API:FAQ|Частыя пытаньні]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Сьпіс рассылкі]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-аб’явы]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Памылкі і запыты]\n</div>\n<strong>Статус:</strong> усе магчымасьці на гэтай старонцы павінны працаваць, але API знаходзіцца ў актыўнай распрацоўцы і можа зьмяняцца ў любы момант. Падпісвайцеся на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ рассылку mediawiki-api-announce] дзеля паведамленьняў пра абнаўленьні.\n\n<strong>Памылковыя запыты:</strong> калі да API дасылаюцца памылковыя запыты, HTTP-загаловак будзе дасланы з ключом «MediaWiki-API-Error», а потым значэньне загалоўку і код памылкі будуць выстаўленыя на аднолькавае значэньне. Дзеля дадатковай інфармацыі глядзіце [[mw:API:Errors_and_warnings|API: Памылкі і папярэджаньні]].\n\n<strong>Тэставаньне:</strong> для зручнасьці праверкі API-запытаў, глядзіце [[Special:ApiSandbox]].",
@@ -51,5 +52,8 @@
        "apihelp-createaccount-param-reason": "Неабавязковая прычына стварэньня рахунку, якая будзе запісаная ў журнал.",
        "apihelp-createaccount-param-language": "Моўны код, які будзе выстаўлены ўдзельніку па змоўчаньні (неабавязкова, па змоўчаньні мова зьместу).",
        "apihelp-createaccount-example-pass": "Стварэньне ўдзельніка <kbd>testuser</kbd> з паролем <kbd>test123</kbd>.",
-       "apihelp-createaccount-example-mail": "Стварэньне ўдзельніка <kbd>testmailuser</kbd> і адпраўка выпадковага паролю электроннай поштай."
+       "apihelp-createaccount-example-mail": "Стварэньне ўдзельніка <kbd>testmailuser</kbd> і адпраўка выпадковага паролю электроннай поштай.",
+       "apihelp-query+transcludedin-paramvalue-prop-title": "Назва кожнай старонкі.",
+       "apihelp-query+transcludedin-param-limit": "Колькі вяртаць.",
+       "apihelp-query+userinfo-paramvalue-prop-acceptlang": "Дублюе загаловак <code>Accept-Language</code>, адасланы кліентам у структураваным фармаце."
 }
index b8be085..c93d8ba 100644 (file)
@@ -1,10 +1,14 @@
 {
        "@metadata": {
                "authors": [
-                       "Aftabuzzaman"
+                       "Aftabuzzaman",
+                       "Bodhisattwa"
                ]
        },
+       "apihelp-block-description": "ব্যবহারকারীকে বাধা দিন।",
        "apihelp-createaccount-param-name": "ব্যবহারকারী নাম।",
+       "apihelp-delete-description": "একটি পাতা মুছে ফেলুন।",
+       "apihelp-delete-example-simple": "<kbd>প্রধান পাতা</kbd> মুছে ফেলুন।",
        "apihelp-edit-param-minor": "অনুল্লেখ্য সম্পাদনা।",
        "apihelp-login-example-login": "প্রবেশ"
 }
index b6ddc88..fbddc8d 100644 (file)
@@ -8,10 +8,11 @@
                        "Cvanca",
                        "Utar",
                        "Macofe",
-                       "Danny B."
+                       "Danny B.",
+                       "LordMsz"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Dokumentace]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-mailová konference]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Oznámení k API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Chyby a požadavky]\n</div>\n<strong>Stav:</strong> Všechny funkce uvedené na této stránce by měly fungovat, ale API se stále aktivně vyvíjí a může se kdykoli změnit. Upozornění na změny získáte přihlášením se k [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-mailové konferenci mediawiki-api-announce].\n\n<strong>Chybné požadavky:</strong> Pokud jsou do API zaslány chybné požadavky, bude vrácena HTTP hlavička s klíčem „MediaWiki-API-Error“ a hodnota této hlavičky a chybový kód budou nastaveny na stejnou hodnotu. Více informací najdete [[mw:API:Errors_and_warnings|v dokumentaci]].",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Dokumentace]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-mailová konference]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Oznámení k API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Chyby a požadavky]\n</div>\n<strong>Stav:</strong> Všechny funkce uvedené na této stránce by měly fungovat, ale API se stále aktivně vyvíjí a může se kdykoli změnit. Upozornění na změny získáte přihlášením se k [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-mailové konferenci mediawiki-api-announce].\n\n<strong>Chybné požadavky:</strong> Pokud jsou do API zaslány chybné požadavky, bude vrácena HTTP hlavička s klíčem „MediaWiki-API-Error“ a hodnota této hlavičky a chybový kód budou nastaveny na stejnou hodnotu. Více informací najdete [[mw:API:Errors_and_warnings|v dokumentaci]].\n\n<strong>Testování:</strong> Pro jednoduché testování požadavků na API zkuste [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Která akce se má provést.",
        "apihelp-main-param-format": "Formát výstupu.",
        "apihelp-main-param-maxlag": "Maximální zpoždění lze použít, když je MediaWiki nainstalováno na cluster s replikovanou databází. Abyste se vyhnuli zhoršování už tak špatného replikačního zpoždění, můžete tímto parametrem nechat klienta čekat, dokud replikační zpoždění neklesne pod uvedenou hodnotu. V případě příliš vysokého zpoždění se vrátí chybový kód „<samp>maxlag</samp>“ s hlášením typu „<samp>Waiting for $host: $lag seconds lagged</samp>“.<br />Více informací najdete v [[mw:Manual:Maxlag_parameter|příručce]].",
        "apihelp-help-example-query": "Nápověda pro dva podmoduly query",
        "apihelp-imagerotate-description": "Otočit jeden nebo více obrázků.",
        "apihelp-imagerotate-example-generator": "Otočit všechny obrázky v <kbd>Category:Flip</kbd> o <kbd>180</kbd> stupňů.",
-       "apihelp-import-param-summary": "Import shrnutí.",
+       "apihelp-import-param-summary": "Shrnutí do protokolovacího záznamu importu.",
        "apihelp-import-param-xml": "Nahraný XML soubor.",
        "apihelp-import-param-namespace": "Importovat do tohoto jmenného prostoru. Nelze používat současně s parametrem <var>$1rootpage</var>.",
        "apihelp-import-param-rootpage": "Importovat jako podstránku k této stránce. Nelze používat současně s parametrem <var>$1namespace</var>.",
index 5b67c1f..5402ab4 100644 (file)
        "apihelp-imagerotate-example-simple": "<kbd>Datei:Beispiel.png</kbd> um <kbd>90</kbd> Grad drehen.",
        "apihelp-imagerotate-example-generator": "Alle Bilder in der <kbd>Kategorie:Flip</kbd> um <kbd>180</kbd> Grad drehen.",
        "apihelp-import-description": "Importiert eine Seite aus einem anderen Wiki oder von einer XML-Datei.\n\nBitte beachte, dass der HTTP-POST-Vorgang als Dateiupload ausgeführt werden muss (z.B. durch multipart/form-data), um eine Datei über den <var>xml</var>-Parameter zu senden.",
-       "apihelp-import-param-summary": "Import-Zusammenfassung.",
+       "apihelp-import-param-summary": "Importzusammenfassung des Logbucheintrags.",
        "apihelp-import-param-xml": "Hochgeladene XML-Datei.",
        "apihelp-import-param-interwikisource": "Für Interwiki-Importe: Wiki, von dem importiert werden soll.",
        "apihelp-import-param-interwikipage": "Für Interwiki-Importe: zu importierende Seite.",
        "apihelp-purge-example-simple": "Purgt die <kbd>Main Page</kbd> und die <kbd>API</kbd>-Seite.",
        "apihelp-purge-example-generator": "Purgt die ersten 10 Seiten des Hauptnamensraums.",
        "apihelp-query-description": "Bezieht Daten von und über MediaWiki.\n\nAlle Änderungsvorgänge müssen unter Angabe eines Tokens ablaufen, um Missbrauch durch böswillige Anwendungen vorzubeugen.",
-       "apihelp-query-param-prop": "Zurückzuliefernde Eigenschaften der abgefragten Seiten.",
+       "apihelp-query-param-prop": "Zurückzugebende Eigenschaften der abgefragten Seiten.",
        "apihelp-query-param-list": "Welche Listen abgerufen werden sollen.",
        "apihelp-query-param-meta": "Zurückzugebende Metadaten.",
        "apihelp-query-param-indexpageids": "Schließt einen zusätzlichen pageids-Abschnitt mit allen zurückgegebenen Seitenkennungen ein.",
        "apihelp-query+alllinks-example-generator": "Ruft Seiten ab welche die Verknüpfungen beinhalten.",
        "apihelp-query+allmessages-description": "Gibt Nachrichten von dieser Website zurück.",
        "apihelp-query+allmessages-param-messages": "Welche Nachrichten ausgegeben werden sollen. <kbd>*</kbd> (Vorgabe) bedeutet alle Nachrichten.",
-       "apihelp-query+allmessages-param-prop": "Welche Eigenschaften abgerufen werden sollen.",
+       "apihelp-query+allmessages-param-prop": "Zurückzugebende Eigenschaften.",
        "apihelp-query+allmessages-param-enableparser": "Setzen, um den Parser zu aktivieren. Dies wird den Wikitext der Nachricht vorverarbeiten (magische Worte ersetzen, Vorlagen berücksichtigen, usw.).",
        "apihelp-query+allmessages-param-nocontent": "Wenn gesetzt, füge nicht den Inhalt der Nachricht der Ausgabe hinzu.",
        "apihelp-query+allmessages-param-includelocal": "Schließt auch lokale Nachrichten ein. Zum Beispiel Nachrichten die es nicht in der Software gibt, die es aber als MediaWiki: - Seite gibt. Dies listet alle MediaWiki: - Seiten auf. Daher werden auch diejenigen aufgelistet, die eigentlich keine Nachrichten sind, wie [[MediaWiki:Common.js|Common.js]].",
        "apihelp-query+blocks-example-simple": "Sperren auflisten",
        "apihelp-query+blocks-example-users": "Listet Sperren der Benutzer <kbd>Alice</kbd> und <kbd>Bob</kbd> auf.",
        "apihelp-query+categories-description": "Liste alle Kategorien auf, zu denen die Seiten gehören.",
-       "apihelp-query+categories-param-prop": "Welche zusätzlichen Eigenschaften für jede Kategorie abrufen:",
+       "apihelp-query+categories-param-prop": "Zusätzlich zurückzugebende Eigenschaften jeder Kategorie:",
        "apihelp-query+categories-paramvalue-prop-timestamp": "Fügt einen Zeitstempel wann die Kategorie angelegt wurde hinzu.",
        "apihelp-query+categories-param-show": "Welche Art von Kategorien gezeigt werden soll.",
        "apihelp-query+categories-param-limit": "Wie viele Kategorien zurückgegeben werden sollen.",
        "apihelp-query+imageusage-param-redirect": "Falls die verweisende Seite eine Weiterleitung ist, finde alle Seiten, die ebenfalls auf diese Weiterleitung verweisen. Die maximale Grenze wird halbiert.",
        "apihelp-query+imageusage-example-simple": "Zeige Seiten, die [[:File:Albert Einstein Head.jpg]] verwenden.",
        "apihelp-query+info-description": "Ruft Basisinformationen über die Seite ab.",
-       "apihelp-query+info-param-prop": "Welche zusätzlichen Eigenschaften abgerufen werden sollen:",
+       "apihelp-query+info-param-prop": "Zusätzlich zurückzugebende Eigenschaften:",
        "apihelp-query+info-paramvalue-prop-protection": "Liste die Schutzstufe jeder Seite auf.",
        "apihelp-query+info-paramvalue-prop-talkid": "Die Seitenkennung der Diskussionsseite für jede Nicht-Diskussionsseite.",
        "apihelp-query+info-paramvalue-prop-watched": "Liste den Überwachungszustand jeder Seite auf.",
        "apihelp-query+info-paramvalue-prop-displaytitle": "Gibt die Art und Weise an, in der der Seitentitel tatsächlich angezeigt wird.",
        "apihelp-query+info-param-testactions": "Überprüft, ob der aktuelle Benutzer gewisse Aktionen auf der Seite ausführen kann.",
        "apihelp-query+iwbacklinks-param-prefix": "Präfix für das Interwiki.",
+       "apihelp-query+iwbacklinks-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+iwbacklinks-paramvalue-prop-iwprefix": "Ergänzt das Präfix des Interwikis.",
        "apihelp-query+iwbacklinks-paramvalue-prop-iwtitle": "Ergänzt den Titel des Interwikis.",
        "apihelp-query+iwbacklinks-param-dir": "Die Auflistungsrichtung.",
+       "apihelp-query+iwlinks-param-prop": "Zusätzlich zurückzugebende Eigenschaften jedes Interlanguage-Links:",
        "apihelp-query+iwlinks-paramvalue-prop-url": "Ergänzt die vollständige URL.",
        "apihelp-query+iwlinks-param-limit": "Wie viele Interwiki-Links zurückgegeben werden sollen.",
        "apihelp-query+iwlinks-param-prefix": "Gibt nur Interwiki-Links mit diesem Präfix zurück.",
        "apihelp-query+iwlinks-param-dir": "Die Auflistungsrichtung.",
        "apihelp-query+langbacklinks-param-limit": "Wie viele Gesamtseiten zurückgegeben werden sollen.",
+       "apihelp-query+langbacklinks-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+langbacklinks-param-dir": "Die Auflistungsrichtung.",
        "apihelp-query+langbacklinks-example-simple": "Ruft Seiten ab, die auf [[:fr:Test]] verlinken.",
        "apihelp-query+langlinks-param-limit": "Wie viele Sprachlinks zurückgegeben werden sollen.",
+       "apihelp-query+langlinks-param-prop": "Zusätzlich zurückzugebende Eigenschaften jedes Interlanguage-Links:",
        "apihelp-query+langlinks-paramvalue-prop-url": "Ergänzt die vollständige URL.",
        "apihelp-query+langlinks-param-dir": "Die Auflistungsrichtung.",
        "apihelp-query+links-param-limit": "Wie viele Links zurückgegeben werden sollen.",
        "apihelp-query+links-param-dir": "Die Auflistungsrichtung.",
        "apihelp-query+links-example-simple": "Links von der <kbd>Hauptseite</kbd> abrufen",
        "apihelp-query+linkshere-description": "Alle Seiten finden, die auf die angegebenen Seiten verlinken.",
+       "apihelp-query+linkshere-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+linkshere-paramvalue-prop-pageid": "Die Seitenkennung jeder Seite.",
        "apihelp-query+linkshere-paramvalue-prop-title": "Titel jeder Seite.",
        "apihelp-query+logevents-description": "Ereignisse von den Logbüchern abrufen.",
+       "apihelp-query+logevents-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+logevents-paramvalue-prop-type": "Ergänzt den Typ des Logbuchereignisses.",
        "apihelp-query+logevents-paramvalue-prop-comment": "Ergänzt den Kommentar des Logbuchereignisses.",
        "apihelp-query+logevents-example-simple": "Listet die letzten Logbuch-Ereignisse auf.",
        "apihelp-query+pageswithprop-param-limit": "Die maximale Anzahl zurückzugebender Seiten.",
        "apihelp-query+prefixsearch-param-search": "Such-Zeichenfolge.",
        "apihelp-query+prefixsearch-param-offset": "Anzahl der zu überspringenden Ergebnisse.",
+       "apihelp-query+protectedtitles-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+querypage-param-limit": "Anzahl der zurückzugebenden Ergebnisse.",
        "apihelp-query+recentchanges-description": "Listet die letzten Änderungen auf.",
+       "apihelp-query+recentchanges-param-user": "Listet nur Änderungen von diesem Benutzer auf.",
+       "apihelp-query+recentchanges-param-excludeuser": "Listet keine Änderungen von diesem Benutzer auf.",
+       "apihelp-query+recentchanges-param-tag": "Listet nur Änderungen auf, die mit dieser Markierung markiert sind.",
+       "apihelp-query+recentchanges-paramvalue-prop-flags": "Ergänzt Markierungen für die Bearbeitung.",
        "apihelp-query+recentchanges-paramvalue-prop-timestamp": "Ergänzt den Zeitstempel für die Bearbeitung.",
+       "apihelp-query+recentchanges-paramvalue-prop-title": "Ergänzt den Seitentitel der Bearbeitung.",
        "apihelp-query+recentchanges-paramvalue-prop-tags": "Listet Markierungen für den Eintrag auf.",
        "apihelp-query+recentchanges-example-simple": "Listet die letzten Änderungen auf.",
+       "apihelp-query+redirects-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+redirects-paramvalue-prop-pageid": "Seitenkennung einer jeden Weiterleitung.",
        "apihelp-query+redirects-paramvalue-prop-title": "Titel einer jeden Weiterleitung.",
+       "apihelp-query+redirects-param-limit": "Wie viele Weiterleitungen zurückgegeben werden sollen.",
+       "apihelp-query+revisions-param-tag": "Listet nur Versionen auf, die mit dieser Markierung markiert sind.",
+       "apihelp-query+revisions+base-param-prop": "Zurückzugebende Eigenschaften jeder Version:",
        "apihelp-query+revisions+base-paramvalue-prop-ids": "Die Kennung der Version.",
        "apihelp-query+revisions+base-paramvalue-prop-flags": "Versionsmarkierungen (klein).",
        "apihelp-query+revisions+base-paramvalue-prop-timestamp": "Der Zeitstempel der Version.",
        "apihelp-query+search-example-text": "Texte nach <kbd>meaning</kbd> durchsuchen.",
        "apihelp-query+siteinfo-example-simple": "Websiteinformationen abrufen",
        "apihelp-query+tags-description": "Änderungs-Tags auflisten.",
+       "apihelp-query+tags-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+tags-example-simple": "Verfügbare Tags auflisten",
        "apihelp-query+templates-param-dir": "Die Auflistungsrichtung.",
+       "apihelp-query+transcludedin-param-prop": "Zurückzugebende Eigenschaften:",
        "apihelp-query+usercontribs-description": "Alle Bearbeitungen von einem Benutzer abrufen.",
        "apihelp-query+usercontribs-param-limit": "Die maximale Anzahl der zurückzugebenden Beiträge.",
        "apihelp-query+usercontribs-param-start": "Der zurückzugebende Start-Zeitstempel.",
        "apihelp-query+users-paramvalue-prop-rights": "Listet alle Rechte auf, die jeder Benutzer hat.",
        "apihelp-query+users-paramvalue-prop-editcount": "Ergänzt den Bearbeitungszähler des Benutzers.",
        "apihelp-query+users-example-simple": "Gibt Informationen für den Benutzer <kbd>Example</kbd> zurück.",
+       "apihelp-query+watchlist-param-prop": "Zusätzlich zurückzugebende Eigenschaften:",
        "apihelp-query+watchlist-paramvalue-prop-user": "Ergänzt den Benutzer, der die Bearbeitung ausgeführt hat.",
        "apihelp-query+watchlist-paramvalue-prop-userid": "Ergänzt die Kennung des Benutzers, der die Bearbeitung ausgeführt hat.",
        "apihelp-query+watchlist-paramvalue-prop-comment": "Ergänzt den Kommentar der Bearbeitung.",
        "apihelp-query+watchlist-paramvalue-prop-sizes": "Ergänzt die alten und neuen Längen der Seite.",
        "apihelp-query+watchlist-paramvalue-type-new": "Seitenerstellungen.",
        "apihelp-query+watchlist-paramvalue-type-log": "Logbucheinträge.",
+       "apihelp-query+watchlistraw-param-prop": "Zusätzlich zurückzugebende Eigenschaften:",
        "apihelp-rsd-description": "Ein RSD-Schema (Really Simple Discovery) exportieren.",
        "apihelp-rsd-example-simple": "Das RSD-Schema exportieren",
        "apihelp-setnotificationtimestamp-param-entirewatchlist": "An allen beobachteten Seiten arbeiten.",
index 2d1542e..2b23da0 100644 (file)
@@ -20,7 +20,7 @@
        "apihelp-main-param-uselang": "Language to use for message translations. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> with <kbd>siprop=languages</kbd> returns a list of language codes, or specify <kbd>user</kbd> to use the current user's language preference, or specify <kbd>content</kbd> to use this wiki's content language.",
 
        "apihelp-block-description": "Block a user.",
-       "apihelp-block-param-user": "Username, IP address, or IP range to block.",
+       "apihelp-block-param-user": "Username, IP address, or IP address range to block.",
        "apihelp-block-param-expiry": "Expiry time. May be relative (e.g. <kbd>5 months</kbd> or <kbd>2 weeks</kbd>) or absolute (e.g. <kbd>2014-09-18T12:34:56Z</kbd>). If set to <kbd>infinite</kbd>, <kbd>indefinite</kbd>, or <kbd>never</kbd>, the block will never expire.",
        "apihelp-block-param-reason": "Reason for block.",
        "apihelp-block-param-anononly": "Block anonymous users only (i.e. disable anonymous edits for this IP address).",
        "apihelp-imagerotate-example-generator": "Rotate all images in <kbd>Category:Flip</kbd> by <kbd>180</kbd> degrees.",
 
        "apihelp-import-description": "Import a page from another wiki, or from an XML file.\n\nNote that the HTTP POST must be done as a file upload (i.e. using multipart/form-data) when sending a file for the <var>xml</var> parameter.",
-       "apihelp-import-param-summary": "Import summary.",
+       "apihelp-import-param-summary": "Log entry import summary.",
        "apihelp-import-param-xml": "Uploaded XML file.",
        "apihelp-import-param-interwikisource": "For interwiki imports: wiki to import from.",
        "apihelp-import-param-interwikipage": "For interwiki imports: page to import.",
        "apihelp-query+blocks-param-end": "The timestamp to stop enumerating at.",
        "apihelp-query+blocks-param-ids": "List of block IDs to list (optional).",
        "apihelp-query+blocks-param-users": "List of users to search for (optional).",
-       "apihelp-query+blocks-param-ip": "Get all blocks applying to this IP or CIDR range, including range blocks.\nCannot be used together with <var>$3users</var>. CIDR ranges broader than IPv4/$1 or IPv6/$2 are not accepted.",
+       "apihelp-query+blocks-param-ip": "Get all blocks applying to this IP address or CIDR range, including range blocks.\nCannot be used together with <var>$3users</var>. CIDR ranges broader than IPv4/$1 or IPv6/$2 are not accepted.",
        "apihelp-query+blocks-param-limit": "The maximum number of blocks to list.",
        "apihelp-query+blocks-param-prop": "Which properties to get:",
        "apihelp-query+blocks-paramvalue-prop-id": "Adds the ID of the block.",
 
        "apihelp-unblock-description": "Unblock a user.",
        "apihelp-unblock-param-id": "ID of the block to unblock (obtained through <kbd>list=blocks</kbd>). Cannot be used together with <var>$1user</var>.",
-       "apihelp-unblock-param-user": "Username, IP address or IP range to unblock. Cannot be used together with <var>$1id</var>.",
+       "apihelp-unblock-param-user": "Username, IP address or IP address range to unblock. Cannot be used together with <var>$1id</var>.",
        "apihelp-unblock-param-reason": "Reason for unblock.",
        "apihelp-unblock-param-tags": "Change tags to apply to the entry in the block log.",
        "apihelp-unblock-example-id": "Unblock block ID #<kbd>105</kbd>.",
diff --git a/includes/api/i18n/eo.json b/includes/api/i18n/eo.json
new file mode 100644 (file)
index 0000000..45060c2
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Robin van der Vliet"
+               ]
+       },
+       "apihelp-createaccount-param-name": "Uzantnomo.",
+       "apihelp-delete-description": "Forigi paĝon.",
+       "apihelp-edit-example-edit": "Redakti paĝon.",
+       "apihelp-login-param-name": "Uzantnomo.",
+       "apihelp-login-param-password": "Pasvorto.",
+       "apihelp-login-example-login": "Ensaluti."
+}
index 2570bc1..bbb8656 100644 (file)
                        "Chris TR",
                        "Ncontinanza",
                        "Poco a poco",
-                       "YoViajo"
+                       "YoViajo",
+                       "Eloy",
+                       "AlvaroMolina",
+                       "Ciencia Al Poder"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentación]]\n* [[mw:API:FAQ|Preguntas frecuentes]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de correos]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API de anuncios]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Errores y peticiones]\n</div>\n<strong>Estado:</strong> Todas las características que se muestran en esta página debería funcionar, pero la API aún está en desarrollo activo y puede cambiar en cualquier momento. Suscríbete a [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la lista de correo de mediawiki-api-announce] para estar al día de las actualizaciones.\n\n<strong>Solicitudes erróneas:</strong> Cuando se envían solicitudes erróneas a la API, se envía un encabezado HTTP con la clave \"MediaWiki-API-Error\" y ambos valores, del encabezado y el código de error, se establecerán en el mismo valor. Para más información, véase [[mw:API:Errors_and_warnings|API: Errores y advertencias]].\n\n<strong>Pruebas:</strong> para facilitar las pruebas de solicitudes a la API, consulta [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Qué acción se realizará.",
        "apihelp-main-param-format": "El formato de la salida.",
-       "apihelp-main-param-smaxage": "Establece el encabezado <code>s-maxage</code> durante estos segundos. Los errores nunca se almacenan en caché.",
-       "apihelp-main-param-maxage": "Establece el encabezado <code>max-age</code> durante estos segundos. Los errores nunca se almacenan en caché.",
+       "apihelp-main-param-smaxage": "Establece el encabezado HTTP <code>s-maxage</code> de control de caché a esta cantidad de segundos. Los errores nunca se almacenan en caché.",
+       "apihelp-main-param-maxage": "Establece el encabezado HTTP <code>max-age</code> de control de caché a esta cantidad de segundos. Los errores nunca se almacenan en caché.",
        "apihelp-main-param-assert": "Comprobar que el usuario haya iniciado sesión si el valor es <kbd>user</kbd> o si tiene el permiso de bot si es <kbd>bot</kbd>.",
        "apihelp-main-param-requestid": "Cualquier valor dado aquí se incluirá en la respuesta. Se puede utilizar para distinguir solicitudes.",
        "apihelp-main-param-servedby": "Incluir el nombre del host que ha servido la solicitud en los resultados.",
        "apihelp-main-param-curtimestamp": "Incluir la marca de tiempo actual en el resultado.",
+       "apihelp-main-param-origin": "Cuando se accede a la API usando una petición AJAX de distinto dominio (CORS), establece este valor al dominio de origen. Debe ser incluido en cualquier petición pre-vuelo, y por lo tanto debe ser parte de la URI de la petición (no del cuerpo POST). Debe coincidir exactamente con uno de los orígenes de la cabecera <code>Origin</code>, por lo que debería ser algo como <kbd>https://en.wikipedia.org</kbd> o <kbd>https://meta.wikimedia.org</kbd>. Si este parámetro no coincide con la cabecera <code>Origin</code>, se devolverá una respuesta 403.\nSi este parámetro coincide con la cabecera <code>Origin</code> y el origen está en lista blanca, se creará una cabecera <code>Access-Control-Allow-Origin</code>.",
        "apihelp-main-param-uselang": "El idioma que se usará para las traducciones de mensajes. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> con <kbd>siprop=languages</kbd> devuelve una lista de códigos de idiomas, o especifica <kbd>user</kbd> para usar la preferencia de idioma del usuario actual, o especifica <kbd>content</kbd> para usar el idioma de contenido de este wiki.",
        "apihelp-block-description": "Bloquear a un usuario.",
        "apihelp-block-param-user": "El nombre de usuario, dirección IP o intervalo de IP que quieres bloquear.",
-       "apihelp-block-param-expiry": "Fecha de expiración. Puede ser relativa (por ejemplo, <kbd>5 meses</kbd> o <kbd>2 semanas</kbd>) o absoluta (por ejemplo, <kbd>2014-09-18T12:34:56Z</kbd>). Si se establece en <kbd>infinito</kbd>, <kbd>indefinido</kbd>, o <kbd>nunca</kbd>, el bloqueo será permanente.",
+       "apihelp-block-param-expiry": "Fecha de expiración. Puede ser relativa (por ejemplo, <kbd>5 months</kbd> o <kbd>2 weeks</kbd>) o absoluta (por ejemplo, <kbd>2014-09-18T12:34:56Z</kbd>). Si se establece en <kbd>infinite</kbd>, <kbd>indefinite</kbd>, o <kbd>never</kbd>, el bloqueo será permanente.",
        "apihelp-block-param-reason": "Razón para el bloqueo.",
        "apihelp-block-param-anononly": "Bloquear solo usuarios anónimos (es decir, desactivar ediciones anónimas de esta dirección IP).",
        "apihelp-block-param-nocreate": "Prevenir la creación de cuentas.",
@@ -38,7 +42,7 @@
        "apihelp-block-param-allowusertalk": "Permitir que el usuario edite su propia página de discusión (depende de <var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
        "apihelp-block-param-reblock": "Si la cuenta ya está bloqueada, sobrescribir el bloqueo existente.",
        "apihelp-block-param-watchuser": "Vigilar las páginas de usuario y de discusión del usuario o de la dirección IP.",
-       "apihelp-block-example-ip-simple": "Bloquear la dirección IP <kbd>192.0.2.5</kbd> durante 3 días por el motivo: <kbd>Primer ataque</kbd>.",
+       "apihelp-block-example-ip-simple": "Bloquear la dirección IP <kbd>192.0.2.5</kbd> durante 3 días por el motivo <kbd>First strike</kbd>.",
        "apihelp-block-example-user-complex": "Bloquear al usuario <kbd>Vandal</kbd> indefinidamente con el motivo <kbd>Vandalism</kbd> y evitar que se cree nuevas cuentas o envíe correos.",
        "apihelp-checktoken-description": "Comprueba la validez de una ficha desde <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
        "apihelp-checktoken-param-type": "Tipo de ficha a probar.",
        "apihelp-feedcontributions-param-toponly": "Mostrar solo ediciones que son últimas revisiones.",
        "apihelp-feedcontributions-param-newonly": "Mostrar solo ediciones que son creaciones de páginas.",
        "apihelp-feedcontributions-param-showsizediff": "Mostrar la diferencia de tamaño entre revisiones.",
-       "apihelp-feedcontributions-example-simple": "Devolver las contribuciones del usuario <kbd>Ejemplo</kbd>.",
+       "apihelp-feedcontributions-example-simple": "Devolver las contribuciones del usuario <kbd>Example</kbd>.",
        "apihelp-feedrecentchanges-description": "Devuelve un canal de cambios recientes.",
        "apihelp-feedrecentchanges-param-feedformat": "El formato del canal.",
        "apihelp-feedrecentchanges-param-namespace": "Espacio de nombres al cual limitar los resultados.",
        "apihelp-help-example-query": "Ayuda para dos submódulos de consulta.",
        "apihelp-imagerotate-description": "Girar una o más imágenes.",
        "apihelp-imagerotate-param-rotation": "Grados que rotar una imagen en sentido horario.",
-       "apihelp-imagerotate-example-simple": "Rotar <kbd>File:Ejemplo.png</kbd> <kbd>90</kbd> grados.",
-       "apihelp-imagerotate-example-generator": "Rotar todas las imágenes en la  <kbd>Categoría:Girar</kbd> <kbd>180</kbd> grados.",
-       "apihelp-import-param-summary": "Resumen de importación.",
+       "apihelp-imagerotate-example-simple": "Rotar <kbd>File:Example.png</kbd> <kbd>90</kbd> grados.",
+       "apihelp-imagerotate-example-generator": "Rotar todas las imágenes en <kbd>Category:Flip</kbd> <kbd>180</kbd> grados.",
+       "apihelp-import-param-summary": "Resumen de importación de entrada del registro.",
        "apihelp-import-param-xml": "Se cargó el archivo XML.",
        "apihelp-import-param-interwikisource": "Para importaciones interwiki: wiki desde la que importar.",
        "apihelp-import-param-interwikipage": "Para importaciones interwiki: página a importar.",
        "apihelp-managetags-param-tag": "Etiqueta para crear, eliminar, activar o desactivar. Para crear una etiqueta, esta debe no existir. Para eliminarla, debe existir. Para activarla, debe existir y no estar en uso por ninguna extensión. Para desactivarla, debe estar activada y definida manualmente.",
        "apihelp-managetags-param-reason": "Un motivo opcional para crear, eliminar, activar o desactivar la etiqueta.",
        "apihelp-managetags-example-create": "Crear una etiqueta llamada <kbd>spam</kbd> con el motivo <kbd>For use in edit patrolling</kbd>",
-       "apihelp-managetags-example-delete": "Eliminar la etiqueta <kbd>vandlaismo</kbd> con el motivo <kbd>mal deletreado</kbd>",
+       "apihelp-managetags-example-delete": "Eliminar la etiqueta <kbd>vandlaism</kbd> con el motivo <kbd>Misspelt</kbd>",
        "apihelp-managetags-example-activate": "Activar una etiqueta llamada <kbd>spam</kbd> con el motivo <kbd>For use in edit patrolling</kbd>",
        "apihelp-managetags-example-deactivate": "Desactivar una etiqueta llamada <kbd>spam</kbd> con el motivo <kbd>No longer required</kbd>",
        "apihelp-mergehistory-description": "Fusionar historiales de páginas.",
        "apihelp-parse-example-summary": "Analizar un resumen.",
        "apihelp-patrol-description": "Verificar una página o revisión.",
        "apihelp-patrol-param-rcid": "Identificador de cambios recientes que verificar.",
+       "apihelp-patrol-param-revid": "ID de revisión a patrullar.",
        "apihelp-patrol-example-rcid": "Verificar un cambio reciente.",
        "apihelp-patrol-example-revid": "Verificar una revisión.",
        "apihelp-protect-description": "Cambiar el nivel de protección de una página.",
        "apihelp-query+backlinks-example-generator": "Obtener información acerca de las páginas enlazadas a <kbd>Main page</kbd>.",
        "apihelp-query+blocks-description": "Listar todos los usuarios y direcciones IP bloqueadas.",
        "apihelp-query+blocks-param-users": "Lista de usuarios a buscar (opcional).",
+       "apihelp-query+blocks-param-ip": "Obtiene todos los bloqueos que se aplican a esta dirección IP o intervalo CIDR, incluyendo bloqueos de intervalos. No se puede usar en conjunto con <var>$3users</var>. No se aceptan intervalos CIDR mayores que IPv4/$1 o IPv6/$2.",
        "apihelp-query+blocks-param-prop": "Qué propiedades se obtendrán:",
        "apihelp-query+blocks-paramvalue-prop-userid": "Añade el identificador del usuario bloqueado.",
        "apihelp-query+blocks-paramvalue-prop-timestamp": "Añade la fecha y hora de cuando se aplicó el bloque.",
        "apihelp-query+embeddedin-param-limit": "Cuántas páginas se devolverán.",
        "apihelp-query+extlinks-param-limit": "Cuántos enlaces se devolverán.",
        "apihelp-query+extlinks-example-simple": "Obtener una lista de los enlaces externos en <kbd>Main Page</kbd>.",
+       "apihelp-query+exturlusage-description": "Enumera páginas que contienen una URL dada.",
        "apihelp-query+exturlusage-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+exturlusage-paramvalue-prop-ids": "Añade el identificado de la página.",
        "apihelp-query+exturlusage-paramvalue-prop-title": "Agrega el título y el identificador del espacio de nombres de la página.",
        "apihelp-query+redirects-paramvalue-prop-fragment": "Fragmento de cada redirección, si los hubiere.",
        "apihelp-query+redirects-param-limit": "Cuántas redirecciones se devolverán.",
        "apihelp-query+redirects-example-simple": "Mostrar una lista de las redirecciones a la [[Main Page|Portada]]",
-       "apihelp-query+revisions-example-last5": "Mostrar las últimas 5 revisiones de la <kbd>Portada</kbd>.",
+       "apihelp-query+revisions-example-last5": "Mostrar las últimas 5 revisiones de la <kbd>Main Page</kbd>.",
        "apihelp-query+revisions+base-param-prop": "Las propiedades que se obtendrán para cada revisión:",
        "apihelp-query+revisions+base-paramvalue-prop-ids": "El identificador de la revisión.",
        "apihelp-query+revisions+base-paramvalue-prop-flags": "Marcas de revisión (menor).",
        "apihelp-query+usercontribs-paramvalue-prop-patrolled": "Etiqueta ediciones verificadas.",
        "apihelp-query+usercontribs-paramvalue-prop-tags": "Lista las etiquetas para la edición.",
        "apihelp-query+usercontribs-param-show": "Mostrar solo los elementos que coinciden con estos criterios. Por ejemplo, solo ediciones no menores: <kbd>$2show=!minor</kbd>.\n\nSi se establece <kbd>$2show=patrolled</kbd> o <kbd>$2show=!patrolled</kbd>, las revisiones más antiguas que <var>[[mw:Manual:$wgRCMaxAge|$wgRCMaxAge]]</var> ($1 {{PLURAL:$1|segundo|segundos}}) no se mostrarán.",
-       "apihelp-query+usercontribs-example-user": "Mostrar contribuciones del usuario <kbd>Ejemplo</kbd>.",
+       "apihelp-query+usercontribs-example-user": "Mostrar contribuciones del usuario <kbd>Example</kbd>.",
        "apihelp-query+usercontribs-example-ipprefix": "Mostrar las contribuciones de todas las direcciones IP con el prefijo <kbd>192.0.2.</kbd>.",
        "apihelp-query+userinfo-description": "Obtener información sobre el usuario actual.",
        "apihelp-query+userinfo-param-prop": "Qué piezas de información incluir:",
        "apihelp-tag-param-logid": "Uno o más identificadores de entradas del registro a los que agregar o eliminar la etiqueta.",
        "apihelp-tag-param-reason": "Motivo del cambio.",
        "apihelp-tag-example-rev": "Añadir la etiqueta <kbd>vandalism</kbd> al identificador de revisión 123 sin especificar un motivo",
-       "apihelp-tag-example-log": "Eliminar la etiqueta <kbd>spam</kbd> de la entrada del registro con identificador 123 con el motivo <kbd>aplicada incorrectamente</kbd>",
+       "apihelp-tag-example-log": "Eliminar la etiqueta <kbd>spam</kbd> de la entrada del registro con identificador 123 con el motivo <kbd>Wrongly applied</kbd>",
        "apihelp-unblock-description": "Desbloquear un usuario.",
+       "apihelp-unblock-param-user": "Nombre de usuario, dirección IP o rango de direcciones IP para desbloquear. No se puede utilizar junto con <var>$1id</var>.",
        "apihelp-unblock-param-reason": "Motivo del desbloqueo.",
-       "apihelp-unblock-example-user": "Desbloquear al usuario <kbd>Bob</kbd> con el motivo <kbd>Lo siento, Bob</kbd>",
+       "apihelp-unblock-example-user": "Desbloquear al usuario <kbd>Bob</kbd> con el motivo <kbd>Sorry Bob</kbd>",
        "apihelp-undelete-param-reason": "Motivo de la restauración.",
        "apihelp-undelete-example-revisions": "Restaurar dos revisiones de la página <kbd>Main Page</kbd>.",
        "apihelp-upload-param-tags": "Cambiar etiquetas para aplicar a la entrada del registro de subidas y a la revisión de página de archivo.",
        "apihelp-userrights-param-reason": "Motivo del cambio.",
        "apihelp-userrights-example-user": "Agregar al usuario <kbd>FooBot</kbd> al grupo <kbd>bot</kbd> y eliminarlo de los grupos <kbd>sysop</kbd> y <kbd>bureaucrat</kbd>.",
        "apihelp-watch-example-watch": "Vigilar la página <kbd>Main Page</kbd>.",
-       "apihelp-watch-example-unwatch": "Dejar de vigilar la <kbd>Portada</kbd>.",
+       "apihelp-watch-example-unwatch": "Dejar de vigilar la <kbd>Main Page</kbd>.",
        "apihelp-format-example-generic": "Devolver el resultado de la consulta en formato $1.",
        "api-help-main-header": "Módulo principal",
        "api-help-flag-deprecated": "Este módulo está en desuso.",
index f870887..a429583 100644 (file)
@@ -12,7 +12,8 @@
                        "Ebraminio",
                        "Macofe",
                        "Huji",
-                       "Ladsgroup"
+                       "Ladsgroup",
+                       "Freshman404"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|مستندات]]\n* [[mw:API:FAQ|پرسش‌های متداول]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api فهرست پست الکترونیکی]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce اعلانات رابط برنامه‌نویسی کاربردی]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R ایرادها و درخواست‌ها]\n</div>\n\n<strong>وضعیت:</strong> تمام ویژگی‌هایی که در این صفحه نمایش یافته‌اند باید کار بکنند، ولی رابط برنامه‌نویسی کاربردی کماکان در حال توسعه است، و ممکن است در هر زمان تغییر بکند. به عضویت [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ فهرست پست الکترونیکی mediawiki-api-announce] در بیایید تا از تغییرات باخبر شوید.\n\n<strong>درخواست‌های معیوب:</strong> وقتی درخواست‌های معیوب به رابط برنامه‌نویسی کاربردی فرستاده شوند، یک سرایند اچ‌تی‌تی‌پی با کلید «MediaWiki-API-Erorr» فرستاده می‌شود و بعد هم مقدار سرایند و هم کد خطای بازگردانده شده  هر دو به یک مقدار نسبت داده می‌شوند. برای اطلاعات بیشتر [[mw:API:Errors_and_warnings|API: Errors and warnings]] را ببینید.\n\n<strong>آزمایش:</strong> برای انجام درخواست‌های API آزمایشی [[Special:ApiSandbox]] را ببینید.",
        "apihelp-opensearch-param-suggest": "کاری نکنید اگر <var>[[mw:Manual:$wgEnableOpenSearchSuggest|$wgEnableOpenSearchSuggest]]</var> false است.",
        "apihelp-opensearch-param-format": "فرمت خروجی.",
        "apihelp-opensearch-example-te": "یافتن صفحه‌هایی که با <kbd>Te</kbd> آغاز می‌شوند",
+       "apihelp-options-param-reset": "ترجیحات را به مقادیر پیش فرض سایت بازمی گرداند.",
        "apihelp-options-example-reset": "بازنشانی همه تنظیمات.",
        "apihelp-paraminfo-param-helpformat": "ساختار راهنمای رشته‌ها",
        "apihelp-parse-example-page": "تجزیه یک صفحه.",
index b1089c7..4c0d177 100644 (file)
@@ -22,7 +22,8 @@
                        "L",
                        "Umherirrender",
                        "Elfix",
-                       "Lbayle"
+                       "Lbayle",
+                       "Verdy p"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentation]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> Toutes les fonctionnalités affichées sur cette page devraient fonctionner, mais l’API est encore en cours de développement et peut changer à tout moment. Inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un en-tête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet en-tête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Test :</strong> Pour faciliter le test des requêtes de l’API, voyez [[Special:ApiSandbox]].",
        "apihelp-imagerotate-example-simple": "Faire pivoter <kbd>File:Example.png</kbd> de <kbd>90</kbd> degrés.",
        "apihelp-imagerotate-example-generator": "Faire pivoter toutes les images de <kbd>Category:Flip</kbd> de <kbd>180</kbd> degrés.",
        "apihelp-import-description": "Importer une page depuis un autre wiki, ou depuis un fichier XML.\n\nNoter que le POST HTTP doit être effectué comme un import de fichier (c’est-à-dire en utilisant multipart/form-data) lors de l’envoi d’un fichier pour le paramètre <var>xml</var>.",
-       "apihelp-import-param-summary": "Importer le résumé.",
+       "apihelp-import-param-summary": "Résumé de l’importation de l’entrée de journal.",
        "apihelp-import-param-xml": "Fichier XML téléchargé.",
        "apihelp-import-param-interwikisource": "Pour les importations interwiki : wiki depuis lequel importer.",
        "apihelp-import-param-interwikipage": "Pour les importations interwiki : page à importer.",
        "apihelp-purge-param-forcerecursivelinkupdate": "Mettre à jour la table des liens, et mettre à jour les tables de liens pour toute page qui utilise cette page comme modèle",
        "apihelp-purge-example-simple": "Purger les pages <kbd>Main Page</kbd> et <kbd>API</kbd>.",
        "apihelp-purge-example-generator": "Purger les 10 premières pages de l’espace de noms principal",
-       "apihelp-query-description": "Extraire des données de et sur MédiaWiki.\n\nToutes les modifications de données devront d’abord utiliser une requête pour obtenir un jeton, afin d’éviter les abus de la part de sites malveillants.",
+       "apihelp-query-description": "Extraire des données de et sur MediaWiki.\n\nToutes les modifications de données devront d’abord utiliser une requête pour obtenir un jeton, afin d’éviter les abus de la part de sites malveillants.",
        "apihelp-query-param-prop": "Quelles propriétés obtenir des pages demandées.",
        "apihelp-query-param-list": "Quelles listes obtenir.",
        "apihelp-query-param-meta": "Quelles métadonnées obtenir.",
        "apihelp-query+allimages-param-minsize": "Restreindre aux images avec au moins ce nombre d’octets.",
        "apihelp-query+allimages-param-maxsize": "Restreindre aux images avec au plus ce nombre d’octets.",
        "apihelp-query+allimages-param-sha1": "Hachage SHA1 de l’image. Écrase $1sha1base36.",
-       "apihelp-query+allimages-param-sha1base36": "Hachage SHA1 de l’image en base 36 (utilisé dans MédiaWiki).",
+       "apihelp-query+allimages-param-sha1base36": "Hachage SHA1 de l’image en base 36 (utilisé dans MediaWiki).",
        "apihelp-query+allimages-param-user": "Renvoyer seulement les fichiers téléchargés par cet utilisateur. Utilisable uniquement avec $1sort=timestamp. Impossible à utiliser avec $1filterbots.",
        "apihelp-query+allimages-param-filterbots": "Comment filtrer les fichiers téléchargés par des robots. Peut être utilisé uniquement avec $1sort=timestamp. Impossible à utiliser avec $1user.",
        "apihelp-query+allimages-param-mime": "Quels types MIME rechercher, par ex. <kbd>image/jpeg</kbd>.",
        "apihelp-query+pagepropnames-example-simple": "Obtenir les 10 premiers noms de propriété.",
        "apihelp-query+pageprops-description": "Obtenir diverses propriétés de page définies dans le contenu de la page.",
        "apihelp-query+pageprops-param-prop": "Lister uniquement ces propriétés de page (<kbd>[[Special:ApiHelp/query+pagepropnames|action=query&list=pagepropnames]]</kbd> renvoie les noms de propriété de page utilisés). Utile pour vérifier si des pages utilisent une certaine propriété de page.",
-       "apihelp-query+pageprops-example-simple": "Obtenir les propriétés des pages <kbd>Accueil</kbd> et <kbd>MédiaWiki</kbd>.",
+       "apihelp-query+pageprops-example-simple": "Obtenir les propriétés des pages <kbd>Main Page</kbd> et <kbd>MediaWiki</kbd>.",
        "apihelp-query+pageswithprop-description": "Lister toutes les pages utilisant une propriété de page donnée.",
        "apihelp-query+pageswithprop-param-propname": "Propriété de page pour laquelle énumérer les pages (<kbd>[[Special:ApiHelp/query+pagepropnames|action=query&list=pagepropnames]]</kbd> renvoie les noms de propriété de page utilisés).",
        "apihelp-query+pageswithprop-param-prop": "Quelles informations inclure :",
        "apihelp-tokens-example-emailmove": "Récupérer un jeton de courriel et un jeton de déplacement.",
        "apihelp-unblock-description": "Débloquer un utilisateur.",
        "apihelp-unblock-param-id": "ID du blocage à lever (obtenu via <kbd>list=blocks</kbd>). Impossible à utiliser avec <var>$1user</var>.",
-       "apihelp-unblock-param-user": "Nom d’utilisateur, adresse IP ou plage d’adresse IP à débloquer. Impossible à utiliser avec <var>$1id</var>.",
+       "apihelp-unblock-param-user": "Nom d’utilisateur, adresse IP ou plage d’adresses IP à débloquer. Impossible à utiliser en même temps que <var>$1id</var>.",
        "apihelp-unblock-param-reason": "Motif de déblocage.",
        "apihelp-unblock-param-tags": "Modifier les balises à appliquer à l’entrée dans le journal de blocage.",
        "apihelp-unblock-example-id": "Lever le blocage d’ID #<kbd>105</kbd>.",
index 6841ab7..80c4024 100644 (file)
        "apihelp-imagerotate-example-simple": "Rotar <kbd>File:Example.png</kbd> <kbd>90</kbd> graos.",
        "apihelp-imagerotate-example-generator": "Rotar tódalas imaxes en <kbd>Category:Flip</kbd> <kbd>180</kbd> graos",
        "apihelp-import-description": "Importar unha páxina doutra wiki, ou dun ficheiro XML.\n\nDecátese de que o POST HTTP debe facerse como unha carga de ficheiro (p. ex. usando multipart/form-data) cando se envíe un ficheiro para o parámetro <var>xml</var>.",
-       "apihelp-import-param-summary": "Resume de importación.",
+       "apihelp-import-param-summary": "Resume de importación de entrada no rexistro.",
        "apihelp-import-param-xml": "Subido ficheiro XML.",
        "apihelp-import-param-interwikisource": "Para importacións interwiki: wiki da que importar.",
        "apihelp-import-param-interwikipage": "Para importacións interwiki: páxina a importar.",
        "apihelp-watch-example-unwatch": "Deixar de vixiar a páxina <kbd>Páxina Principal</kbd>.",
        "apihelp-watch-example-generator": "Vixiar as primeiras páxinas no espazo de nomes principal",
        "apihelp-format-example-generic": "Devolver o resultado da consulta no formato $1.",
+       "apihelp-format-param-wrappedhtml": "Devolver o HTML formatado e os módulos ResourceLoader asociados como un obxecto JSON.",
        "apihelp-json-description": "Datos de saída en formato JSON.",
        "apihelp-json-param-callback": "Se está especificado, inclúe a saída na chamada da función indicada. Para maior seguridade, todos os datos específicos do usuario serán restrinxidos.",
        "apihelp-json-param-utf8": "Se está especificado, codifica a maioría (pero non todos) dos caracteres ASCII como UTF-8 no canto de reemprazalos con secuencias de escape hexadecimais. Por defecto cando <var>formatversion</var> non é <kbd>1</kbd>.",
index 618fbc7..7a842f4 100644 (file)
@@ -39,7 +39,7 @@
        "apihelp-block-param-reblock": "אם המשתמש כבר חסום, לדרוס את החסימה הנוכחית.",
        "apihelp-block-param-watchuser": "לעקוב אחרי דף המשתמש ודף השיחה של המשתמש או של כתובת ה־IP.",
        "apihelp-block-example-ip-simple": "חסימת כתובת ה־IP‏ <kbd>192.0.2.5</kbd> לשלושה ימים עם הסיבה <kbd>First strike</kbd>.",
-       "apihelp-block-example-user-complex": "×\97ס×\99×\9eת ×\94×\9eשת×\9eש <kbd>Vandal</kbd> ×\9c×\9c×\90 ×\94×\92×\91×\9cת ×\96×\9e×\9f ×¢×\9d ×\94ס×\99×\91×\94 <kbd>Vandalism</kbd>, ×\95×\9e× ×\99עת ×\99צ×\99רת ×\97ש×\91×\95×\91ות חדשים ושליחת דוא\"ל.",
+       "apihelp-block-example-user-complex": "×\97ס×\99×\9eת ×\94×\9eשת×\9eש <kbd>Vandal</kbd> ×\9c×\9c×\90 ×\94×\92×\91×\9cת ×\96×\9e×\9f ×¢×\9d ×\94ס×\99×\91×\94 <kbd>Vandalism</kbd>, ×\95×\9e× ×\99עת ×\99צ×\99רת ×\97ש×\91×\95× ות חדשים ושליחת דוא\"ל.",
        "apihelp-checktoken-description": "בדיקת התקינות של האסימון מ־<kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
        "apihelp-checktoken-param-type": "סוג האסימון שבבדיקה.",
        "apihelp-checktoken-param-token": "איזה אסימון לבדוק.",
        "apihelp-imagerotate-example-simple": "לסובב את <kbd>File:Example.png</kbd> ב־<kbd>90</kbd> מעלות.",
        "apihelp-imagerotate-example-generator": "לסובב את כל התמונות ב־<kbd>Category:Flip</kbd> ב־<kbd>180</kbd> מעלות.",
        "apihelp-import-description": "לייבא דף מוויקי אחר או מקובץ XML.\n\nיש לשים לב לכך שפעולת HTTP POST צריכה להיעשות בתור העלאת קובץ (כלומר, עם multipart/form-data) בזמן שליחת קובץ לפרמטר <var>xml</var>.",
-       "apihelp-import-param-summary": "תקצ×\99ר ×\99×\91×\95×\90.",
+       "apihelp-import-param-summary": "תקצ×\99ר ×\99×\99×\91×\95×\90 ×¢×\99×\95×\9c×\99 ×\99×\95×\9e×\9f.",
        "apihelp-import-param-xml": "קובץ XML שהועלה.",
        "apihelp-import-param-interwikisource": "ליבוא בין אתרי ויקי: מאיזה ויקי לייבא.",
        "apihelp-import-param-interwikipage": "ליבוא בין אתרי ויקי: איזה דף לייבא.",
        "apihelp-query+allusers-paramvalue-prop-groups": "הוספת קבוצות שמשתמש חבר בהן. זה משתמש ביותר משאבי דפדפן ויכול להחזיר פחות תוצאות מהמגבלה.",
        "apihelp-query+allusers-paramvalue-prop-implicitgroups": "לרשום את כל הקבוצות שהמשתמש חבר בהן אוטומטית.",
        "apihelp-query+allusers-paramvalue-prop-rights": "רשימת הההרשאות שיש למשתמש.",
-       "apihelp-query+allusers-paramvalue-prop-editcount": "×\94×\95ספת ×\9e× ×\99×\99×\9f ×\94ער×\99×\9b×\95ת ×©×\9c ×\94×\9eשת×\9eש .",
+       "apihelp-query+allusers-paramvalue-prop-editcount": "×\94×\95ספת ×\9e×\95× ×\94 ×\94ער×\99×\9b×\95ת ×©×\9c ×\94×\9eשת×\9eש.",
        "apihelp-query+allusers-paramvalue-prop-registration": "הוספת חותם־הזמן של זמן הרישום של המשתמש (יכול להיות ריק).",
        "apihelp-query+allusers-paramvalue-prop-centralids": "הוספת המזהה המרכזי ומצב השיוך למשתמש.",
        "apihelp-query+allusers-param-limit": "כמה שמות משתמש בסך הכול לשנות.",
index 5eaa449..ba66a87 100644 (file)
@@ -5,7 +5,8 @@
                        "Dorgan",
                        "Tacsipacsi",
                        "ViDam",
-                       "Macofe"
+                       "Macofe",
+                       "Wolf Rex"
                ]
        },
        "apihelp-main-param-action": "Milyen műveletet hajtson végre.",
        "apihelp-block-param-expiry": "Lejárat ideje. Lehet relatív (pl. <kbd>5 months</kbd>, <kbd>2 weeks</kbd>) vagy abszolút (pl. <kbd>2014-09-18T12:34:56Z</kbd>). Ha <kbd>infinite</kbd>-re, <kbd>indefinite</kbd>-re vagy <kbd>never</kbd>-re állítod, a blokk soha nem fog lejárni.",
        "apihelp-block-param-reason": "Blokkolás oka.",
        "apihelp-block-param-nocreate": "Új regisztráció megakadályozása",
+       "apihelp-block-param-watchuser": "A szerkesztő vagy IP-cím szerkesztői- és vitalapjának figyelése.",
        "apihelp-createaccount-param-name": "Felhasználónév.",
+       "apihelp-createaccount-param-email": "A szerkesztő e-mail-címe (nem kötelező).",
+       "apihelp-createaccount-param-realname": "A szerkesztő valódi neve (nem kötelező).",
        "apihelp-delete-description": "Lap törlése.",
+       "apihelp-delete-param-unwatch": "A lap törlése a szerkesztő figyelőlistájáról.",
        "apihelp-delete-example-simple": "<kbd>Main Page</kbd> törlése.",
+       "apihelp-disabled-description": "Ez a modul le lett tiltva.",
+       "apihelp-edit-description": "Lapok létrehozása és szerkesztése.",
+       "apihelp-edit-param-sectiontitle": "Az új szakasz címe.",
+       "apihelp-edit-param-minor": "Apró változtatás.",
        "apihelp-edit-example-edit": "Lap szerkesztése",
        "apihelp-expandtemplates-param-title": "Lap címe.",
+       "apihelp-feedrecentchanges-param-hideminor": "Apró változtatások elrejtése.",
+       "apihelp-feedrecentchanges-param-hidebots": "Botszerkesztések elrejtése.",
+       "apihelp-feedrecentchanges-param-hidepatrolled": "Ellenőrzött változtatások elrejtése.",
+       "apihelp-login-param-name": "Szerkesztőnév.",
+       "apihelp-login-param-password": "Jelszó.",
+       "apihelp-login-example-login": "Bejelentkezés.",
+       "apihelp-mergehistory-description": "Laptörténetek egyesítése",
+       "apihelp-mergehistory-param-reason": "Laptörténet egyesítésének oka.",
+       "apihelp-move-param-movetalk": "Nevezd át a vitalapot is, ha létezik.",
+       "apihelp-move-param-movesubpages": "Nevezd át az allapokat is, ha lehetséges.",
+       "apihelp-opensearch-param-limit": "Találatok maximális száma.",
+       "apihelp-options-example-reset": "Minden beállítás visszaállítása",
+       "apihelp-protect-example-protect": "Lap levédése.",
+       "apihelp-query+allcategories-param-dir": "A rendezés iránya.",
+       "apihelp-query+deletedrevs-paraminfo-modes": "{{PLURAL:$1|Mód|Módok}}: $2",
+       "apihelp-query+imageinfo-paramvalue-prop-sha1": "SHA-1 hash hozzáadása a fájlhoz.",
+       "apihelp-query+imageinfo-paramvalue-prop-mime": "MIME-típus hozzáadása a fájlhoz.",
+       "apihelp-query+info-paramvalue-prop-watchers": "A lapot figyelők száma, ha lehetséges.",
        "apihelp-userrights-param-userid": "Felhasználói azonosító.",
        "api-help-title": "MediaWiki API súgó",
        "api-help-lead": "Ez egy automatikusan generált MediaWiki API-dokumentációs lap.\n\nDokumentáció és példák: https://www.mediawiki.org/wiki/API",
index 223e585..480ad24 100644 (file)
@@ -1,8 +1,10 @@
 {
        "@metadata": {
                "authors": [
-                       "WongKentir"
+                       "WongKentir",
+                       "Beeyan"
                ]
        },
-       "apihelp-createaccount-param-name": "Nama pengguna"
+       "apihelp-createaccount-param-name": "Nama pengguna",
+       "apihelp-revisiondelete-param-ids": "Penanda untuk perubahan yang akan dihapus"
 }
index 927509c..d26b996 100644 (file)
                        "JackLantern"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentazione (in inglese)]]\n* [[mw:API:FAQ|FAQ (in inglese)]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunci sull'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug & richieste]\n</div>\n<strong>Stato:</strong> Tutte le funzioni e caratteristiche mostrate su questa pagina dovrebbero funzionare, ma l'API è ancora in fase d'attivo sviluppo, e potrebbe cambiare in qualsiasi momenento. Iscriviti alla [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce mailing list] per essere informato sugli aggiornamenti.\n\n<strong>Istruzioni sbagliate:</strong> quando vengono impartite all'API delle istruzioni sbagliate, un'intestazione HTTP verrà inviata col messaggio \"MediaWiki-API-Error\" e sia al valore dell'intestazione sia al codice d'errore verrà impostato lo stesso valore. Per maggiori informazioni leggi [[mw:API:Errors_and_warnings|API:Errori ed avvertimenti (in inglese)]].\n\n<strong>Test:</strong> per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentazione]] (in inglese)\n* [[mw:API:FAQ|FAQ]] (in inglese)\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunci sull'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug & richieste]\n</div>\n<strong>Stato:</strong> tutte le funzioni e caratteristiche mostrate su questa pagina dovrebbero funzionare, ma le API sono ancora in fase attiva di sviluppo, e potrebbero cambiare in qualsiasi momento. Iscriviti alla [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la mailing list sugli annunci delle API MediaWiki] per essere informato sugli aggiornamenti.\n\n<strong>Istruzioni sbagliate:</strong> quando vengono impartite alle API delle istruzioni sbagliate, un'intestazione HTTP verrà inviata col messaggio \"MediaWiki-API-Error\" e, sia il valore dell'intestazione, sia il codice d'errore, verranno impostati con lo stesso valore. Per maggiori informazioni leggi [[mw:API:Errors_and_warnings|API:Errori ed avvertimenti]] (in inglese).\n\n<strong>Test:</strong> per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Azione da compiere.",
        "apihelp-main-param-format": "Formato dell'output.",
-       "apihelp-main-param-assert": "Verifica che l'utente sia loggato se si è impostato <kbd>utente</kbd>, o che abbia i permessi di bot se si è impostato <kbd>bot</kbd>.",
+       "apihelp-main-param-assert": "Verifica che l'utente abbia effettuato l'accesso se si è impostato <kbd>user</kbd>, o che abbia i permessi di bot se si è impostato <kbd>bot</kbd>.",
        "apihelp-main-param-requestid": "Tutti i valori forniti saranno implementati nella risposta. Potrebbero venir utilizzati per distinguere le richieste.",
        "apihelp-main-param-servedby": "Includi nel risultato il nome dell'host che ha servito la richiesta.",
        "apihelp-main-param-curtimestamp": "Includi nel risultato il timestamp attuale.",
        "apihelp-block-description": "Blocca  un utente.",
        "apihelp-block-param-user": "Nome utente, indirizzo IP o range di IP da bloccare.",
+       "apihelp-block-param-expiry": "Tempo di scadenza. Può essere relativo (ad esempio, <kbd>5 months</kbd> o <kbd>2 weeks</kbd>) o assoluto (ad esempio <kbd>2014-09-18T12:34:56Z</kbd>). Se impostato a <kbd>infinite</kbd>, <kbd>indefinite</kbd> o <kbd>never</kbd>, il blocco non scadrà mai.",
        "apihelp-block-param-reason": "Motivo del blocco.",
        "apihelp-block-param-anononly": "Blocca solo gli utenti non registrati (cioè disattiva i contributi anonimi da questo indirizzo IP).",
        "apihelp-block-param-nocreate": "Impedisci creazione di utenze.",
+       "apihelp-block-param-autoblock": "Blocca automaticamente l'ultimo indirizzo IP usato dall'utente e i successivi con cui viene tentato l'accesso.",
        "apihelp-block-param-hidename": "Nascondi il nome utente dal registro dei blocchi (Richiede i permessi di <code>hideuser</code>).",
        "apihelp-block-param-reblock": "Se l'utente è già bloccato, sovrascrivere il blocco esistente.",
        "apihelp-block-param-watchuser": "Segui la pagina utente e le pagine di discussione utente dell'utente o dell'indirizzo IP.",
        "apihelp-createaccount-example-pass": "Crea l'utente <kbd>testuser</kbd> con password <kbd>test123</kbd>.",
        "apihelp-createaccount-example-mail": "Crea l'utente <kbd>testmailuser</kbd> e mandagli via e-mail una password generata casualmente.",
        "apihelp-delete-description": "Cancella una pagina.",
-       "apihelp-delete-param-title": "Titolo della pagina che si desidera eliminare. Non può essere usato insieme con <var>$1pageid</var>.",
+       "apihelp-delete-param-title": "Titolo della pagina che si desidera eliminare. Non può essere usato insieme a <var>$1pageid</var>.",
        "apihelp-delete-param-pageid": "ID di pagina della pagina da cancellare. Non può essere usato insieme con <var>$1title</var>.",
        "apihelp-delete-param-reason": "Motivo della cancellazione. Se non indicato, verrà usata una motivazione generata automaticamente.",
        "apihelp-delete-param-watch": "Aggiunge la pagina agli osservati speciali dell'utente attuale.",
        "apihelp-delete-param-unwatch": "Rimuove la pagina dagli osservati speciali dell'utente attuale.",
+       "apihelp-delete-param-oldimage": "Il nome della vecchia immagine da cancellare, come fornita da [[Special:ApiHelp/query+imageinfo|action=query&prop=imageinfo&iiprop=archivename]].",
        "apihelp-delete-example-simple": "Cancella <kbd>Main Page</kbd>.",
        "apihelp-delete-example-reason": "Cancella la <kbd>Main Page</kbd> con motivazione <kbd>Preparing for move</kbd>.",
        "apihelp-disabled-description": "Questo modulo è stato disabilitato.",
        "apihelp-edit-description": "Crea e modifica pagine.",
-       "apihelp-edit-param-title": "Titolo della pagina da modificare. Non può essere usato insieme con <var>$1pageid</var>.",
+       "apihelp-edit-param-title": "Titolo della pagina da modificare. Non può essere usato insieme a <var>$1pageid</var>.",
        "apihelp-edit-param-pageid": "ID di pagina della pagina da modificare. Non può essere usato insieme con <var>$1title</var>.",
+       "apihelp-edit-param-section": "Numero di sezione. <kbd>0</kbd> per la sezione iniziale, <kbd>new</kbd> per una nuova sezione.",
        "apihelp-edit-param-sectiontitle": "Il titolo per una nuova sezione.",
        "apihelp-edit-param-text": "Contenuto della pagina.",
        "apihelp-edit-param-summary": "Oggetto della modifica. Anche titolo della sezione se $1sezione=new e $1sectiontitle non è impostato.",
        "apihelp-edit-param-watch": "Aggiunge la pagina agli osservati speciali dell'utente attuale.",
        "apihelp-edit-param-unwatch": "Rimuove la pagina dagli osservati speciali dell'utente attuale.",
        "apihelp-edit-param-redirect": "Risolvi automaticamente redirect.",
+       "apihelp-edit-param-contentmodel": "Modello di contenuto dei nuovi contenuti.",
+       "apihelp-edit-param-token": "Il token deve sempre essere inviato come ultimo parametro, o almeno dopo il parametro $1text.",
        "apihelp-edit-example-edit": "Modifica una pagina.",
+       "apihelp-edit-example-prepend": "Anteponi <kbd>_&#95;NOTOC_&#95;</kbd> a una pagina.",
        "apihelp-emailuser-description": "Manda un'e-mail ad un utente.",
        "apihelp-emailuser-param-target": "Utente a cui inviare l'e-mail.",
        "apihelp-emailuser-param-subject": "Oggetto dell'e-mail.",
        "apihelp-feedcontributions-param-feedformat": "Il formato del feed.",
        "apihelp-feedcontributions-param-year": "Dall'anno (e precedenti).",
        "apihelp-feedcontributions-param-month": "Dal mese (e precedenti).",
+       "apihelp-feedcontributions-param-tagfilter": "Filtra contributi che hanno queste etichette.",
        "apihelp-feedcontributions-param-deletedonly": "Mostra solo i contribuiti cancellati.",
        "apihelp-feedcontributions-param-toponly": "Mostra solo i contributi che sono le ultime versioni per la pagina.",
        "apihelp-feedcontributions-param-newonly": "Visualizza solo le modifiche che sono creazioni di pagina.",
+       "apihelp-feedcontributions-param-showsizediff": "Mostra la differenza di dimensioni tra le versioni.",
+       "apihelp-feedcontributions-example-simple": "Restituisce contributi per l'utente <kbd>Example</kbd>.",
+       "apihelp-feedrecentchanges-param-feedformat": "Il formato del feed.",
+       "apihelp-feedrecentchanges-param-namespace": "Namespace a cui limitare i risultati.",
+       "apihelp-feedrecentchanges-param-associated": "Includi namespace associato (discussione o principale)",
+       "apihelp-feedrecentchanges-param-limit": "Numero massimo di risultati da restituire.",
        "apihelp-feedrecentchanges-param-hideminor": "Nascondi le modifiche minori.",
        "apihelp-feedrecentchanges-param-hidebots": "Nascondi le modifiche apportate da bot.",
        "apihelp-feedrecentchanges-param-hideanons": "Nascondi le modifiche fatte da utenti anonimi.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Mostra solo le modifiche alle pagine collegate a quella specificata.",
        "apihelp-feedrecentchanges-example-simple": "Mostra le ultime modifiche.",
        "apihelp-feedrecentchanges-example-30days": "Mostra le modifiche degli ultimi 30 giorni.",
+       "apihelp-feedwatchlist-param-feedformat": "Il formato del feed.",
        "apihelp-feedwatchlist-param-linktosections": "Collega direttamente alla sezione modificata, se possibile.",
        "apihelp-filerevert-description": "Ripristina un file ad una versione precedente.",
        "apihelp-filerevert-param-filename": "Nome del file di destinazione, senza il prefisso 'File:'.",
        "apihelp-filerevert-param-comment": "Commento sul caricamento.",
        "apihelp-filerevert-param-archivename": "Nome dell'archivio della versione da ripristinare.",
        "apihelp-filerevert-example-revert": "Ripristina <kbd>Wiki.png</kbd> alla versione del <kbd>2011-03-05T15:27:40Z</kbd>.",
+       "apihelp-help-param-toc": "Includi un indice nell'output HTML.",
+       "apihelp-help-example-main": "Aiuto per il modulo principale.",
        "apihelp-help-example-submodules": "Aiuto per <kbd>action=query</kbd> e tutti i suoi sotto-moduli.",
+       "apihelp-help-example-recursive": "Tutti gli aiuti in una pagina.",
+       "apihelp-help-example-help": "Aiuto per lo stesso modulo di aiuto.",
        "apihelp-imagerotate-description": "Ruota una o più immagini.",
        "apihelp-imagerotate-param-rotation": "Gradi di rotazione dell'immagine in senso orario.",
        "apihelp-imagerotate-example-simple": "Ruota <kbd>File:Example.png</kbd> di <kbd>90</kbd> gradi.",
        "apihelp-imagerotate-example-generator": "Ruota tutte le immagini in <kbd>Category:Flip</kbd> di <kbd>180</kbd> gradi.",
-       "apihelp-import-param-summary": "Oggetto dell'importazione.",
+       "apihelp-import-param-summary": "Oggetto nel registro di importazione.",
        "apihelp-import-param-xml": "File XML caricato.",
        "apihelp-import-param-interwikisource": "Per importazioni interwiki: wiki da cui importare.",
        "apihelp-import-param-interwikipage": "Per importazioni interwiki: pagina da importare.",
        "apihelp-import-param-fullhistory": "Per importazioni interwiki: importa l'intera cronologia, non solo la versione attuale.",
        "apihelp-import-param-templates": "Per importazioni interwiki: importa anche tutti i template inclusi.",
+       "apihelp-import-param-namespace": "Importa in questo namespace. Non può essere usato insieme a <var>$1rootpage</var>.",
+       "apihelp-import-param-rootpage": "Importa come sottopagina di questa pagina. Non può essere usato insieme a <var>$1namespace</var>.",
        "apihelp-import-example-import": "Importa [[meta:Help:ParserFunctions]] nel namespace 100 con cronologia completa.",
        "apihelp-login-param-name": "Nome utente.",
        "apihelp-login-param-password": "Password.",
        "apihelp-login-param-domain": "Dominio (opzionale).",
+       "apihelp-login-example-gettoken": "Recupera un token di login.",
        "apihelp-login-example-login": "Entra.",
+       "apihelp-logout-description": "Esci e cancella i dati della sessione.",
        "apihelp-mergehistory-description": "Unisce cronologie pagine.",
        "apihelp-mergehistory-param-from": "Il titolo della pagina da cui cronologia sarà unita. Non può essere usato insieme a <var>$1fromid</var>.",
        "apihelp-mergehistory-param-fromid": "L'ID della pagina da cui cronologia sarà unita. Non può essere usato insieme a <var>$1from</var>.",
        "apihelp-mergehistory-example-merge": "Unisci l'intera cronologia di <kbd>Oldpage</kbd> in <kbd>Newpage</kbd>.",
        "apihelp-mergehistory-example-merge-timestamp": "Unisci le versioni della pagina <kbd>Oldpage</kbd> fino a <kbd>2015-12-31T04:37:41Z</kbd> in <kbd>Newpage</kbd>.",
        "apihelp-move-description": "Sposta una pagina.",
+       "apihelp-move-param-to": "Titolo a cui spostare la pagina.",
        "apihelp-move-param-reason": "Motivo della rinomina.",
        "apihelp-move-param-movetalk": "Rinomina la pagina di discussione, se esiste.",
        "apihelp-move-param-movesubpages": "Rinomina sottopagine, se applicabile.",
        "apihelp-move-param-noredirect": "Non creare un rinvio.",
        "apihelp-move-param-watch": "Aggiunge la pagina e il redirect agli osservati speciali dell'utente attuale.",
+       "apihelp-move-param-unwatch": "Rimuovi la pagina e il redirect dagli osservati speciali dell'utente attuale.",
        "apihelp-move-param-ignorewarnings": "Ignora i messaggi di avvertimento del sistema.",
+       "apihelp-move-example-move": "Sposta <kbd>Badtitle</kbd> a <kbd>Goodtitle</kbd> senza lasciare redirect.",
+       "apihelp-opensearch-param-search": "Stringa di ricerca.",
+       "apihelp-opensearch-param-limit": "Numero massimo di risultati da restituire.",
+       "apihelp-opensearch-param-suggest": "Non fare nulla se <var>[[mw:Manual:$wgEnableOpenSearchSuggest|$wgEnableOpenSearchSuggest]]</var> è falso.",
        "apihelp-opensearch-param-format": "Il formato dell'output.",
        "apihelp-opensearch-example-te": "Trova le pagine che iniziano con <kbd>Te</kbd>.",
        "apihelp-options-example-reset": "Reimposta tutte le preferenze.",
+       "apihelp-paraminfo-description": "Ottieni informazioni sui moduli API.",
        "apihelp-paraminfo-param-helpformat": "Formato delle stringhe di aiuto.",
        "apihelp-parse-param-summary": "Oggetto da analizzare.",
+       "apihelp-parse-param-prop": "Quali pezzi di informazioni ottenere:",
        "apihelp-parse-example-text": "Analizza wikitext.",
        "apihelp-parse-example-texttitle": "Analizza wikitext, specificando il titolo della pagina.",
        "apihelp-parse-example-summary": "Analizza un oggetto.",
+       "apihelp-patrol-description": "Verifica una pagina o versione.",
+       "apihelp-patrol-param-rcid": "ID della modifica recente da verificare.",
+       "apihelp-patrol-param-revid": "ID versione da verificare.",
        "apihelp-patrol-param-tags": "Modifica etichette da applicare all'elemento del registro delle verifiche.",
+       "apihelp-patrol-example-rcid": "Verifica una modifica recente.",
+       "apihelp-patrol-example-revid": "Verifica una versione.",
+       "apihelp-protect-description": "Modifica il livello di protezione di una pagina.",
+       "apihelp-protect-param-title": "Titolo della pagina da (s)proteggere. Non può essere usato insieme a <var>$1pageid</var>.",
+       "apihelp-protect-param-pageid": "ID della pagina da (s)proteggere. Non può essere usato insieme con $1title.",
        "apihelp-protect-param-tags": "Modifica etichette da applicare all'elemento del registro delle protezioni.",
        "apihelp-protect-example-protect": "Proteggi una pagina.",
+       "apihelp-protect-example-unprotect": "Sproteggi una pagina impostando restrizione su <kbd>all</kbd>.",
+       "apihelp-protect-example-unprotect2": "Sproteggi una pagina impostando nessuna restrizione.",
+       "apihelp-purge-param-forcelinkupdate": "Aggiorna la tabella dei collegamenti.",
+       "apihelp-purge-param-forcerecursivelinkupdate": "Aggiorna la tabella dei collegamenti per questa pagina, e per ogni pagina che usa questa pagina come template.",
+       "apihelp-query-param-list": "Quali elenchi ottenere.",
+       "apihelp-query-param-meta": "Quali metadati ottenere.",
        "apihelp-query-param-export": "Esporta la versione attuale di tutte le pagine ottenute o generate.",
+       "apihelp-query+allcategories-description": "Enumera tutte le categorie.",
+       "apihelp-query+allcategories-param-from": "La categoria da cui iniziare l'elenco.",
+       "apihelp-query+allcategories-param-to": "La categoria al quale interrompere l'elenco.",
+       "apihelp-query+allcategories-param-prefix": "Ricerca per tutti i titoli delle categorie che iniziano con questo valore.",
        "apihelp-query+allcategories-param-dir": "Direzione dell'ordinamento.",
+       "apihelp-query+allcategories-param-limit": "Quante categorie restituire.",
        "apihelp-query+allcategories-param-prop": "Quali proprietà ottenere:",
+       "apihelp-query+allcategories-paramvalue-prop-size": "Aggiungi il numero di pagine nella categoria.",
+       "apihelp-query+allcategories-paramvalue-prop-hidden": "Etichetta categorie che sono nascoste con <code>_&#95;HIDDENCAT_&#95;</code>.",
+       "apihelp-query+allcategories-example-size": "Elenca categorie con informazioni sul numero di pagine in ognuna.",
+       "apihelp-query+alldeletedrevisions-description": "Elenca tutte le versioni cancellate da un utente o in un namespace.",
+       "apihelp-query+alldeletedrevisions-paraminfo-useronly": "Può essere utilizzato solo con <var>$3user</var>.",
+       "apihelp-query+alldeletedrevisions-paraminfo-nonuseronly": "Non può essere utilizzato con <var>$3user</var>.",
+       "apihelp-query+alldeletedrevisions-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+alldeletedrevisions-param-end": "Il timestamp al quale interrompere l'elenco.",
+       "apihelp-query+alldeletedrevisions-param-from": "Inizia elenco a questo titolo.",
+       "apihelp-query+alldeletedrevisions-param-to": "Interrompi elenco a questo titolo.",
+       "apihelp-query+alldeletedrevisions-param-prefix": "Ricerca per tutti i titoli delle pagine che iniziano con questo valore.",
+       "apihelp-query+alldeletedrevisions-param-user": "Elenca solo le versioni di questo utente.",
+       "apihelp-query+alldeletedrevisions-param-excludeuser": "Non elencare le versioni di questo utente.",
+       "apihelp-query+alldeletedrevisions-param-namespace": "Elenca solo le pagine in questo namespace.",
+       "apihelp-query+alldeletedrevisions-example-user": "Elenca gli ultimi 50 contributi cancellati dell'utente <kbd>Example</kbd>.",
+       "apihelp-query+alldeletedrevisions-example-ns-main": "Elenca le prime 50 versioni cancellate nel namespace principale.",
+       "apihelp-query+allfileusages-param-from": "Il titolo del file da cui iniziare l'elenco.",
+       "apihelp-query+allfileusages-param-to": "Il titolo del file al quale interrompere l'elenco.",
+       "apihelp-query+allfileusages-param-prefix": "Ricerca per tutti i titoli dei file che iniziano con questo valore.",
+       "apihelp-query+allfileusages-param-prop": "Quali pezzi di informazioni includere:",
        "apihelp-query+allfileusages-paramvalue-prop-title": "Aggiunge il titolo del file.",
        "apihelp-query+allfileusages-param-limit": "Quanti elementi totali restituire.",
        "apihelp-query+allfileusages-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+allfileusages-example-generator": "Ottieni le pagine contenenti i file.",
        "apihelp-query+allimages-param-sort": "Proprietà di ordinamento.",
        "apihelp-query+allimages-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+allimages-param-from": "Il titolo dell'immagine da cui iniziare l'elenco. Può essere utilizzato solo con $1sort=name.",
+       "apihelp-query+allimages-param-start": "Il timestamp da cui iniziare l'elenco. Può essere utilizzato solo con $1sort=timestamp.",
+       "apihelp-query+allimages-param-end": "Il timestamp al quale interrompere l'elenco. Può essere utilizzato solo con $1sort=timestamp.",
+       "apihelp-query+allimages-param-limit": "Quante immagini in totale restituire.",
+       "apihelp-query+allimages-example-B": "Mostra un elenco di file a partire dalla lettera <kbd>B</kbd>.",
+       "apihelp-query+alllinks-description": "Elenca tutti i collegamenti che puntano ad un namespace indicato.",
+       "apihelp-query+alllinks-param-from": "Il titolo del collegamento da cui iniziare l'elenco.",
+       "apihelp-query+alllinks-param-to": "Il titolo del collegamento al quale interrompere l'elenco.",
+       "apihelp-query+alllinks-param-prefix": "Ricerca per tutti i titoli dei collegamenti che iniziano con questo valore.",
+       "apihelp-query+alllinks-param-prop": "Quali pezzi di informazioni includere:",
+       "apihelp-query+alllinks-paramvalue-prop-ids": "Aggiunge l'ID pagina della pagina collegata (non può essere usato con <var>$1unique</var>).",
        "apihelp-query+alllinks-paramvalue-prop-title": "Aggiunge il titolo del collegamento.",
+       "apihelp-query+alllinks-param-namespace": "Il namespace da elencare.",
        "apihelp-query+alllinks-param-limit": "Quanti elementi totali restituire.",
        "apihelp-query+alllinks-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+alllinks-example-generator": "Ottieni le pagine contenenti i collegamenti.",
+       "apihelp-query+allmessages-description": "Restituisce messaggi da questo sito.",
+       "apihelp-query+allmessages-param-prop": "Quali proprietà ottenere.",
        "apihelp-query+allmessages-param-lang": "Restituisci messaggi in questa lingua.",
+       "apihelp-query+allmessages-param-prefix": "Restituisci messaggi con questo prefisso.",
+       "apihelp-query+allpages-param-from": "Il titolo di pagina da cui iniziare l'elenco.",
+       "apihelp-query+allpages-param-to": "Il titolo di pagina al quale interrompere l'elenco.",
+       "apihelp-query+allpages-param-prefix": "Ricerca per tutti i titoli delle pagine che iniziano con questo valore.",
+       "apihelp-query+allpages-param-namespace": "Il namespace da elencare.",
        "apihelp-query+allpages-param-filterredir": "Quali pagine elencare.",
+       "apihelp-query+allpages-param-limit": "Quante pagine totali restituire.",
        "apihelp-query+allpages-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+allredirects-param-from": "Il titolo del reindirizzamento da cui iniziare l'elenco.",
+       "apihelp-query+allredirects-param-prop": "Quali pezzi di informazioni includere:",
        "apihelp-query+allredirects-paramvalue-prop-title": "Aggiunge il titolo del redirect.",
+       "apihelp-query+allredirects-param-namespace": "Il namespace da elencare.",
        "apihelp-query+allredirects-param-limit": "Quanti elementi totali restituire.",
        "apihelp-query+allredirects-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+allredirects-example-generator": "Ottieni le pagine contenenti i reindirizzamenti.",
        "apihelp-query+allrevisions-description": "Elenco di tutte le versioni.",
+       "apihelp-query+allrevisions-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+allrevisions-param-end": "Il timestamp al quale interrompere l'elenco.",
        "apihelp-query+allrevisions-param-user": "Elenca solo le versioni di questo utente.",
        "apihelp-query+allrevisions-param-excludeuser": "Non elencare le versioni di questo utente.",
        "apihelp-query+allrevisions-param-namespace": "Elenca solo le pagine in questo namespace.",
        "apihelp-query+mystashedfiles-paramvalue-prop-size": "Recupera la dimensione del file e le dimensioni dell'immagine.",
        "apihelp-query+mystashedfiles-paramvalue-prop-type": "Recupera il tipo MIME del file e il tipo media.",
        "apihelp-query+mystashedfiles-param-limit": "Quanti file restituire.",
+       "apihelp-query+alltransclusions-description": "Elenca tutte le inclusioni (pagine incorporate utilizzando &#123;&#123;x&#125;&#125;), comprese le non esistenti.",
+       "apihelp-query+alltransclusions-param-from": "Il titolo dell'inclusione da cui iniziare l'elenco.",
+       "apihelp-query+alltransclusions-param-prop": "Quali pezzi di informazioni includere:",
        "apihelp-query+alltransclusions-paramvalue-prop-title": "Aggiunge il titolo dell'inclusione.",
+       "apihelp-query+alltransclusions-param-namespace": "Il namespace da elencare.",
        "apihelp-query+alltransclusions-param-limit": "Quanti elementi totali restituire.",
        "apihelp-query+alltransclusions-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+alltransclusions-example-generator": "Ottieni pagine contenenti le inclusioni.",
+       "apihelp-query+allusers-param-from": "Il nome utente da cui iniziare l'elenco.",
+       "apihelp-query+allusers-param-to": "Il nome utente al quale interrompere l'elenco.",
+       "apihelp-query+allusers-param-prefix": "Ricerca per tutti gli utenti che iniziano con questo valore.",
        "apihelp-query+allusers-param-dir": "Direzione dell'ordinamento.",
+       "apihelp-query+allusers-param-group": "Includi solo gli utenti nei gruppi indicati.",
+       "apihelp-query+allusers-param-excludegroup": "Escludi gli utenti nei gruppi indicati.",
+       "apihelp-query+allusers-param-prop": "Quali pezzi di informazioni includere:",
+       "apihelp-query+allusers-param-limit": "Quanti nomi utente totali restituire.",
        "apihelp-query+backlinks-description": "Trova tutte le pagine che puntano a quella specificata.",
+       "apihelp-query+backlinks-param-namespace": "Il namespace da elencare.",
        "apihelp-query+backlinks-param-dir": "La direzione in cui elencare.",
        "apihelp-query+backlinks-param-redirect": "Se la pagina collegata è un redirect, trova tutte le pagine che puntano al redirect. Il limite massimo è dimezzato.",
+       "apihelp-query+backlinks-example-simple": "Mostra collegamenti a <kbd>Main page</kbd>.",
+       "apihelp-query+blocks-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+blocks-param-end": "Il timestamp al quale interrompere l'elenco.",
+       "apihelp-query+blocks-param-limit": "Il numero massimo di blocchi da elencare.",
        "apihelp-query+blocks-param-prop": "Quali proprietà ottenere:",
+       "apihelp-query+blocks-paramvalue-prop-id": "Aggiunge l'ID del blocco.",
+       "apihelp-query+blocks-paramvalue-prop-user": "Aggiunge il nome utente dell'utente bloccato.",
        "apihelp-query+blocks-paramvalue-prop-userid": "Aggiunge l'ID utente dell'utente bloccato.",
+       "apihelp-query+blocks-paramvalue-prop-by": "Aggiunge il nome utente dell'utente che ha effettuato il blocco.",
        "apihelp-query+blocks-paramvalue-prop-byid": "Aggiunge l'ID utente dell'utente che ha effettuato il blocco.",
        "apihelp-query+blocks-example-simple": "Elenca i blocchi.",
+       "apihelp-query+categories-param-show": "Quale tipo di categorie mostrare.",
+       "apihelp-query+categories-param-limit": "Quante categorie restituire.",
        "apihelp-query+categories-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+categoryinfo-description": "Restituisce informazioni su una categoria indicata.",
+       "apihelp-query+categoryinfo-example-simple": "Ottieni informazioni su <kbd>Category:Foo</kbd> e <kbd>Category:Bar</kbd>.",
+       "apihelp-query+categorymembers-description": "Elenca tutte le pagine in una categoria indicata.",
+       "apihelp-query+categorymembers-param-prop": "Quali pezzi di informazioni includere:",
+       "apihelp-query+categorymembers-paramvalue-prop-ids": "Aggiunge l'ID pagina.",
        "apihelp-query+categorymembers-paramvalue-prop-title": "Aggiunge il titolo e l'ID namespace della pagina.",
        "apihelp-query+categorymembers-paramvalue-prop-type": "Aggiunge il tipo di come la pagina è stata categorizzata (<samp>page</samp>, <samp>subcat</samp> o <samp>file</samp>).",
        "apihelp-query+categorymembers-param-namespace": "Includi solo le pagine in questi namespace. Nota che può essere usato <kbd>$1type=subcat</kbd> o <kbd>$1type=file</kbd> anziché <kbd>$1namespace=14</kbd> o <kbd>6</kbd>.",
+       "apihelp-query+categorymembers-param-limit": "Il numero massimo di pagine da restituire.",
+       "apihelp-query+categorymembers-param-sort": "Proprietà di ordinamento.",
+       "apihelp-query+categorymembers-param-dir": "In quale direzione ordinare.",
+       "apihelp-query+categorymembers-param-start": "Il timestamp da cui iniziare l'elenco. Può essere utilizzato solo con <kbd>$1sort=timestamp</kbd>.",
+       "apihelp-query+categorymembers-param-end": "Il timestamp al quale interrompere l'elenco. Può essere utilizzato solo con <kbd>$1sort=timestamp</kbd>.",
+       "apihelp-query+categorymembers-param-startsortkey": "Usa $1starthexsortkey invece.",
+       "apihelp-query+categorymembers-param-endsortkey": "Usa $1endhexsortkey invece.",
+       "apihelp-query+categorymembers-example-simple": "Ottieni le prime 10 pagine in <kbd>Category:Physics</kbd>.",
+       "apihelp-query+categorymembers-example-generator": "Ottieni informazioni sulle prime 10 pagine in <kbd>Category:Physics</kbd>.",
+       "apihelp-query+contributors-param-limit": "Quanti contributi restituire.",
+       "apihelp-query+deletedrevisions-param-start": "Il timestamp da cui iniziare l'elenco. Ignorato quando si elabora un elenco di ID versioni.",
+       "apihelp-query+deletedrevisions-param-end": "Il timestamp al quale interrompere l'elenco. Ignorato quando si elabora un elenco di ID versioni.",
+       "apihelp-query+deletedrevisions-param-tag": "Elenca solo le versioni etichettate con questa etichetta.",
+       "apihelp-query+deletedrevisions-param-user": "Elenca solo le versioni di questo utente.",
+       "apihelp-query+deletedrevisions-param-excludeuser": "Non elencare le versioni di questo utente.",
+       "apihelp-query+deletedrevisions-example-titles": "Elenca le versioni cancellate delle pagine <kbd>Main Page</kbd> e <kbd>Talk:Main Page</kbd>, con il contenuto.",
+       "apihelp-query+deletedrevisions-example-revids": "Elenca le informazioni per la versione cancellata <kbd>123456</kbd>.",
+       "apihelp-query+deletedrevs-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+deletedrevs-param-end": "Il timestamp al quale interrompere l'elenco.",
+       "apihelp-query+deletedrevs-param-from": "Inizia elenco a questo titolo.",
+       "apihelp-query+deletedrevs-param-to": "Interrompi elenco a questo titolo.",
+       "apihelp-query+deletedrevs-param-prefix": "Ricerca per tutti i titoli delle pagine che iniziano con questo valore.",
+       "apihelp-query+deletedrevs-param-unique": "Elenca solo una versione per ogni pagina.",
+       "apihelp-query+deletedrevs-param-tag": "Elenca solo le versioni etichettate con questa etichetta.",
+       "apihelp-query+deletedrevs-param-user": "Elenca solo le versioni di questo utente.",
+       "apihelp-query+deletedrevs-param-excludeuser": "Non elencare le versioni di questo utente.",
+       "apihelp-query+deletedrevs-param-namespace": "Elenca solo le pagine in questo namespace.",
+       "apihelp-query+deletedrevs-param-limit": "Il numero massimo di versioni da elencare.",
+       "apihelp-query+disabled-description": "Questo modulo query è stato disabilitato.",
+       "apihelp-query+duplicatefiles-param-limit": "Quanti file duplicati restituire.",
        "apihelp-query+duplicatefiles-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+duplicatefiles-example-simple": "Cerca i duplicati di [[:File:Albert Einstein Head.jpg]].",
+       "apihelp-query+duplicatefiles-example-generated": "Cerca i duplicati di tutti i file.",
        "apihelp-query+embeddedin-description": "Trova tutte le pagine che incorporano (transclusione) il titolo specificato.",
+       "apihelp-query+embeddedin-param-namespace": "Il namespace da elencare.",
        "apihelp-query+embeddedin-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+embeddedin-param-limit": "Quante pagine totali restituire.",
+       "apihelp-query+extlinks-param-limit": "Quanti collegamenti restituire.",
+       "apihelp-query+exturlusage-param-prop": "Quali pezzi di informazioni includere:",
+       "apihelp-query+exturlusage-paramvalue-prop-ids": "Aggiunge l'ID della pagina.",
        "apihelp-query+exturlusage-paramvalue-prop-title": "Aggiunge il titolo e l'ID namespace della pagina.",
+       "apihelp-query+exturlusage-paramvalue-prop-url": "Aggiunge l'URL utilizzato nella pagina.",
+       "apihelp-query+exturlusage-param-namespace": "I namespace da elencare.",
+       "apihelp-query+exturlusage-param-limit": "Quante pagine restituire.",
+       "apihelp-query+filearchive-param-from": "Il titolo dell'immagine da cui iniziare l'elenco.",
+       "apihelp-query+filearchive-param-limit": "Quante immagini restituire in totale.",
        "apihelp-query+filearchive-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+filearchive-paramvalue-prop-mime": "Aggiunge MIME dell'immagine.",
+       "apihelp-query+filearchive-paramvalue-prop-bitdepth": "Aggiunge la profondità di bit della versione.",
        "apihelp-query+filearchive-example-simple": "Mostra un elenco di tutti i file cancellati.",
        "apihelp-query+fileusage-description": "Trova tutte le pagine che utilizzano il file specificato.",
        "apihelp-query+fileusage-param-prop": "Quali proprietà ottenere:",
        "apihelp-query+fileusage-param-namespace": "Includi solo le pagine in questi namespace.",
        "apihelp-query+fileusage-param-show": "Mostra solo gli elementi che soddisfano questi criteri:\n;redirect:mostra solo i redirect.\n;!redirect:mostra solo i non redirect.",
        "apihelp-query+fileusage-example-simple": "Ottieni un elenco di pagine che usano [[:File:Example.jpg]].",
+       "apihelp-query+imageinfo-paramvalue-prop-mime": "Aggiunge il tipo MIME del file.",
+       "apihelp-query+imageinfo-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+imageinfo-param-urlheight": "Simile a $1urlwidth.",
+       "apihelp-query+images-param-limit": "Quanti file restituire.",
        "apihelp-query+images-param-dir": "La direzione in cui elencare.",
        "apihelp-query+images-example-simple": "Ottieni un elenco di file usati in [[Main Page]].",
        "apihelp-query+imageusage-description": "Trova tutte le pagine che utilizzano il titolo dell'immagine specificato.",
+       "apihelp-query+imageusage-param-namespace": "Il namespace da elencare.",
        "apihelp-query+imageusage-param-dir": "La direzione in cui elencare.",
        "apihelp-query+imageusage-param-redirect": "Se la pagina collegata è un redirect, trova tutte le pagine che puntano al redirect. Il limite massimo è dimezzato.",
        "apihelp-query+info-paramvalue-prop-visitingwatchers": "Il numero di osservatori di ogni pagina che hanno visitato le ultime modifiche alla pagina, se consentito.",
+       "apihelp-query+iwbacklinks-param-prefix": "Prefisso per l'interwiki.",
+       "apihelp-query+iwbacklinks-param-limit": "Quante pagine totali restituire.",
        "apihelp-query+iwbacklinks-param-prop": "Quali proprietà ottenere:",
+       "apihelp-query+iwbacklinks-paramvalue-prop-iwprefix": "Aggiunge il prefisso dell'interwiki.",
        "apihelp-query+iwbacklinks-paramvalue-prop-iwtitle": "Aggiunge il titolo dell'interwiki.",
        "apihelp-query+iwbacklinks-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+iwlinks-description": "Restituisce tutti i collegamenti interwiki dalle pagine indicate.",
+       "apihelp-query+iwlinks-paramvalue-prop-url": "Aggiunge l'URL completo.",
+       "apihelp-query+iwlinks-param-limit": "Quanti collegamenti interwiki restituire.",
        "apihelp-query+iwlinks-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+langbacklinks-param-limit": "Quante pagine totali restituire.",
        "apihelp-query+langbacklinks-param-prop": "Quali proprietà ottenere:",
        "apihelp-query+langbacklinks-paramvalue-prop-lltitle": "Aggiunge il titolo del collegamento linguistico.",
        "apihelp-query+langbacklinks-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+langlinks-paramvalue-prop-url": "Aggiunge l'URL completo.",
        "apihelp-query+langlinks-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+links-param-namespace": "Mostra collegamenti solo in questi namespace.",
+       "apihelp-query+links-param-limit": "Quanti collegamenti restituire.",
        "apihelp-query+links-param-dir": "La direzione in cui elencare.",
        "apihelp-query+linkshere-description": "Trova tutte le pagine che puntano a quelle specificate.",
        "apihelp-query+linkshere-param-prop": "Quali proprietà ottenere:",
        "apihelp-query+linkshere-example-simple": "Ottieni un elenco di pagine che puntano a [[Main Page]].",
        "apihelp-query+logevents-param-prop": "Quali proprietà ottenere:",
        "apihelp-query+logevents-paramvalue-prop-title": "Aggiunge il titolo della pagine per l'evento nel registro.",
+       "apihelp-query+logevents-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+logevents-param-end": "Il timestamp al quale interrompere l'elenco.",
+       "apihelp-query+pageswithprop-param-prop": "Quali pezzi di informazioni includere:",
+       "apihelp-query+pageswithprop-paramvalue-prop-ids": "Aggiunge l'ID pagina.",
        "apihelp-query+pageswithprop-paramvalue-prop-title": "Aggiunge il titolo e l'ID namespace della pagina.",
+       "apihelp-query+pageswithprop-paramvalue-prop-value": "Aggiunge il valore della proprietà di pagina.",
+       "apihelp-query+pageswithprop-param-limit": "Il numero massimo di pagine da restituire.",
+       "apihelp-query+pageswithprop-param-dir": "In quale direzione ordinare.",
+       "apihelp-query+prefixsearch-param-search": "Stringa di ricerca.",
+       "apihelp-query+prefixsearch-param-limit": "Numero massimo di risultati da restituire.",
+       "apihelp-query+prefixsearch-param-offset": "Numero di risultati da saltare",
+       "apihelp-query+protectedtitles-description": "Elenca tutti i titoli protetti dalla creazione.",
+       "apihelp-query+protectedtitles-param-namespace": "Elenca solo i titoli in questi namespace.",
+       "apihelp-query+protectedtitles-param-level": "Elenca solo i titoli con questi livelli di protezione.",
+       "apihelp-query+protectedtitles-param-limit": "Quante pagine totali restituire.",
        "apihelp-query+protectedtitles-param-prop": "Quali proprietà ottenere:",
+       "apihelp-query+protectedtitles-paramvalue-prop-user": "Aggiunge l'utente che ha aggiunto la protezione.",
        "apihelp-query+protectedtitles-paramvalue-prop-userid": "Aggiunge l'ID utente che ha aggiunto la protezione.",
+       "apihelp-query+protectedtitles-paramvalue-prop-comment": "Aggiunge il commento per la protezione.",
        "apihelp-query+protectedtitles-paramvalue-prop-level": "Aggiunge il livello di protezione.",
        "apihelp-query+protectedtitles-example-generator": "Trova collegamenti a titoli protetti nel namespace principale.",
+       "apihelp-query+querypage-param-limit": "Numero di risultati da restituire.",
+       "apihelp-query+querypage-example-ancientpages": "Restituisce risultati da [[Special:Ancientpages|Speciale:PagineMenoRecenti]].",
+       "apihelp-query+random-param-namespace": "Restituisci le pagine solo in questi namespace.",
+       "apihelp-query+random-param-redirect": "Usa <kbd>$1filterredir=redirects</kbd> invece.",
+       "apihelp-query+random-example-simple": "Restituisce due pagine casuali dal namespace principale.",
+       "apihelp-query+recentchanges-description": "Elenca le modifiche recenti.",
+       "apihelp-query+recentchanges-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+recentchanges-param-end": "Il timestamp al quale interrompere l'elenco.",
        "apihelp-query+recentchanges-example-simple": "Elenco modifiche recenti.",
+       "apihelp-query+redirects-description": "Restituisce tutti i reindirizzamenti alla data indicata.",
        "apihelp-query+redirects-param-prop": "Quali proprietà ottenere:",
        "apihelp-query+redirects-paramvalue-prop-pageid": "ID pagina di ogni redirect.",
        "apihelp-query+redirects-paramvalue-prop-title": "Titolo di ogni redirect.",
        "apihelp-query+redirects-param-namespace": "Includi solo le pagine in questi namespace.",
+       "apihelp-query+redirects-param-limit": "Quanti reindirizzamenti restituire.",
        "apihelp-query+redirects-example-simple": "Ottieni un elenco di redirect a [[Main Page]].",
+       "apihelp-query+revisions-param-startid": "L'ID versione da cui iniziare l'elenco.",
+       "apihelp-query+revisions-param-start": "Il timestamp della versione da cui iniziare l'elenco.",
+       "apihelp-query+revisions-param-tag": "Elenca solo le versioni etichettate con questa etichetta.",
        "apihelp-query+revisions+base-paramvalue-prop-ids": "L'ID della versione.",
+       "apihelp-query+revisions+base-paramvalue-prop-timestamp": "Il timestamp della versione.",
        "apihelp-query+revisions+base-paramvalue-prop-content": "Testo della versione.",
        "apihelp-query+revisions+base-paramvalue-prop-tags": "Etichette della versione.",
+       "apihelp-query+search-param-what": "Quale tipo di ricerca effettuare.",
+       "apihelp-query+search-param-info": "Quali metadati restituire.",
+       "apihelp-query+search-param-prop": "Quali proprietà restituire.",
+       "apihelp-query+search-paramvalue-prop-size": "Aggiungi la dimensione della pagina in byte.",
+       "apihelp-query+search-paramvalue-prop-wordcount": "Aggiungi il conteggio delle parole nella pagina.",
+       "apihelp-query+search-paramvalue-prop-timestamp": "Aggiungi il timestamp di quando la pagina è stata modificata l'ultima volta.",
        "apihelp-query+search-paramvalue-prop-redirecttitle": "Aggiunge il titolo del redirect corrispondente.",
        "apihelp-query+search-paramvalue-prop-sectiontitle": "Aggiunge il titolo della sezione corrispondente.",
+       "apihelp-query+search-param-limit": "Quante pagine totali restituire.",
+       "apihelp-query+siteinfo-param-prop": "Quali informazioni ottenere:",
+       "apihelp-query+siteinfo-paramvalue-prop-libraries": "Restituisci librerie installate sul wiki.",
+       "apihelp-query+siteinfo-paramvalue-prop-extensions": "Restituisci estensioni installate sul wiki.",
        "apihelp-query+siteinfo-paramvalue-prop-restrictions": "Restituisce informazioni sui tipi di restrizione (protezione) disponibili.",
        "apihelp-query+tags-param-prop": "Quali proprietà ottenere:",
+       "apihelp-query+templates-param-limit": "Quanti template restituire.",
        "apihelp-query+templates-param-dir": "La direzione in cui elencare.",
+       "apihelp-query+tokens-param-type": "Tipi di token da richiedere.",
        "apihelp-query+tokens-example-simple": "Recupera un token csrf (il predefinito).",
        "apihelp-query+transcludedin-description": "Trova tutte le pagine che incorporano quella specificata.",
        "apihelp-query+transcludedin-param-prop": "Quali proprietà ottenere:",
        "apihelp-query+transcludedin-param-namespace": "Includi solo le pagine in questi namespace.",
        "apihelp-query+transcludedin-param-show": "Mostra solo gli elementi che soddisfano questi criteri:\n;redirect:mostra solo i redirect.\n;!redirect:mostra solo i non redirect.",
        "apihelp-query+transcludedin-example-simple": "Ottieni un elenco di pagine che includono <kbd>Main Page</kbd>.",
+       "apihelp-query+usercontribs-param-namespace": "Elenca solo i contributi in questi namespace.",
        "apihelp-query+usercontribs-paramvalue-prop-title": "Aggiunge il titolo e l'ID namespace della pagina.",
+       "apihelp-query+usercontribs-paramvalue-prop-patrolled": "Etichetta modifiche verificate",
        "apihelp-query+userinfo-description": "Ottieni informazioni sull'utente attuale.",
        "apihelp-query+userinfo-paramvalue-prop-blockinfo": "Etichetta se l'utente attuale è bloccato, da chi e per quale motivo.",
        "apihelp-query+userinfo-paramvalue-prop-hasmsg": "Aggiunge un'etichetta <samp>messages</samp> se l'utente attuale ha messaggi in attesa.",
        "apihelp-query+userinfo-paramvalue-prop-implicitgroups": "Elenca tutti i gruppi di cui l'utente attuale è automaticamente membro.",
        "apihelp-query+userinfo-paramvalue-prop-changeablegroups": "Elenca tutti i gruppi di cui l'utente attuale può essere aggiunto o rimosso.",
+       "apihelp-query+userinfo-paramvalue-prop-realname": "Aggiungi il nome reale dell'utente.",
+       "apihelp-query+userinfo-paramvalue-prop-registrationdate": "Aggiungi la data di registrazione dell'utente.",
        "apihelp-query+userinfo-example-simple": "Ottieni informazioni sull'utente attuale.",
        "apihelp-query+users-description": "Ottieni informazioni su un elenco di utenti.",
+       "apihelp-query+users-param-prop": "Quali pezzi di informazioni includere:",
        "apihelp-query+users-param-users": "Un elenco di utenti di cui ottenere informazioni.",
        "apihelp-query+watchlist-description": "Ottieni le ultime modifiche alle pagine tra gli osservati speciali dell'utente attuale.",
+       "apihelp-query+watchlist-param-start": "Il timestamp da cui iniziare l'elenco.",
+       "apihelp-query+watchlist-param-end": "Il timestamp al quale interrompere l'elenco.",
+       "apihelp-query+watchlist-param-prop": "Quali proprietà aggiuntive ottenere:",
+       "apihelp-query+watchlist-paramvalue-prop-ids": "Aggiunge l'ID versione e l'ID pagina.",
+       "apihelp-query+watchlist-paramvalue-prop-title": "Aggiungi il titolo della pagina.",
+       "apihelp-query+watchlistraw-param-namespace": "Elenca solo le pagine nei namespace indicati.",
+       "apihelp-query+watchlistraw-param-fromtitle": "Il titolo (con prefisso namespace) da cui iniziare l'elenco.",
+       "apihelp-query+watchlistraw-param-totitle": "Il titolo (con prefisso namespace) al quale interrompere l'elenco.",
        "apihelp-query+watchlistraw-example-simple": "Elenca le pagine fra gli osservati speciali dell'utente attuale.",
        "apihelp-query+watchlistraw-example-generator": "Recupera le informazioni sulle pagine fra gli osservati speciali dell'utente attuale.",
+       "apihelp-stashedit-param-sectiontitle": "Il titolo per una nuova sezione.",
+       "apihelp-stashedit-param-text": "Contenuto della pagina.",
+       "apihelp-stashedit-param-contentmodel": "Modello di contenuto dei nuovi contenuti.",
        "apihelp-tokens-param-type": "Tipi di token da richiedere.",
        "apihelp-tokens-example-edit": "Recupera un token di modifica (il predefinito).",
        "apihelp-unblock-description": "Sblocca un utente",
        "apihelp-unblock-param-tags": "Modifica etichette da applicare all'elemento del registro dei blocchi.",
        "apihelp-undelete-param-title": "Titolo della pagina da ripristinare.",
        "apihelp-undelete-param-tags": "Modifica etichette da applicare all'elemento del registro delle cancellazioni.",
+       "apihelp-upload-param-file": "Contenuto del file.",
        "apihelp-upload-example-url": "Carica da un URL.",
        "apihelp-userrights-param-user": "Nome utente.",
        "apihelp-userrights-param-userid": "ID utente.",
+       "apihelp-userrights-param-add": "Aggiungi l'utente a questi gruppi.",
+       "apihelp-userrights-param-remove": "Rimuovi l'utente da questi gruppi.",
+       "apihelp-userrights-param-reason": "Motivo del cambiamento.",
        "apihelp-watch-description": "Aggiunge o rimuove pagine dagli osservati speciali dell'utente attuale.",
        "apihelp-format-param-wrappedhtml": "Restituisce l'HTML ben formattato e i moduli ResourceLoader associati come un oggetto JSON.",
        "api-pageset-param-titles": "Un elenco di titoli su cui lavorare.",
        "api-pageset-param-pageids": "Un elenco di ID pagina su cui lavorare.",
        "api-pageset-param-revids": "Un elenco di ID versioni su cui lavorare.",
        "api-pageset-param-redirects-generator": "Risolvi automaticamente redirect in <var>$1titles</var>, <var>$1pageids</var>, e <var>$1revids</var>, e nelle pagine restituite da <var>$1generator</var>.",
+       "api-pageset-param-redirects-nogenerator": "Risolve automaticamente i reindirizzamenti in <var>$1titles</var>, <var>$1pageids</var>, e <var>$1revids</var>.",
        "api-pageset-param-converttitles": "Converte i titoli in altre varianti, se necessario. Funziona solo se la lingua del contenuto del wiki supporta la conversione in varianti. Le lingue che supportano la conversione in varianti includono $1",
        "api-help-main-header": "Modulo principale",
+       "api-help-flag-deprecated": "Questo modulo è deprecato.",
+       "api-help-flag-internal": "<strong>Questo modulo è interno o instabile.</strong> Il suo funzionamento potrebbe variare senza preavviso.",
+       "api-help-flag-readrights": "Questo modulo richiede i diritti di lettura.",
+       "api-help-flag-writerights": "Questo modulo richiede i diritti di scrittura.",
+       "api-help-flag-mustbeposted": "Questo modulo accetta solo richieste POST.",
+       "api-help-flag-generator": "Questo modulo può essere utilizzato come generatore.",
+       "api-help-source": "Fonte: $1",
+       "api-help-source-unknown": "Fonte: <span class=\"apihelp-unknown\">sconosciuta</span>",
        "api-help-license": "Licenza: [[$1|$2]]",
+       "api-help-license-noname": "Licenza: [[$1|Vedi collegamento]]",
        "api-help-license-unknown": "Licenza: <span class=\"apihelp-unknown\">sconosciuta</span>",
        "api-help-parameters": "{{PLURAL:$1|Parametro|Parametri}}:",
        "api-help-param-deprecated": "Deprecato.",
        "api-help-param-required": "Questo parametro è obbligatorio.",
+       "api-help-datatypes-header": "Tipi di dato",
+       "api-help-param-type-limit": "Tipo: intero o <kbd>max</kbd>",
+       "api-help-param-type-integer": "Tipo: {{PLURAL:$1|1=intero|2=elenco di interi}}",
+       "api-help-param-type-boolean": "Tipo: booleano ([[Special:ApiHelp/main#main/datatypes|dettagli]])",
+       "api-help-param-type-timestamp": "Tipo: {{PLURAL:$1|1=timestamp|2=elenco di timestamp}} ([[Special:ApiHelp/main#main/datatypes|formati consentiti]])",
        "api-help-param-type-user": "Tipo: {{PLURAL:$1|1=nome utente|2=elenco di nomi utente}}",
        "api-help-param-list": "{{PLURAL:$1|1=Uno dei seguenti valori|2=Valori (separati da <kbd>{{!}}</kbd>)}}: $2",
+       "api-help-param-list-can-be-empty": "{{PLURAL:$1|0=Deve essere vuoto|Può essere vuoto, o $2}}",
+       "api-help-param-limit": "Non più di $1 consentito.",
+       "api-help-param-limit2": "Non più di $1 ($2 per bot) consentito.",
+       "api-help-param-integer-min": "{{PLURAL:$1|1=Il valore non deve essere inferiore|2=I valori non devono essere inferiori}} a $2.",
+       "api-help-param-integer-max": "{{PLURAL:$1|1=Il valore non deve essere superiore|2=I valori non devono essere superiori}} a $3.",
+       "api-help-param-integer-minmax": "{{PLURAL:$1|1=Il valore deve essere compreso|2=I valori devono essere compresi}} tra $2 e $3.",
+       "api-help-param-multi-separate": "Separa i valori con <kbd>|</kbd>.",
        "api-help-param-multi-max": "Il numero massimo di valori è {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} per i bot).",
        "api-help-param-default": "Predefinito: $1",
        "api-help-param-default-empty": "Predefinito: <span class=\"apihelp-empty\">(vuoto)</span>",
index 04a7554..d6596b1 100644 (file)
        "apihelp-feedrecentchanges-example-30days": "最近30日間の変更を表示する。",
        "apihelp-feedwatchlist-description": "ウォッチリストのフィードを返します。",
        "apihelp-feedwatchlist-param-feedformat": "フィードの形式。",
+       "apihelp-feedwatchlist-param-linktosections": "可能であれば、変更された節に直接リンクする。",
        "apihelp-feedwatchlist-example-default": "ウォッチリストのフィードを表示する。",
        "apihelp-feedwatchlist-example-all6hrs": "ウォッチ中のページに対する過去6時間の更新をすべて表示する。",
        "apihelp-filerevert-description": "ファイルを古い版に差し戻します。",
        "apihelp-imagerotate-example-simple": "<kbd>File:Example.png</kbd> を <kbd>90</kbd> 度回転させる。",
        "apihelp-imagerotate-example-generator": "<kbd>Category:Flip</kbd> 内のすべての画像を <kbd>180</kbd> 度回転させる。",
        "apihelp-import-description": "他のWikiまたはXMLファイルからページを取り込む。\n\n<var>xml</var> パラメーターでファイルを送信する場合、ファイルのアップロードとしてHTTP POSTされなければならない (例えば、multipart/form-dataを使用する) 点に注意してください。",
-       "apihelp-import-param-summary": "ページ取り込みの要約。",
+       "apihelp-import-param-summary": "記録されるページ取り込みの要約。",
        "apihelp-import-param-xml": "XMLファイルをアップロード",
        "apihelp-import-param-interwikisource": "ウィキ間の取り込みの場合: 取り込み元のウィキ。",
        "apihelp-import-param-interwikipage": "ウィキ間の取り込みの場合: 取り込むページ。",
        "apihelp-import-param-namespace": "この名前空間に取り込む。<var>$1rootpage</var>パラメータとは同時に使用できません。",
        "apihelp-import-param-rootpage": "このページの下位ページとして取り込む。<var>$1namespace</var> パラメータとは同時に使用できません。",
        "apihelp-import-example-import": "[[meta:Help:ParserFunctions]] をすべての履歴とともに名前空間100に取り込む。",
+       "apihelp-login-description": "ログインして認証クッキーを取得します。\n\nログインが成功した場合、必要なクッキーは HTTP 応答ヘッダに含まれます。ログインに失敗した場合、自動化のパスワード推定攻撃を制限するために、追加の試行は速度制限されることがあります。",
        "apihelp-login-param-name": "利用者名。",
        "apihelp-login-param-password": "パスワード。",
        "apihelp-login-param-domain": "ドメイン (省略可能)",
        "apihelp-managetags-example-activate": "<kbd>spam</kbd> という名前のタグを <kbd>For use in edit patrolling</kbd> という理由で有効化する",
        "apihelp-managetags-example-deactivate": "<kbd>No longer required</kbd> という理由でタグ <kbd>spam</kbd> を無効化する",
        "apihelp-mergehistory-description": "ページの履歴を統合する。",
+       "apihelp-mergehistory-param-from": "履歴統合元のページ名。<var>$1fromid</var> とは同時に使用できません。",
+       "apihelp-mergehistory-param-fromid": "履歴統合元のページ。<var>$1from</var> とは同時に使用できません。",
+       "apihelp-mergehistory-param-to": "履歴統合先のページ名。<var>$1toid</var> とは同時に使用できません。",
+       "apihelp-mergehistory-param-toid": "履歴統合先のページID。<var>$1to</var> とは同時に使用できません。",
        "apihelp-mergehistory-param-reason": "履歴の統合の理由。",
        "apihelp-mergehistory-example-merge": "<kbd>Oldpage</kbd> のすべての履歴を <kbd>Newpage</kbd> に統合する。",
        "apihelp-move-description": "ページを移動します。",
        "apihelp-opensearch-param-format": "出力する形式。",
        "apihelp-opensearch-example-te": "<kbd>Te</kbd> から始まるページを検索する。",
        "apihelp-options-param-reset": "個人設定をサイトの既定値にリセットする。",
+       "apihelp-options-param-resetkinds": "<var>$1reset</var> が設定されている場合、リセットする設定項目の種類のリスト。",
+       "apihelp-options-param-change": "名前=値 の形式 (例えば skin=vector) で整形された変更のリスト。値はパイプ文字を含むことができません。optionname|otheroption|... のように値が与えられない (イコール記号すら無い) 場合、設定は既定値にリセットされます。",
        "apihelp-options-example-reset": "すべて初期設定に戻す。",
        "apihelp-options-example-change": "<kbd>skin</kbd> および <kbd>hideminor</kbd> の個人設定を変更する。",
        "apihelp-options-example-complex": "すべての個人設定を初期化し、<kbd>skin</kbd> および <kbd> nickname </kbd> を設定する。",
        "apihelp-paraminfo-param-helpformat": "ヘルプ文字列の形式。",
        "apihelp-paraminfo-param-querymodules": "クエリモジュール名のリスト (<var>prop</var>, <var>meta</var> or <var>list</var> パラメータの値)。<kbd>$1querymodules=foo</kbd> の代わりに <kbd>$1modules=query+foo</kbd> を使用してください。",
        "apihelp-paraminfo-example-1": "<kbd>[[Special:ApiHelp/parse|action=parse]]</kbd>, <kbd>[[Special:ApiHelp/jsonfm|format=jsonfm]]</kbd>, <kbd>[[Special:ApiHelp/query+allpages|action=query&list=allpages]]</kbd>, and <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> に関する情報を表示する。",
+       "apihelp-parse-param-title": "文字列が属するページのページ名。これを省略する場合、必ず <var>$1contentmodel</var> を指定しなければなりません。また、その場合 [[API]] がページ名として使用されます。",
+       "apihelp-parse-param-text": "構文解析する文字列。コンテンツ・モデルを制御するためには<var>$1title</var> または <var>$1contentmodel</var> を使用してください。",
        "apihelp-parse-param-summary": "構文解析のための要約",
        "apihelp-parse-param-page": "このページの内容を構文解析します。<var>$1text</var> および <var>$1title</var> とは同時に使用できません。",
+       "apihelp-parse-param-pageid": "このページの内容を構文解析する。<var>$1page</var> をオーバーライドします。",
        "apihelp-parse-param-redirects": "もし <var>$1page</var> や <var>$1pageid</var> に転送ページが指定された場合、それを解決する。",
+       "apihelp-parse-param-oldid": "この版の内容を構文解析する。<var>$1page</var> および <var>$1pageid</var> をオーバーライドします。",
        "apihelp-parse-param-prop": "どの情報を取得するか:",
        "apihelp-parse-paramvalue-prop-text": "ウィキテキストの解析されたテキストを提供します。",
        "apihelp-parse-paramvalue-prop-langlinks": "解析されたウィキテキストにおける言語リンクを提供します。",
        "apihelp-query+alldeletedrevisions-param-user": "この利用者による版のみを一覧表示する。",
        "apihelp-query+alldeletedrevisions-param-excludeuser": "この利用者による版を一覧表示しない。",
        "apihelp-query+alldeletedrevisions-param-namespace": "この名前空間に含まれるページのみを一覧表示します。",
+       "apihelp-query+alldeletedrevisions-param-miser-user-namespace": "<strong>注意:</strong> [[mw:Manual:$wgMiserMode|miser mode]] により、<var>$1user</var> と <var>$1namespace</var> を同時に使用すると継続する前に <var>$1limit</var> より返される結果が少なくなることがあります; 極端な場合では、ゼロ件の結果が返ることもあります。",
        "apihelp-query+alldeletedrevisions-param-generatetitles": "ジェネレーターとして使用する場合、版IDではなくページ名を生成します。",
        "apihelp-query+alldeletedrevisions-example-user": "利用者 <kbd>Example</kbd> による削除された直近の50版を一覧表示する。",
        "apihelp-query+alldeletedrevisions-example-ns-main": "標準名前空間にある削除された最初の50版を一覧表示する。",
        "apihelp-query+allfileusages-param-limit": "返す項目の総数。",
        "apihelp-query+allfileusages-param-dir": "一覧表示する方向。",
        "apihelp-query+allfileusages-example-unique": "ユニークなファイルを一覧表示する。",
+       "apihelp-query+allfileusages-example-unique-generator": "ファイル名を、存在しないものに印をつけて、すべて取得する。",
        "apihelp-query+allfileusages-example-generator": "ファイルを含むページを取得します。",
        "apihelp-query+allimages-description": "順次すべての画像を列挙します。",
        "apihelp-query+allimages-param-sort": "並べ替えに使用するプロパティ。",
        "apihelp-query+allimages-param-maxsize": "画像の最大バイト数を制限する。",
        "apihelp-query+allimages-param-sha1": "画像の SHA1 ハッシュ値。$1sha1base36 をオーバーライドします。",
        "apihelp-query+allimages-param-user": "この利用者によりアップロードされたファイルのみを返す。$1sort=timestamp を指定した場合のみ使用できます。 $1filterbots とは同時に使用できません。",
+       "apihelp-query+allimages-param-filterbots": "ボットによりアップロードされたファイルを絞り込む方法。$1sort=timestamp を指定した場合のみ使用できます。$1user とは同時に使用できません。",
        "apihelp-query+allimages-param-mime": "検索対象のMIMEタイプ、たとえば <kbd>image/jpeg</kbd>。",
        "apihelp-query+allimages-param-limit": "返す画像の総数。",
        "apihelp-query+allimages-example-B": "<kbd>B</kbd> で始まるファイルの一覧を表示する。",
        "apihelp-query+alllinks-param-dir": "一覧表示する方向。",
        "apihelp-query+alllinks-example-B": "<kbd>B</kbd> で始まるリンクされたページ (存在しないページも含む)を、リンク元のページIDとともに表示する。",
        "apihelp-query+alllinks-example-unique": "ユニークなリンクのタイトルを一覧。",
+       "apihelp-query+alllinks-example-unique-generator": "リンクされているページを、存在しないものに印をつけて、すべて取得する。",
        "apihelp-query+alllinks-example-generator": "リンクを含むページを取得します。",
        "apihelp-query+allmessages-param-messages": "出力のためのメッセージ。 <kbd>*</kbd>(デフォルト)は、すべてのメッセージを意味します。",
        "apihelp-query+allmessages-param-prop": "取得するプロパティ:",
        "apihelp-query+allrevisions-param-generatetitles": "ジェネレーターとして使用する場合、版IDではなくページ名を生成します。",
        "apihelp-query+allrevisions-example-user": "利用者 <kbd>Example</kbd> による直近の50版を一覧表示する。",
        "apihelp-query+allrevisions-example-ns-main": "標準名前空間にある最初の50版を一覧表示する。",
+       "apihelp-query+mystashedfiles-param-prop": "ファイルのどのプロパティを取得するか。",
+       "apihelp-query+mystashedfiles-paramvalue-prop-size": "ファイルサイズと画像の大きさを取得します。",
+       "apihelp-query+mystashedfiles-paramvalue-prop-type": "ファイルの MIME タイプとメディアタイプを取得します。",
        "apihelp-query+mystashedfiles-param-limit": "取得するファイルの数。",
-       "apihelp-query+alltransclusions-param-prefix": "この値で始まるすべてのトランスクルードされているページを検索する。",
+       "apihelp-query+alltransclusions-description": "存在しないものも含めて、すべての参照読み込み (&#123;&#123;x&#125;&#125; で埋め込まれたページ) を一覧表示します。",
+       "apihelp-query+alltransclusions-param-from": "列挙を開始する参照読み込みのページ名。",
+       "apihelp-query+alltransclusions-param-to": "列挙を終了する参照読み込みのページ名。",
+       "apihelp-query+alltransclusions-param-prefix": "この値で始まるすべての参照読み込みされているページを検索する。",
        "apihelp-query+alltransclusions-param-prop": "どの情報を結果に含めるか:",
-       "apihelp-query+alltransclusions-param-namespace": "列挙する前空間。",
+       "apihelp-query+alltransclusions-paramvalue-prop-ids": "参照元のページIDを追加します ($1unique とは同時に使用できません)。",
+       "apihelp-query+alltransclusions-paramvalue-prop-title": "参照読み込みのページ名を追加します。",
+       "apihelp-query+alltransclusions-param-namespace": "列挙する名前空間。",
        "apihelp-query+alltransclusions-param-limit": "返す項目の総数。",
        "apihelp-query+alltransclusions-param-dir": "一覧表示する方向。",
-       "apihelp-query+alltransclusions-example-B": "<kbd>B</kbd> で始まる参照読み込みされているページ (存在しないページも含む)を、参照元のページIDとともに表示する。",
+       "apihelp-query+alltransclusions-example-B": "参照読み込みされているページ (存在しないページも含む) を、参照元のページIDとともに、<kbd>B</kbd> で始まるものから一覧表示する。",
+       "apihelp-query+alltransclusions-example-unique-generator": "参照読み込みされたページを、存在しないものに印をつけて、すべて取得する。",
        "apihelp-query+alltransclusions-example-generator": "参照読み込みを含んでいるページを取得する。",
        "apihelp-query+allusers-description": "すべての登録利用者を一覧表示します。",
        "apihelp-query+allusers-param-from": "列挙を開始する利用者名。",
        "apihelp-query+exturlusage-paramvalue-prop-title": "ページ名と名前空間IDを追加します。",
        "apihelp-query+exturlusage-paramvalue-prop-url": "ページ内で使用されているURLを追加します。",
        "apihelp-query+exturlusage-param-protocol": "URLのプロトコル。このパラメータが空であり、かつ<var>$1query</var> が設定されている場合, protocol は <kbd>http</kbd> となります。すべての外部リンクを一覧表示するためにはこのパラメータと <var>$1query</var> の両方を空にしてください。",
+       "apihelp-query+exturlusage-param-query": "プロトコルを除いた検索文字列。[[Special:LinkSearch]] も参照してください。すべての外部リンクを一覧表示するには空欄にしてください。",
        "apihelp-query+exturlusage-param-namespace": "列挙するページ名前空間。",
        "apihelp-query+exturlusage-example-simple": "<kbd>http://www.mediawiki.org</kbd> にリンクしているページを一覧表示する。",
        "apihelp-query+filearchive-description": "削除されたファイルをすべて順に列挙します。",
        "apihelp-query+pageprops-description": "ページコンテンツで定義されている様々なページのプロパティを取得。",
        "apihelp-query+pageprops-example-simple": "ページ <kbd>Main Page</kbd> および <kbd>MeiaWiki</kbd> のプロパティを取得する。",
        "apihelp-query+pageswithprop-description": "与えられたページプロパティが使用されているすべてのページを一覧表示します。",
+       "apihelp-query+pageswithprop-param-prop": "どの情報を結果に含めるか:",
        "apihelp-query+pageswithprop-paramvalue-prop-ids": "ページIDを追加します。",
        "apihelp-query+pageswithprop-paramvalue-prop-title": "ページ名と名前空間IDを追加します。",
        "apihelp-query+pageswithprop-paramvalue-prop-value": "ページプロパティの値を追加。",
        "apihelp-query+usercontribs-param-tag": "このタグが付与された版のみを一覧表示する。",
        "apihelp-query+usercontribs-param-toponly": "最新の版である変更のみを一覧表示する。",
        "apihelp-query+usercontribs-example-user": "利用者 <kbd>Example</kbd> の投稿記録を表示する。",
+       "apihelp-query+userinfo-param-prop": "どの情報を結果に含めるか:",
        "apihelp-query+userinfo-paramvalue-prop-realname": "利用者の本名を追加します。",
        "apihelp-query+userinfo-example-simple": "現在の利用者に関する情報を取得します。",
        "apihelp-query+userinfo-example-data": "現在の利用者に関する追加情報を取得します。",
        "apihelp-revisiondelete-example-revision": "<kbd>Main Page</kbd> の版 <kbd>12345</kbd> の本文を隠す。",
        "apihelp-rollback-param-title": "巻き戻すページ名です。<var>$1pageid</var> とは同時に使用できません。",
        "apihelp-rollback-param-pageid": "巻き戻すページのページIDです。<var>$1title</var> とは同時に使用できません。",
+       "apihelp-rollback-param-tags": "巻き戻しに適用するタグ。",
        "apihelp-rollback-param-user": "巻き戻し対象の編集を行った利用者名。",
        "apihelp-rollback-param-markbot": "巻き戻された編集と巻き戻しをボットの編集としてマークする。",
        "apihelp-rollback-example-simple": "利用者 <kbd>Example</kbd> による <kbd>Main Page</kbd> への最後の一連の編集を巻き戻す。",
        "apihelp-rollback-example-summary": "IP利用者 <kbd>192.0.2.5</kbd> による <kbd>Main Page</kbd> への最後の一連の編集を <kbd>Reverting vandalism</kbd> という理由で、それらの編集とその差し戻しをボットの編集としてマークして差し戻す。",
        "apihelp-stashedit-param-title": "編集されているページのページ名。",
+       "apihelp-stashedit-param-text": "ページの本文。",
+       "apihelp-stashedit-param-contentmodel": "新しいコンテンツのコンテンツ・モデル。",
+       "apihelp-tag-description": "個々の版または記録項目に対しタグの追加または削除を行います。",
+       "apihelp-tag-param-add": "追加するタグ。手動で定義されたタグのみ追加可能です。",
        "apihelp-tag-param-reason": "変更の理由。",
+       "apihelp-tag-example-rev": "版ID 123に <kbd>vandalism</kbd> タグを理由を指定せずに追加する",
        "apihelp-tag-example-log": "<kbd>Wrongly applied</kbd> という理由で <kbd>spam</kbd> タグを 記録項目ID 123 から取り除く",
        "apihelp-tokens-param-type": "リクエストするトークンの種類。",
        "apihelp-tokens-example-edit": "編集トークンを取得する (既定)。",
        "apihelp-upload-param-watch": "このページをウォッチする。",
        "apihelp-upload-param-ignorewarnings": "あらゆる警告を無視する。",
        "apihelp-upload-param-url": "ファイル取得元のURL.",
+       "apihelp-userrights-description": "利用者の所属グループを変更します。",
        "apihelp-userrights-param-user": "利用者名。",
        "apihelp-userrights-param-userid": "利用者ID。",
        "apihelp-userrights-param-add": "利用者をこのグループに追加します。",
        "api-help-param-default": "既定値: $1",
        "api-help-param-default-empty": "既定値: <span class=\"apihelp-empty\">(空)</span>",
        "api-help-param-token": "[[Special:ApiHelp/query+tokens|action=query&meta=tokens]] から取得した「$1」トークン",
+       "api-help-param-token-webui": "互換性のために、ウェブUIで使用されるトークンも受理されます。",
+       "api-help-param-limited-in-miser-mode": "<strong>注意:</strong> [[mw:Manual:$wgMiserMode|miser mode]] により、これを使用すると継続する前に <var>$1limit</var> より返される結果が少なくなることがあります; 極端な場合では、ゼロ件の結果が返ることもあります。",
        "api-help-param-direction": "列挙の方向:\n;newer:古いものを先に表示します。注意: $1start は $1end 以前でなければなりません。\n;older:新しいものを先に表示します (既定)。注意: $1start は $1end 以降でなければなりません。",
        "api-help-param-no-description": "<span class=\"apihelp-empty\">(説明なし)</span>",
        "api-help-examples": "{{PLURAL:$1|例}}:",
index 1497e34..0618a88 100644 (file)
@@ -14,7 +14,7 @@
                        "Priviet"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|설명문서]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 메일링 리스트]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API 공지 사항] * [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R 버그 및 요청] </div>\n<strong>상태:</strong> 이 페이지에 표시된 모든 기능은 정상적으로 작동하지만, API는 여전히 활발하게 개발되고 있으며, 언제든지 변경될 수 있습니다. 업데이트 정보를 받아보려면 [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce 메일링 리스트]를 구독하십시오.\n\n<strong>잘못된 요청:</strong> API에 잘못된 요청이 전송되면 HTTP 헤더에서 \"MediaWiki-API-Error\" 키를 보내고, 헤더 값과 오류 코드가 같게 설정됩니다. 자세한 정보에 대해서는 [[mw:API:Errors_and_warnings|API:오류와 경고]]를 참조하십시오.",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|설명문서]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 메일링 리스트]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API 알림 사항]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R 버그 및 요청]\n</div>\n<strong>상태:</strong> 이 페이지에 보여지는 모든 기능은 정상적으로 작동하지만, API는 여전히 활발하게 개발되고 있으며, 언제든지 변경될 수 있습니다. 업데이트 공지를 받아보려면 [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 메일링 리스트]를 구독하십시오.\n\n<strong>잘못된 요청:</strong> API에 잘못된 요청이 전송되면 HTTP 헤더에서 \"MediaWiki-API-Error\" 키를 보내고, 헤더 값과 오류 코드가 같게 설정됩니다. 자세한 정보에 대해서는 [[mw:API:Errors_and_warnings|API:오류와 경고]]를 참조하십시오.\n\n<strong>테스트하기:</strong> API 요청을 테스트의 편의를 위해, [[Special:ApiSandbox]]를 보세요.",
        "apihelp-main-param-action": "수행할 동작",
        "apihelp-main-param-format": "출력값의 형식.",
        "apihelp-main-param-maxlag": "최대 랙은 미디어위키가 데이터베이스 복제된 클러스터에 설치되었을 때 사용될 수 있습니다. 특정한 행동이 사이트 복제 랙을 유발할 때, 이 변수는 클라이언트가 복제 랙이 설정된 숫자 아래로 내려갈 때까지 기다리도록 지시합니다. 과도한 랙의 경우, <samp>maxlag</samp> 오류 코드와 <samp>Waiting for $host: $lag seconds lagged</samp> 메시지가 제공됩니다.<br />[[mw:Manual:Maxlag_parameter|매뉴얼: Maxlag 변수]] 에서 더 많은 정보를 얻을 수 있습니다.",
index 7b5361d..26da426 100644 (file)
@@ -7,7 +7,7 @@
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page/de|Dokemäntazjohn]]\n* [[mw:API:FAQ/de|Öff jefrohch]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mäileng_Leß]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Aanköndejonge zom <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Application Programming Interface\">API</i>]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Jemäldte Fähler un Wönsch]\n</div>\n<strong>Status:</strong> Alle op heh dä Sigg aanjzeischte Ußwahle sullte donn, ävver et <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Application Programming Interface\">API</i> weed jrahd noch äntwekeld un et kann sesch alle Nahslangs jädd ändere. Holl Der de [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ Mäileng_Leß med Aanköndejonge], öm automattesch övver Neujeschkeite enfommehrt ze wähde.\n\n<strong>Kapodde Aanfrohre:</strong> Wam_mer kapodde Aanfroheaan et API <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Application Programming Interface\">API</i> schek, kritt mer ene <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Transfer Protocol\">HTTP</i>-Kopp ußjejovve met däm Täx „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">MediaWiki-API-Error</code>“ dren, dä mer als ene Schlößel bedraachte kann. Mih dohzoh fengk met op dä Sigg [[mw:API:Errors_and_warnings|<i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Application Programming Interface\">API</i>: Fähler un Warnonge]].",
        "apihelp-main-param-action": "Wat för en Aufjahb.",
        "apihelp-main-param-format": "Et Fommaht för ußzejävve.",
-       "apihelp-main-param-maxlag": "Der hühste zohjelohße Verzoch kann jenumme wähde, wann MehdijaWikki obb enem Dahtebangk  replicated cluster enschtallehrt weed. Öm kein Opdräschd aan de Dahtebangk ze scheke, di dat noch schlemmer maache dähte, kam_mer övver heh dä Parramehter et Projramm affwahde lohße, bes dat  the replication lag onger däm aanjejovve Wäät lit. Wann dä Verzoch övvermähßesch jruhs es kritt mer dä Fähler <samp lang=\"en\" xml:lang=\"en\" dir=\"ltr\">maxlag</samp> jemälldt en ene Nohreesch esu wi <samp lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Mer wahde op dä ẞööver $Maschihn un di es $Verzoch Sekonde hengerher</samp>.<br />Op dä [[mw:Manual:Maxlag_parameter|Hanndbohchsigg zom \n<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Maxlag</code>-Parramehter]] kam_mer noch mih zerdoh lässe.<!-- https://translatewiki.net/wiki/Thread:Support/About_MediaWiki:Apihelp-main-param-maxlag/ksh -->",
+       "apihelp-main-param-maxlag": "Der hühste zohjelohße Verzoch kann jenumme wähde, wann MehdijaWikki obb enem Knubbel Rääschner medd ene replezehrte (dadd es, lebänndesch koppehrte) Dahtebangk enschtallehrt weed. Öm kein Opdräschd aan de Dahtebangk ze scheke, di dat noch schlemmer maache dähte, kam_mer övver heh dä Parramehter et Projramm affwahde lohße, bes dat dä Verzoch vum Replezehre onger däm aanjejovve Wäät lit. Wann dä Verzoch övvermähßesch jruhs es, kritt mer dä Fähler <samp lang=\"en\" xml:lang=\"en\" dir=\"ltr\">maxlag</samp> jemälldt med ene Nohreesch esu wi <samp lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Mer wahde op dä ẞööver $Maschihn un di es $Verzoch Sekonde hengerher</samp>.<br />Op dä [[mw:Manual:Maxlag_parameter|Hanndbohchsigg zom \n<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Maxlag</code>-Parramehter]] kam_mer noch mih zerdoh lässe.",
        "apihelp-main-param-smaxage": "Säz <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">max-age</code> en dä Kopp_Reihj <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">HTTP cache control</code> obb esu vill Sekonde. Fähler wähde nimmohls faßjehallde.",
        "apihelp-main-param-maxage": "Säz <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">max-age</code> en dä Kopp_Reihj <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">HTTP cache control</code> obb esu vill Sekonde. Fähler wähde nimmohls faßjehallde.",
        "apihelp-main-param-assert": "Ställ sescher, dat dä Metmaacher enjelogg es (doh för jiff <kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">user</kbd> en), udder ene Bot es (doh för jiff <kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">bot</kbd> en).",
        "apihelp-feedrecentchanges-param-hideliu": "Änderonge ußschlehße, di vun aanjemälldete Metmaacher jemaht wohde.",
        "apihelp-feedrecentchanges-param-hidepatrolled": "Nohjelohrte Änderonge övverjonn.",
        "apihelp-feedrecentchanges-param-hidemyself": "Änderonge vun heh dämm Metmaacher övverjonn.",
+       "apihelp-feedrecentchanges-param-hidecategorization": "Donn Änderonge aan de Zohjehüreshkeit zoh Saachjroppe veschteijsche.",
        "apihelp-feedrecentchanges-param-tagfilter": "Noh Makkehronge beschängke.",
        "apihelp-feedrecentchanges-param-target": "Zeijsch Änderonge aan Sigge, op di vun heh dä Sigg ene Lengk jeihd.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Zeijsch Änderonge aan Sigge, op di vun dä ußjesöhk Sigg ene Lengk jeihd.",
+       "apihelp-feedrecentchanges-param-categories": "Donn blohß de Änderonge aan de Zohjehüreshkeit för all heh di Saachjroppe zeije.",
+       "apihelp-feedrecentchanges-param-categories_any": "Donn deföhr blohß de Änderonge aan de Zohjehüreshkeit för öhndseijn fun heh dä Saachjroppe zeije.",
        "apihelp-feedrecentchanges-example-simple": "Zeijsch de {{LCFIRST:{{int:recentchanges}}}}",
        "apihelp-feedrecentchanges-example-30days": "Zeijsch de {{LCFIRST:{{int:recentchanges}}}} vun de läzde 30 Dähsch.",
        "apihelp-feedwatchlist-description": "Donn ene Kannahl met dä Oppaßleß zerökjävve.",
        "apihelp-query+allrevisions-param-generatetitles": "Wann als ene  Jenerahtor enjesaz, brängk dat Övverschreffte un kein Kännonge vun Väsjohne.",
        "apihelp-query+allrevisions-example-user": "Donn de läzde fuffzisch Beijdrähsch vum Metmaacher „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Example</kbd>“ opleßte.",
        "apihelp-query+allrevisions-example-ns-main": "Donn de eezde fuffzisch Väsjohne em Houp-Appachemang opleßte.",
+       "apihelp-query+mystashedfiles-param-prop": "Wat för en Aanjahbe holle för di Datteije.",
        "apihelp-query+mystashedfiles-param-limit": "Wi vill Datteije holle?",
        "apihelp-query+alltransclusions-param-from": "De Övverschreff vun dä ennjeföhschte Sigg, woh de Leß medd aanfange sull.",
        "apihelp-query+alltransclusions-param-to": "De Övverschreff vun dä ennjeföhschte Sigg, woh et Zälle ophühre sull.",
        "apihelp-query+random-param-namespace": "Jiff blohß sigge en heh dä Appachtemangs uß.",
        "apihelp-query+random-param-limit": "Wi vill zohfälleje Sigge sulle ußjejovve wähde?",
        "apihelp-query+random-param-redirect": "Nemm <kbd>$1filterredir=redirects</kbd> schtatt dämm.",
+       "apihelp-query+random-param-filterredir": "Wi de Ömleijdonge ußzottehre?",
        "apihelp-query+random-example-simple": "Donn zwai zohfälleje Sigge vum Houb_Appachtemang ußjävve.",
        "apihelp-query+random-example-generator": "Donn Ennfommazjuhne övver zwai zohfälleje Sigge vum Houb_Appachtemang ußjävve.",
        "apihelp-query+recentchanges-description": "Donn de  neußte Änderonge opleßte.",
index 8e2a8b5..156cf25 100644 (file)
@@ -7,5 +7,30 @@
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page Torohevitra be kokoa]\n* [https://www.mediawiki.org/wiki/API:FAQ Fanontaniana miverina matetika]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lisitry ny mailaka manaraka]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Filazana API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Baogy & hataka]\n</div>\n<strong>Status:</strong> \nTokony mandeha avokoa ny fitaovana aseho eto amin'ity pehy ity, na dia izany aza mbola am-panamboarana ny API ary mety hiova na oviana na oviana. Araho amin'ny alalan'ny fisoratana ny mailakao ao amin'ny [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce lisitra fampielezana] ny fiovana.\n\n<strong>Hataka diso:</strong> \nRehefa alefa ao amin'i API ny hata, ho alefa miaraka amin'ny lakile \"MediaWiki-API-Error\" ny header HTTP ary samy homen-tsanda mitovy ny header ary ny kaodin-kadisoana. Ho an'ny torohay fanampiny dia jereo https://www.mediawiki.org/wiki/API:Errors_and_warnings.",
        "apihelp-main-param-action": "Inona ny zavatra ho atao.",
        "apihelp-main-param-format": "Format mivoaka",
-       "apihelp-createaccount-param-name": "Anaram-pikambana."
+       "apihelp-block-param-user": "Anaram-pikambana, adiresy IP na valan' IP hosakanana.",
+       "apihelp-block-param-expiry": "Fitaom-pisasarana. Mety miovaova(e.g. <kbd>5 volana</kbd> na <kbd>herinandro 2</kbd>) na voafaritra (e.g. <kbd>2014-09-18T12:34:56Z</kbd>). Raha atao <kbd>tsiefa</kbd>, <kbd>tsy fantatra</kbd>, na <kbd>mandrakizay</kbd>, dia tsy hitsahatra mihitsy ilay sakana.",
+       "apihelp-block-param-reason": "Antom-panakanana",
+       "apihelp-block-param-anononly": "Mpikambana tsy nisoratra anarana ihany no sakanana (izany hoe aza mamela fiovan'olona tsy nisoratra anarana avy amin'ity adiresy IP ity).",
+       "apihelp-block-param-nocreate": "Hanakana famoronan-kaonty.",
+       "apihelp-block-param-autoblock": "Manakana ny adiresy IP farany nampiasaina, ary izay adiresy IP mety hidirany.",
+       "apihelp-block-param-noemail": "Hanakana ny mpikambana tsy handefa mailaka amin'ny alalan'ny wiki (Mila ny zo <code>blockemail</code>).",
+       "apihelp-block-param-hidename": "Hanafina ny anaram-pikambana amin'ny laogim-panakanana (mila ny zo <code>hideuser</code>).",
+       "apihelp-block-param-allowusertalk": "Hamela ny mpikambana hanova ny pejin-dresany (miankina amin'ny <var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>)",
+       "apihelp-block-param-reblock": "Raha efa nosakanana ilay mpikambana, itsahina ilay sakana efa misy.",
+       "apihelp-block-param-watchuser": "Hijery ny adiresy IP ary ny pejin-dresak'ilay mpikambana.",
+       "apihelp-block-example-ip-simple": "Hanakana ny adiresy IP <kbd>192.0.2.5</kbd> mandritry ny telo andro miaraka amin'ny antony <kbd>Filazana voalohany</kbd>.",
+       "apihelp-compare-param-fromtitle": "Lohateny voalohany ampitahaina.",
+       "apihelp-compare-param-fromid": "ID pejy voalohany ampitahaina.",
+       "apihelp-compare-param-fromrev": "Versions voalohany ampitahaina.",
+       "apihelp-compare-param-totitle": "Lohateny faharoa ampitahaina.",
+       "apihelp-compare-param-toid": "ID pejy faharoa ampitahaina.",
+       "apihelp-compare-param-torev": "Versiona faharoa ampitahaina.",
+       "apihelp-compare-example-1": "Hamorona raki-pahasamihafan'ny versiona 1 sy 2.",
+       "apihelp-createaccount-description": "Hamorona kaontim-pikambana vaovao.",
+       "apihelp-createaccount-param-name": "Anaram-pikambana.",
+       "apihelp-createaccount-param-password": "Tenimiafina (tsy raharahiana raha voafaritra i <var>$1mailpassword</var>).",
+       "apihelp-createaccount-param-domain": "Vala ho an'ilay famantarana avy any ivelany (azo tsy fenoina).",
+       "apihelp-createaccount-param-token": "Famantarana famoronan-kaonty azo tamin'ny hataka voalohany.",
+       "apihelp-createaccount-param-email": "Adiresy imailaky ny mpikambana (azo tsy fenoina).",
+       "apihelp-createaccount-param-realname": "Tena anaran'ilay mpikambana (azo tsy fenoina)."
 }
index a43d840..9235247 100644 (file)
@@ -5,11 +5,17 @@
                        "C.R."
                ]
        },
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentaziona]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista 'e mmasciate]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunziaziune 'e ll'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug e richieste]\n</div>\n<strong>Stato:</strong> Tuttuquante 'e funziune 'e sta paggena avesser'a funziunà, ma ll'API è ancora a se sviluppà, picciò chesto putesse cagnà a nu certo mumento. Iscriviteve ccà ncoppa: [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce 'a lista 'e mmasciate] pe' n'avé cocche notifica 'e ll'agghiurnamente.\n\n<strong>Richieste sbagliate:</strong> Si se mannasse na richiesta sbagliata a ll'API, nu cap' 'e HTTP sarrà mannata c' 'a chiave 'e mmasciata \"MediaWiki-API-Error\" e po' tuttuquante 'e valure d' 'a cap' 'e mmasciata e codece 'errore se mannassero arreto e se mpustassero a 'o stesso valore. Pe n'avé cchiù nfurmaziune vedite [[mw:API:Errors_and_warnings|API: Errure e Avvise]].\n\n<strong>Test:</strong> Pe' ve ffà cchiù semprice 'e test 'e richieste API, vedite [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Quale aziona d'avess'a fà.",
        "apihelp-main-param-format": "Qualu furmato avess'ascì d'output.",
        "apihelp-main-param-maxlag": "'O massimo lag ca se putess'ausà quanno MediaWiki s'installasse ncopp'a nu cluster replicato 'e database. Pe' puté sarvà aziune ca causassero cchiù lag 'e replicato, stu parammetro putesse fà 'o cliente aspettà nfin'a quanno 'o tiempo 'e replicaziona fosse meno ca nu valore specificato. Si nce stesse cchiù assaje tiempo 'e lag, nu codece 'errore <samp>maxlag</samp> se turnasse comm'a na mmasciata tipo <samp>Aspettanno 'o $host: nu $lag secunde 'e lag</samp>.<br />Vedite [[mw:Manual:Maxlag_parameter|Manuale: Parammetro Maxlag]] pe' n'avé cchiù nfurmaziune.",
+       "apihelp-main-param-smaxage": "Mpustate 'a cap' 'e cuntrollo 'e cache HTTP <code>s-maxage</code> a sta quantità 'e secondi. Ll'errure nun s'acchiappassero maje.",
+       "apihelp-main-param-maxage": "Mpustate 'a cap' 'e cuntrollo 'e cache HTTP <code>max-age</code> a sta quantità 'e secondi. Ll'errure nun s'acchiappassero maje.",
+       "apihelp-main-param-assert": "Cuntrullate si l'utente è trasuto si sta mpustato comm' <kbd>user</kbd>, o pure ca téne o deritto 'e bot si <kbd>bot</kbd>.",
+       "apihelp-main-param-requestid": "Qualunque valore dato ccà se mpizzasse dint'a risposta. Se putess'ausà pe' puté distinguere richieste.",
        "apihelp-main-param-servedby": "Include 'o risultato 'e nomme d' 'o host ca servette 'a richiesta.",
        "apihelp-main-param-curtimestamp": "Include dint' 'o risultato 'o timestamp 'e mò.",
+       "apihelp-main-param-origin": "Quanno se trasesse a ll'API ausanno richieste 'e cross-dominio AJAX (CORS), mpustate chesto a 'o dominio origgenale. Chesto s'avess'azzeccà dint'a qualsiasi richiesta 'e pre-volo, e picciò avess'a ffà parte d' 'a richiesta d'URI (nun fosse 'o cuorpo POST). Chesto s'avess'azzeccà  a uno 'e ll'origgene dint' 'o cap' 'e paggena <code>Origin</code> pricisamente, picciò s'avessa mpustà coccosa tipo <kbd>https://en.wikipedia.org</kbd> o <kbd>https://meta.wikimedia.org</kbd>. Si stu parammetro nun s'azzeccasse c' 'o cap' 'e paggena <code>Origin</code>, allora na risposta 403 se turnasse. Si stu parammetro s'azzeccasse c' 'o cap' 'e paggena <code>Origin</code> e ll'origgene fosse dint' 'a lista janca, allora nu cap' 'e paggena <code>Access-Control-Allow-Origin</code> fosse mpustato.",
        "apihelp-block-description": "Blocca n'utente.",
        "apihelp-block-param-user": "Nomme utente, indirizzo IP o range IP 'a bluccà.",
        "apihelp-block-param-reason": "Mutive p' 'o blocco.",
        "apihelp-expandtemplates-param-generatexml": "Generà ll'albero XML (scagnato 'a $1prop=parsetree).",
        "apihelp-expandtemplates-example-simple": "Spanne 'o wikitesto <kbd><nowiki>{{Project:Sandbox}}</nowiki></kbd>.",
        "apihelp-feedcontributions-description": "Tuorna nu feed 'e cuntribbute 'utente.",
-       "apihelp-feedcontributions-param-feedformat": "'O furmatto d' 'o feed.",
+       "apihelp-feedcontributions-param-feedformat": "'O furmato d' 'o feed.",
        "apihelp-feedcontributions-param-user": "'A quale 'utente nc'avimm'a piglià cuntribbute.",
        "apihelp-feedcontributions-param-namespace": "'A qualu namespace s'avesser'a filtrà 'e cuntribbute.",
        "apihelp-feedcontributions-param-year": "'E ll'anno (e primma).",
        "apihelp-feedcontributions-param-month": "D' 'o mese (e pure cchiù primma).",
+       "apihelp-feedcontributions-param-tagfilter": "Filtrà cuntribbute ca teneno sti ttag.",
+       "apihelp-feedcontributions-param-deletedonly": "Mmusta surtant' 'e cuntribbute scancellate.",
+       "apihelp-feedcontributions-param-toponly": "Fà vedé sulamente 'e contribbute 'e l'urdeme verziune.",
+       "apihelp-feedcontributions-param-newonly": "Fà vedé sulamente 'e contribbute ca songo criazione 'e paggene.",
+       "apihelp-feedcontributions-param-showsizediff": "Fà vedé 'a differenza nfra verziune.",
+       "apihelp-feedcontributions-example-simple": "Tuòrna cuntribbute 'a ll'utente <kbd>Esempio</kbd>.",
+       "apihelp-feedrecentchanges-description": "Tuorna 'o blocco 'e nutizie 'e ll'urdeme cagnamiente.",
+       "apihelp-feedrecentchanges-param-feedformat": "'O furmato d' 'o feed.",
        "apihelp-feedwatchlist-param-feedformat": "'O furmato d' 'o feed.",
+       "apihelp-filerevert-param-comment": "Carreca commento.",
+       "apihelp-help-description": "Fà veré l'aiuto p' 'e module specificate",
+       "apihelp-help-param-submodules": "Azzecca n'aiuto p' 'e submodule 'e nu modulo ca téne nome.",
        "apihelp-login-example-login": "Tràse.",
        "apihelp-move-description": "Mòve paggena.",
        "apihelp-opensearch-param-search": "Ascìa stringa.",
index fcdbb25..0c9f12f 100644 (file)
@@ -11,7 +11,8 @@
                        "Peter Bowman",
                        "Darellur",
                        "The Polish",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Sethakill"
                ]
        },
        "apihelp-main-param-action": "Wybierz akcję do wykonania.",
@@ -25,6 +26,7 @@
        "apihelp-block-param-anononly": "Blokuj tylko anonimowych użytkowników (blokuje anonimowe edycje z tego adresu IP).",
        "apihelp-block-param-nocreate": "Zapobiegnij utworzeniu konta.",
        "apihelp-block-param-autoblock": "Zablokuj ostatni adres IP tego użytkownika i automatycznie wszystkie kolejne, z których będzie się logował.",
+       "apihelp-block-param-hidename": "Ukryj nazwę użytkownika z rejestru blokad. (Wymagane uprawnienia <code>hideuser</code>)",
        "apihelp-block-param-reblock": "Jeżeli ten użytkownik jest już zablokowany, nadpisz blokadę.",
        "apihelp-block-param-watchuser": "Obserwuj stronę użytkownika i jego IP oraz ich strony dyskusji.",
        "apihelp-block-example-ip-simple": "Zablokuj IP <kbd>192.0.2.5</kbd> na 3 dni za <kbd>Pierwszy atak</kbd>.",
        "apihelp-imagerotate-param-rotation": "Stopni w prawo, aby obrócić zdjęcie.",
        "apihelp-imagerotate-example-simple": "Obróć <kbd>Plik:Przykład.png</kbd> o <kbd>90</kbd> stopni.",
        "apihelp-imagerotate-example-generator": "Obróć wszystkie obrazki w <kbd>Kategorii:Flip</kbd> o <kbd>180</kbd> stopni.",
-       "apihelp-import-param-summary": "Podsumowanie importu.",
+       "apihelp-import-param-summary": "Podsumowanie importu rekordów dziennika.",
        "apihelp-import-param-xml": "Przesłany plik XML.",
        "apihelp-import-param-interwikisource": "Dla importów mediawiki: źródłowa wiki.",
        "apihelp-import-param-interwikipage": "Dla importów interwiki: strona do importu.",
        "apihelp-logout-example-logout": "Wyloguj obecnego użytkownika.",
        "apihelp-managetags-param-reason": "Opcjonalny powód utworzenia, usunięcia, włączenia lub wyłączenia znacznika.",
        "apihelp-managetags-param-ignorewarnings": "Czy zignorować ostrzeżenia, które pojawiają się w trakcie operacji.",
+       "apihelp-mergehistory-description": "Łączenie historii edycji.",
        "apihelp-move-description": "Przenieś stronę.",
        "apihelp-move-param-reason": "Powód zmiany nazwy.",
        "apihelp-move-param-movetalk": "Zmień nazwę strony dyskusji, jeśli istnieje.",
index 254f1c8..b70ebe9 100644 (file)
@@ -7,7 +7,7 @@
                        "Jkb8"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentação]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de discussão]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anúncios da API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Erros e solicitações]\n</div>\n<strong>Estado:</strong> Todas as funcionalidades mostradas nesta página deveriam estar a funcionar, mas a API ainda está em activo desenvolvimento, e pode ser alterada a qualquer momento. Inscreva-se na [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de discussão mediawiki-api-announce] para ser informado acerca das actualizações.\n\n<strong>Solicitações erradas:</strong> Quando solicitações erradas são enviadas à API, um cabeçalho em HTTP será enviado com a chave \"MediaWiki-API-Error\" e, em seguida, tanto o valor do cabeçalho quanto o código de erro retornado serão definidos com o mesmo valor. Para mais informação, consulte [[mw:API:Errors_and_warnings|API: Errors and warnings]].",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentação]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de discussão]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anúncios da API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Erros e solicitações]\n</div>\n<strong>Estado:</strong> Todas as funcionalidades mostradas nesta página deveriam estar a funcionar, mas a API ainda está em activo desenvolvimento, e pode ser alterada a qualquer momento. Inscreva-se na [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de discussão mediawiki-api-announce] para ser informado acerca das actualizações.\n\n<strong>Solicitações erradas:</strong> Quando solicitações erradas são enviadas à API, um cabeçalho em HTTP será enviado com a chave \"MediaWiki-API-Error\" e, em seguida, tanto o valor do cabeçalho quanto o código de erro retornado serão definidos com o mesmo valor. Para mais informação, consulte [[mw:API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Testes:</strong> Para facilitar os testes de solicitações à API, consulte [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Qual acção a executar.",
        "apihelp-main-param-format": "O formato de saída.",
        "apihelp-block-description": "Bloquear um utilizador.",
index 26fe02d..4ded4aa 100644 (file)
@@ -18,7 +18,7 @@
        "apihelp-main-description": "{{doc-apihelp-description|main}}",
        "apihelp-main-param-action": "{{doc-apihelp-param|main|action}}",
        "apihelp-main-param-format": "{{doc-apihelp-param|main|format}}",
-       "apihelp-main-param-maxlag": "{{doc-apihelp-param|main|maxlag}}\n\n\"$host\" and \"$lag\" are not variables and appear as is.",
+       "apihelp-main-param-maxlag": "{{doc-apihelp-param|main|maxlag}}",
        "apihelp-main-param-smaxage": "{{doc-apihelp-param|main|smaxage}}",
        "apihelp-main-param-maxage": "{{doc-apihelp-param|main|maxage}}",
        "apihelp-main-param-assert": "{{doc-apihelp-param|main|assert}}",
index a692ff2..dd537f6 100644 (file)
                        "INS Pirat",
                        "Macofe",
                        "Краснорядцева Елена",
-                       "Iniquity"
+                       "Iniquity",
+                       "Лилиә",
+                       "Айсар",
+                       "Гизатуллина"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Документация]]\n* [[mw:API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почтовая рассылка]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Новости API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Ошибки и запросы]\n</div>\n<strong>Статус:</strong> Все отображаемые на этой странице функции должны работать, однако API находится в статусе активной разработки, и может измениться в любой момент. Подпишитесь на  [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\n<strong>Ошибочные запросы:</strong> Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом \"MediaWiki-API-Error\", после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:API:Errors_and_warnings|API: Ошибки и предупреждения]].",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Документация]]\n* [[mw:API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почтовая рассылка]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Новости API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Ошибки и запросы]\n</div>\n<strong>Статус:</strong> Все отображаемые на этой странице функции должны работать, однако API находится в статусе активной разработки и может измениться в любой момент. Подпишитесь на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\n<strong>Ошибочные запросы:</strong> Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом «MediaWiki-API-Error», после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:API:Errors_and_warnings|API: Ошибки и предупреждения]].\n\n<strong>Тестирование:</strong> для удобства тестирования API-запросов, см. [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Действие, которое следует выполнить.",
        "apihelp-main-param-format": "Формат вывода.",
        "apihelp-main-param-smaxage": "Устанавливает значение HTTP-заголовка Cache-Control <code>s-maxage</code> в заданное число секунд. Ошибки никогда не кэшируются.",
@@ -32,7 +35,9 @@
        "apihelp-block-param-anononly": "Блокировать только анонимных пользователей (т. е. запретить анонимные правки для этого IP-адреса).",
        "apihelp-block-param-nocreate": "Запретить создание учётных записей.",
        "apihelp-block-param-autoblock": "Автоматически блокировать последний использованный IP-адрес и все последующие, с которых будут совершаться попытки авторизации.",
+       "apihelp-block-param-noemail": "Запретить участнику отправлять электронную почту через интерфейс вики. (Требуется право <code>blockemail</code>).",
        "apihelp-block-param-hidename": "Скрыть имя участника из журнала блокировок. (Требуется право <code>hideuser</code>).",
+       "apihelp-block-param-allowusertalk": "Позволяет участникам редактировать их собственные страницы обсуждения (зависит от <var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
        "apihelp-block-param-reblock": "Если участник уже заблокирован, перезаписать существующую блокировку.",
        "apihelp-block-param-watchuser": "Следить за страницей пользователя или IP-участника и страницей обсуждения.",
        "apihelp-checktoken-param-type": "Тип маркера проходит тестирование.",
@@ -93,6 +98,7 @@
        "apihelp-expandtemplates-param-text": "Викитекст для конвертирования",
        "apihelp-expandtemplates-paramvalue-prop-wikitext": "Расширенный викитекст",
        "apihelp-expandtemplates-paramvalue-prop-parsetree": "Дерево разбора XML входных данных.",
+       "apihelp-feedcontributions-param-feedformat": "Биреү форматы",
        "apihelp-feedcontributions-param-year": "От года (и ранее).",
        "apihelp-feedcontributions-param-month": "От месяца (и ранее).",
        "apihelp-feedcontributions-param-deletedonly": "Показать только удалённые правки.",
        "apihelp-feedrecentchanges-param-showlinkedto": "Показать правки на страницах, ссылающихся на данную.",
        "apihelp-feedrecentchanges-example-simple": "Список последних изменений.",
        "apihelp-feedrecentchanges-example-30days": "Показать последние изменения в течение 30 дней.",
+       "apihelp-feedwatchlist-param-feedformat": "Биреү форматы.",
+       "apihelp-feedwatchlist-param-hours": "Был ваҡыттан алып үҙгәртелгән биттәр исемлеге",
        "apihelp-feedwatchlist-param-linktosections": "Ссылаться прямо на разделы с изменениями, если возможно.",
+       "apihelp-feedwatchlist-example-default": "Күҙәтеү каналын күрһәтергә",
+       "apihelp-feedwatchlist-example-all6hrs": "Күҙәтелгән биттәрҙә һуңғы 6 сәғәт эсендәге үҙгәрештәрҙе күрһәтергә.",
+       "apihelp-filerevert-description": "Файлды иҫке версияға ҡайтарырға.",
        "apihelp-filerevert-param-filename": "Целевое имя файла без префикса File:.",
        "apihelp-filerevert-param-comment": "Загрузить комментарий.",
+       "apihelp-help-param-helpformat": "Белешмә яҙыу форматы.",
        "apihelp-help-example-main": "Помощь по главному модулю.",
        "apihelp-help-example-recursive": "Вся справка в одном разделе.",
        "apihelp-imagerotate-description": "Поворот одного или нескольких изображений.",
        "apihelp-login-example-login": "Войти",
        "apihelp-logout-description": "Выйти и очистить данные сессии.",
        "apihelp-mergehistory-description": "Объединение историй правок",
+       "apihelp-mergehistory-param-reason": "Причина для объединения истории.",
        "apihelp-move-description": "Переместить страницу.",
        "apihelp-move-param-to": "Заголовок, в который следует переименовать страницу.",
        "apihelp-move-param-reason": "Причина переименования.",
        "apihelp-move-param-watch": "Добавить страницу и перенаправление в список наблюдения текущего пользователя.",
        "apihelp-move-param-unwatch": "Удалить страницу и перенаправление из списка наблюдения текущего пользователя.",
        "apihelp-move-param-ignorewarnings": "Игнорировать предупреждения",
+       "apihelp-move-example-move": "Переименовать <kbd>Badtitle</kbd> в <kbd>Goodtitle</kbd> без оставления перенаправления.",
        "apihelp-opensearch-param-search": "Строка поиска.",
        "apihelp-opensearch-param-limit": "Максимальное число возвращаемых результатов.",
        "apihelp-opensearch-param-namespace": "Пространства имён для поиска.",
        "apihelp-opensearch-param-format": "Формат вывода.",
+       "apihelp-options-param-reset": "Сбрасывает настройки на установленные по умолчанию.",
        "apihelp-options-example-reset": "Сбросить все настройки.",
        "apihelp-paraminfo-description": "Получить информацию о модулях API.",
        "apihelp-paraminfo-param-helpformat": "Формат строк справки.",
+       "apihelp-parse-param-disablepp": "Урынына <var>$1disablelimitreport</var> ҡулланырға.",
+       "apihelp-parse-param-preview": "Алдан ҡарау режимында синтаксик анализ",
        "apihelp-parse-param-disabletoc": "Не включать в вывод таблицу содержания.",
        "apihelp-parse-example-page": "анализ страницы",
        "apihelp-parse-example-text": "Анализ wikitext.",
+       "apihelp-parse-example-summary": "Һығымтаны тикшереү.",
+       "apihelp-patrol-param-rcid": "Яңы үҙгәртеүҙәрҙе ҡарау идентификаторы.",
+       "apihelp-patrol-param-revid": "Ҡарау версияһы идентификаторы.",
+       "apihelp-patrol-example-rcid": "Һуңғы үҙгәрештәрҙе ҡарау.",
+       "apihelp-patrol-example-revid": "Яңынан ҡарау.",
        "apihelp-protect-description": "Изменить уровень защиты страницы.",
+       "apihelp-protect-param-title": "Бит атамаһы. $1pageid менән бергә ҡулланылмай.",
+       "apihelp-protect-param-reason": "(ООН) һағы сәбәптәре.",
        "apihelp-protect-example-protect": "Защитить страницу.",
+       "apihelp-protect-example-unprotect": "<kbd>всех</kbd> өсөн сикләүҙәр ҡуйып,биттән һаҡлауҙы алырға.",
+       "apihelp-protect-example-unprotect2": "Бер ниндәй сикләүҙәр ҡуймай биттән һаҡлауҙы алырға.",
        "apihelp-purge-param-forcelinkupdate": "Обновление связей таблиц.",
+       "apihelp-purge-param-forcerecursivelinkupdate": "Һылтанманы һәм таблицаны яңыртығыҙ һәм был битте шаблон итеп ҡулланған башҡа биттәр өсөн һылтанмаларҙы ла яңыртығыҙ.",
        "apihelp-query-param-list": "Какие списки использовать",
        "apihelp-query-param-meta": "Какие метаданные использовать",
        "apihelp-query+allcategories-description": "Перечислить все категории.",
+       "apihelp-query+allcategories-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+allcategories-param-dir": "Сортлау йүнәлештәре.",
        "apihelp-query+allcategories-param-limit": "Сколько категорий вернуть.",
        "apihelp-query+allcategories-param-prop": "Какие свойства получить:",
+       "apihelp-query+allcategories-paramvalue-prop-size": "Категорияларға биттәр һаны өҫтәү",
+       "apihelp-query+allcategories-example-size": "Биттәр һаны буйынса мәғлүмәтле категориялар исемлеге.",
+       "apihelp-query+allcategories-example-generator": "<kbd>исемлек</kbd> категориялар битенән мәғлүмәт алырға.",
+       "apihelp-query+alldeletedrevisions-description": "Бар мөхәррирләү исемлеге ҡулланыусы тарафынан юйылған.",
+       "apihelp-query+alldeletedrevisions-paraminfo-useronly": "<var>$3ҡулланыусының</var> менән генә ҡулланыла ала.",
+       "apihelp-query+alldeletedrevisions-param-start": "Һанауҙы башлау ваҡытын билдәләү",
+       "apihelp-query+alldeletedrevisions-param-end": "Һанай башлау ваҡытын билдәләү.",
+       "apihelp-query+alldeletedrevisions-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+alldeletedrevisions-param-user": "Бары тик был ҡулланыусының үҙгәртеүҙәр исемлеге.",
+       "apihelp-query+alldeletedrevisions-param-excludeuser": "Был ҡулланыусының үҙгәртеүҙәр исемлеге түгел.",
+       "apihelp-query+alldeletedrevisions-param-namespace": "Бары тик был исемдәр арауығындағы биттәр исемлеге.",
+       "apihelp-query+alldeletedrevisions-example-ns-main": "Төп исемдәр арауығында юйылған тәүге 50 үҙгәртеү исемлеге.",
+       "apihelp-query+allfileusages-description": "Юйылғандар менән бергә барлыҡ файлдар тәртибе исемлеге.",
+       "apihelp-query+allfileusages-param-from": "Һанауҙы башлау өсөн файл атамаһы.",
+       "apihelp-query+allfileusages-param-to": "Һанауҙы туҡтатыу файлы атамаһы.",
+       "apihelp-query+allfileusages-param-prefix": "Был мәғәнәнән башланған бар атамаларҙы категориялар буйынса эҙләргә.",
+       "apihelp-query+allfileusages-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+allfileusages-paramvalue-prop-title": "Файл атамаһына ҡуша.",
+       "apihelp-query+allfileusages-param-limit": "Нисә битте тергеҙергә?",
+       "apihelp-query+allfileusages-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+allfileusages-example-unique": "Атамаларҙың уҙенсәлекле файлдары исемлеге.",
+       "apihelp-query+allfileusages-example-unique-generator": "Төшөп ҡалғандарҙы айырып, барлыҡ исем-һылтанмаларҙы алырға.",
+       "apihelp-query+allfileusages-example-generator": "Файлдар менән биттәр бар.",
+       "apihelp-query+allimages-description": "Бер-бер артлы бөтә образдарҙы һанап сығырға.",
+       "apihelp-query+allimages-param-sort": "Сортировкалау үҙенсәлектәре.",
+       "apihelp-query+allimages-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+allimages-param-minsize": "Һүрәттәр лимиты (байттарҙа).",
+       "apihelp-query+allimages-param-maxsize": "Бар һүрәттәр лимиты (байттарҙа).",
+       "apihelp-query+allimages-param-limit": "Кире ҡайтыу өсөн образдар һаны.",
+       "apihelp-query+allimages-example-B": "<kbd>Б</kbd> хәрефенән башланған файлдар исемлеген күрһәтергә.",
+       "apihelp-query+allimages-example-recent": "Күптән түгел тейәлгән һәм [[специальные:NewFiles]] оҡшаш файлдар исемлеген күрһәтергә.",
+       "apihelp-query+allimages-example-generator": "<kbd>Т</kbd> хәрефенән башланған 4 файл хаҡында мәғлүмәтте  күрһәтергә.",
+       "apihelp-query+alllinks-description": "Бирелгән исемдәр арауығына йүнәлткән барлыҡ һылтанмаларҙы һанап сығырға.",
+       "apihelp-query+alllinks-param-from": "Һанауҙы башлау өсөн һылтанма атамаһы.",
+       "apihelp-query+alllinks-param-to": "Һанауҙы туҡтатыу һылтанмаһы атамаһы.",
+       "apihelp-query+alllinks-param-prefix": "Был мәғәнәнән башланған бәйләнешле бар атамаларҙы эҙләргә.",
+       "apihelp-query+alllinks-param-prop": "Ҡайһы мәғлүмәтте күрһәтергә:",
+       "apihelp-query+alllinks-paramvalue-prop-title": "Һылтанма атамаһын ҡуша.",
+       "apihelp-query+alllinks-param-namespace": "Һанау өсөн исемдәр арауығы.",
+       "apihelp-query+alllinks-param-limit": "Нисә элементты тергеҙергә?",
+       "apihelp-query+alllinks-param-dir": "Һанау йүнәлеше.",
+       "apihelp-query+alllinks-example-unique": "Атамаларҙың үҙенсәлекле исемдәре бәйләнгән.",
        "apihelp-query+alllinks-example-unique-generator": "Получить все названия-ссылки, выделяя пропущенные.",
+       "apihelp-query+alllinks-example-generator": "Һылтанмалы биттәр бар.",
+       "apihelp-query+allmessages-description": "Был сайттан хәбәр ҡайтарыу.",
+       "apihelp-query+allmessages-param-prop": "Ниндәй үҙенсәлектәрҙе ҡайтарырға.",
+       "apihelp-query+allmessages-param-args": "Аргументтар Хәбәрҙәрҙә биреләсәк.",
        "apihelp-query+blocks-example-simple": "Список блоков.",
        "apihelp-query+categories-param-limit": "Сколько категорий на возврат.",
        "apihelp-query+categorymembers-param-sort": "Свойство для сортировки.",
        "apihelp-query+categorymembers-param-startsortkey": "Использовать $1starthexsortkey вместо.",
        "apihelp-query+categorymembers-param-endsortkey": "Использовать $1endhexsortkey вместо.",
+       "apihelp-query+deletedrevs-param-limit": "Исемлектәге яҙмаларҙың иң күбе.",
+       "apihelp-query+deletedrevs-example-mode1": "Юҡ ителгән һуңғы биттәрҙең исемлеге, баш биттең<kbd>-һы </kbd> һәм<kbd>әйтергә:баш биттең /kbd>-һы,континент менән(режим 1).",
+       "apihelp-query+deletedrevs-example-mode3-talk": "Юҡ ителгән тәүге 50 биттең исемлеге {{НС:фекер алышыу}} исемдәр арауығы(режим 3).",
        "apihelp-query+duplicatefiles-example-generated": "Поиск дубликатов всех файлов.",
        "apihelp-query+logevents-description": "Получать события из журналов.",
        "apihelp-query+logevents-example-simple": "Список последних зарегистрированных событий.",
index 4b0a00e..a525f2e 100644 (file)
        "apihelp-imagerotate-example-simple": "Повернути <kbd>File:Example.png</kbd> на <kbd>90</kbd> градусів.",
        "apihelp-imagerotate-example-generator": "Повернути усі зображення у <kbd>Category:Flip</kbd> на <kbd>180</kbd> градусів.",
        "apihelp-import-description": "Імпортувати сторінку з іншої вікі або з XML-файлу.\n\nЗважте, що HTTP POST має бути виконано як завантаження файлу (тобто з використанням даних різних частин/форм) під час надсилання файлу для параметра <var>xml</var>.",
-       "apihelp-import-param-summary": "Ð\86мпоÑ\80Ñ\82Ñ\83ваÑ\82и Ð¿Ñ\96дÑ\81Ñ\83мок.",
+       "apihelp-import-param-summary": "Ð\9fÑ\96дÑ\81Ñ\83мок Ñ\96мпоÑ\80Ñ\82Ñ\83 Ð·Ð°Ð¿Ð¸Ñ\81Ñ\96в Ð¶Ñ\83Ñ\80налÑ\83.",
        "apihelp-import-param-xml": "Завантажено XML-файл.",
        "apihelp-import-param-interwikisource": "Для інтервікі-імпорту: вікі, з якої імпортувати.",
        "apihelp-import-param-interwikipage": "Для інтервікі-імпорту: сторінки для імпорту.",
index 0bb5f63..6e2ff5a 100644 (file)
@@ -61,6 +61,7 @@
        "apihelp-edit-param-unwatch": "Bỏ trang này khỏi danh sách theo dõi của người dùng hiện tại.",
        "apihelp-edit-param-undo": "Hoàn tác sửa đổi này. Ghi đè $1text, $1prependtext và $ 1appendtext.",
        "apihelp-edit-param-undoafter": "Hoàn tác tất cả các sửa đổi từ $1undo cho tới sửa đổi này. Nếu không được thiết lập, chỉ cần lùi lại một sửa đổi.",
+       "apihelp-edit-param-redirect": "Tự động giải quyết các chuyển hướng.",
        "apihelp-edit-example-edit": "Sửa đổi trang",
        "apihelp-edit-example-prepend": "Đưa <kbd>_&#95;NOTOC_&#95;</kbd> vào đầu trang",
        "apihelp-edit-example-undo": "Lùi sửa các thay đổi 13579–13585 và tự động tóm lược",
        "apihelp-expandtemplates-description": "Bung tất cả bản mẫu trong văn bản wiki.",
        "apihelp-expandtemplates-param-title": "Tên trang.",
        "apihelp-expandtemplates-param-text": "Văn bản wiki để bung.",
+       "apihelp-expandtemplates-paramvalue-prop-wikitext": "Wikitext mở rộng.",
        "apihelp-expandtemplates-paramvalue-prop-parsetree": "Cây phân tích XML của đầu vào.",
        "apihelp-feedcontributions-description": "Trả về nguồn cấp đóng góp người dùng.",
        "apihelp-feedcontributions-param-feedformat": "Định dạng nguồn cấp.",
        "apihelp-feedcontributions-param-user": "Người dùng nhận được những đóng góp gì.",
+       "apihelp-feedcontributions-param-namespace": "Không gian tên để lọc các khoản đóng góp của.",
        "apihelp-feedcontributions-param-year": "Từ năm (trở về trước).",
        "apihelp-feedcontributions-param-month": "Từ tháng (trở về trước).",
+       "apihelp-feedcontributions-param-tagfilter": "Lọc đóng góp có những thẻ này.",
        "apihelp-feedcontributions-param-deletedonly": "Chỉ hiện các đóng góp đã xóa.",
        "apihelp-feedcontributions-param-toponly": "Chỉ hiện các phiên bản mới nhất.",
        "apihelp-feedcontributions-param-newonly": "Chỉ hiện các sửa đổi tạo trang.",
        "apihelp-imagerotate-param-rotation": "Độ xoay hình ảnh theo chiều kim đồng hồ.",
        "apihelp-imagerotate-example-simple": "Xoay <kbd>Tập tin:Ví dụ.jpg</kbd> <kbd>90</kbd> độ.",
        "apihelp-imagerotate-example-generator": "Xoay tất cả các hình ảnh trong <kbd>Thể loại:Búng</kbd> <kbd>180</kbd> độ.",
+       "apihelp-import-param-summary": "Nhập tóm lược.",
+       "apihelp-import-param-xml": "Tập tin XML đã được tải lên.",
        "apihelp-import-param-interwikisource": "Dành cho các nhập khẩu interwiki: wiki để nhập từ.",
        "apihelp-login-param-name": "Tên người dùng.",
        "apihelp-login-param-password": "Mật khẩu.",
        "apihelp-login-example-gettoken": "Lấy dấu hiệu đăng nhập",
        "apihelp-login-example-login": "Đăng nhập",
        "apihelp-logout-example-logout": "Đăng xuất người dùng hiện tại",
+       "apihelp-mergehistory-description": "Hợp nhất lịch sử trang.",
+       "apihelp-mergehistory-param-reason": "Lý do hợp nhất lịch sử.",
        "apihelp-move-description": "Di chuyển trang.",
        "apihelp-move-param-reason": "Lý do đổi tên.",
+       "apihelp-move-param-movesubpages": "Đổi tên trang con, nếu có thể áp dụng.",
        "apihelp-move-param-noredirect": "Không tạo trang đổi hướng.",
        "apihelp-move-param-ignorewarnings": "Bỏ qua tất cả các cảnh báo.",
        "apihelp-opensearch-description": "Tìm kiếm trong wiki qua giao thức OpenSearch.",
        "apihelp-opensearch-param-format": "Định dạng kết quả được cho ra.",
        "apihelp-opensearch-example-te": "Tìm trang bắt đầu với <kbd>Te</kbd>.",
        "apihelp-options-example-reset": "Mặc định lại các tùy chọn",
+       "apihelp-paraminfo-description": "Lấy thông tin về các module API.",
        "apihelp-paraminfo-param-helpformat": "Định dạng chuỗi trợ giúp.",
        "apihelp-parse-param-summary": "Lời tóm lược để phân tích.",
        "apihelp-parse-param-section": "Chỉ phân tích nội dung của số phần này.\n\nNếu có <kbd>new</kbd> thì phân tích <var>$1text</var> và <var>$1sectiontitle</var> như thể thêm phần mới vào trang.\n\nPhần <kbd>new</kbd> chỉ được chấp nhận khi định rõ <var>text</var>.",
index fb8464c..c3ea00a 100644 (file)
        "apihelp-imagerotate-example-simple": "<kbd>90</kbd>度旋转<kbd>File:Example.png</kbd>。",
        "apihelp-imagerotate-example-generator": "将<kbd>Category:Flip</kbd>之中的所有图像旋转<kbd>180</kbd>度。",
        "apihelp-import-description": "从另一个wiki或从一个XML文件导入页面。\n\n注意当发送一个用于<var>xml</var>参数的文件时,HTTP POST必须作为一次文件上传完成(也就是使用multipart/form-data)。",
-       "apihelp-import-param-summary": "导入摘要。",
+       "apihelp-import-param-summary": "日志记录导入摘要。",
        "apihelp-import-param-xml": "上传的XML文件。",
        "apihelp-import-param-interwikisource": "用于跨wiki导入:导入的来源wiki。",
        "apihelp-import-param-interwikipage": "用于跨wiki导入:导入的页面。",
index a954d9f..361fe23 100644 (file)
@@ -279,7 +279,7 @@ class BacklinkCache {
                                $conds = [
                                        "{$prefix}_namespace" => $this->title->getNamespace(),
                                        "{$prefix}_title" => $this->title->getDBkey(),
-                                       $this->getDb()->makeList( [
+                                       $this->getDB()->makeList( [
                                                "{$prefix}_interwiki" => '',
                                                "{$prefix}_interwiki IS NULL",
                                        ], LIST_OR ),
diff --git a/includes/cache/LCStoreStaticArray.php b/includes/cache/LCStoreStaticArray.php
deleted file mode 100644 (file)
index 1e20082..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-/**
- *  Localisation cache storage based on PHP files and static arrays.
- *
- * 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
- */
-
-/**
- * @since 1.26
- */
-class LCStoreStaticArray implements LCStore {
-       /** @var string|null Current language code. */
-       private $currentLang = null;
-
-       /** @var array Localisation data. */
-       private $data = [];
-
-       /** @var string File name. */
-       private $fname = null;
-
-       /** @var string Directory for cache files. */
-       private $directory;
-
-       public function __construct( $conf = [] ) {
-               global $wgCacheDirectory;
-
-               if ( isset( $conf['directory'] ) ) {
-                       $this->directory = $conf['directory'];
-               } else {
-                       $this->directory = $wgCacheDirectory;
-               }
-       }
-
-       public function startWrite( $code ) {
-               $this->currentLang = $code;
-               $this->fname = $this->directory . '/' . $code . '.l10n.php';
-               $this->data[$code] = [];
-               if ( file_exists( $this->fname ) ) {
-                       $this->data[$code] = require $this->fname;
-               }
-       }
-
-       public function set( $key, $value ) {
-               $this->data[$this->currentLang][$key] = self::encode( $value );
-       }
-
-       /**
-        * Encodes a value into an array format
-        *
-        * @param mixed $value
-        * @return array
-        * @throws RuntimeException
-        */
-       public static function encode( $value ) {
-               if ( is_scalar( $value ) || $value === null ) {
-                       // [V]alue
-                       return [ 'v', $value ];
-               }
-               if ( is_object( $value ) ) {
-                       // [S]erialized
-                       return [ 's', serialize( $value ) ];
-               }
-               if ( is_array( $value ) ) {
-                       // [A]rray
-                       return [ 'a', array_map( function ( $v ) {
-                               return LCStoreStaticArray::encode( $v );
-                       }, $value ) ];
-               }
-
-               throw new RuntimeException( 'Cannot encode ' . var_export( $value, true ) );
-       }
-
-       /**
-        * Decode something that was encoded with encode
-        *
-        * @param array $encoded
-        * @return array|mixed
-        * @throws RuntimeException
-        */
-       public static function decode( array $encoded ) {
-               $type = $encoded[0];
-               $data = $encoded[1];
-
-               switch ( $type ) {
-               case 'v':
-                       return $data;
-               case 's':
-                       return unserialize( $data );
-               case 'a':
-                       return array_map( function ( $v ) {
-                               return LCStoreStaticArray::decode( $v );
-                       }, $data );
-               default:
-                       throw new RuntimeException(
-                               'Unable to decode ' . var_export( $encoded, true ) );
-               }
-       }
-
-       public function finishWrite() {
-               file_put_contents(
-                       $this->fname,
-                       "<?php\n" .
-                       "// Generated by LCStoreStaticArray.php -- do not edit!\n" .
-                       "return " .
-                       var_export( $this->data[$this->currentLang], true ) . ';'
-               );
-               $this->currentLang = null;
-               $this->fname = null;
-       }
-
-       public function get( $code, $key ) {
-               if ( !array_key_exists( $code, $this->data ) ) {
-                       $fname = $this->directory . '/' . $code . '.l10n.php';
-                       if ( !file_exists( $fname ) ) {
-                               return null;
-                       }
-                       $this->data[$code] = require $fname;
-               }
-               $data = $this->data[$code];
-               if ( array_key_exists( $key, $data ) ) {
-                       return self::decode( $data[$key] );
-               }
-               return null;
-       }
-}
diff --git a/includes/cache/LocalisationCache.php b/includes/cache/LocalisationCache.php
deleted file mode 100644 (file)
index 6efeabe..0000000
+++ /dev/null
@@ -1,1479 +0,0 @@
-<?php
-/**
- * Cache of the contents of localisation files.
- *
- * 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
- */
-
-use Cdb\Exception as CdbException;
-use Cdb\Reader as CdbReader;
-use Cdb\Writer as CdbWriter;
-use CLDRPluralRuleParser\Evaluator;
-
-/**
- * Class for caching the contents of localisation files, Messages*.php
- * and *.i18n.php.
- *
- * An instance of this class is available using Language::getLocalisationCache().
- *
- * The values retrieved from here are merged, containing items from extension
- * files, core messages files and the language fallback sequence (e.g. zh-cn ->
- * zh-hans -> en ). Some common errors are corrected, for example namespace
- * names with spaces instead of underscores, but heavyweight processing, such
- * as grammatical transformation, is done by the caller.
- */
-class LocalisationCache {
-       const VERSION = 4;
-
-       /** Configuration associative array */
-       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.
-        */
-       private $manualRecache = false;
-
-       /**
-        * True to treat all files as expired until they are regenerated by this object.
-        */
-       private $forceRecache = false;
-
-       /**
-        * The cache data. 3-d array, where the first key is the language code,
-        * the second key is the item key e.g. 'messages', and the third key is
-        * an item specific subkey index. Some items are not arrays and so for those
-        * items, there are no subkeys.
-        */
-       protected $data = [];
-
-       /**
-        * The persistent store object. An instance of LCStore.
-        *
-        * @var LCStore
-        */
-       private $store;
-
-       /**
-        * A 2-d associative array, code/key, where presence indicates that the item
-        * is loaded. Value arbitrary.
-        *
-        * For split items, if set, this indicates that all of the subitems have been
-        * loaded.
-        */
-       private $loadedItems = [];
-
-       /**
-        * 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.
-        */
-       private $loadedSubitems = [];
-
-       /**
-        * 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.
-        */
-       private $initialisedLangs = [];
-
-       /**
-        * 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.
-        */
-       private $shallowFallbacks = [];
-
-       /**
-        * An array where the keys are codes that have been recached by this instance.
-        */
-       private $recachedLangs = [];
-
-       /**
-        * All item keys
-        */
-       static public $allKeys = [
-               'fallback', 'namespaceNames', 'bookstoreList',
-               'magicWords', 'messages', 'rtl', 'capitalizeAllNouns', 'digitTransformTable',
-               'separatorTransformTable', 'fallback8bitEncoding', 'linkPrefixExtension',
-               'linkTrail', 'linkPrefixCharset', 'namespaceAliases',
-               'dateFormats', 'datePreferences', 'datePreferenceMigrationMap',
-               'defaultDateFormat', 'extraUserToggles', 'specialPageAliases',
-               'imageFiles', 'preloadedMessages', 'namespaceGenderAliases',
-               'digitGroupingPattern', 'pluralRules', 'pluralRuleTypes', 'compiledPluralRules',
-       ];
-
-       /**
-        * Keys for items which consist of associative arrays, which may be merged
-        * by a fallback sequence.
-        */
-       static public $mergeableMapKeys = [ 'messages', 'namespaceNames',
-               'namespaceAliases', 'dateFormats', 'imageFiles', 'preloadedMessages'
-       ];
-
-       /**
-        * Keys for items which are a numbered array.
-        */
-       static public $mergeableListKeys = [ 'extraUserToggles' ];
-
-       /**
-        * Keys for items which contain an array of arrays of equivalent aliases
-        * for each subitem. The aliases may be merged by a fallback sequence.
-        */
-       static public $mergeableAliasListKeys = [ 'specialPageAliases' ];
-
-       /**
-        * Keys for items which contain an associative array, and may be merged if
-        * the primary value contains the special array key "inherit". That array
-        * key is removed after the first merge.
-        */
-       static public $optionalMergeKeys = [ 'bookstoreList' ];
-
-       /**
-        * Keys for items that are formatted like $magicWords
-        */
-       static public $magicWordKeys = [ 'magicWords' ];
-
-       /**
-        * Keys for items where the subitems are stored in the backend separately.
-        */
-       static public $splitKeys = [ 'messages' ];
-
-       /**
-        * Keys which are loaded automatically by initLanguage()
-        */
-       static public $preloadedKeys = [ 'dateFormats', 'namespaceNames' ];
-
-       /**
-        * Associative array of cached plural rules. The key is the language code,
-        * the value is an array of plural rules for that language.
-        */
-       private $pluralRules = null;
-
-       /**
-        * Associative array of cached plural rule types. The key is the language
-        * code, the value is an array of plural rule types for that language. For
-        * example, $pluralRuleTypes['ar'] = ['zero', 'one', 'two', 'few', 'many'].
-        * The index for each rule type matches the index for the rule in
-        * $pluralRules, thus allowing correlation between the two. The reason we
-        * don't just use the type names as the keys in $pluralRules is because
-        * Language::convertPlural applies the rules based on numeric order (or
-        * explicit numeric parameter), not based on the name of the rule type. For
-        * example, {{plural:count|wordform1|wordform2|wordform3}}, rather than
-        * {{plural:count|one=wordform1|two=wordform2|many=wordform3}}.
-        */
-       private $pluralRuleTypes = null;
-
-       private $mergeableKeys = null;
-
-       /**
-        * Constructor.
-        * For constructor parameters, see the documentation in DefaultSettings.php
-        * for $wgLocalisationCacheConf.
-        *
-        * @param array $conf
-        * @throws MWException
-        */
-       function __construct( $conf ) {
-               global $wgCacheDirectory;
-
-               $this->conf = $conf;
-               $storeConf = [];
-               if ( !empty( $conf['storeClass'] ) ) {
-                       $storeClass = $conf['storeClass'];
-               } else {
-                       switch ( $conf['store'] ) {
-                               case 'files':
-                               case 'file':
-                                       $storeClass = 'LCStoreCDB';
-                                       break;
-                               case 'db':
-                                       $storeClass = 'LCStoreDB';
-                                       break;
-                               case 'array':
-                                       $storeClass = 'LCStoreStaticArray';
-                                       break;
-                               case 'detect':
-                                       if ( !empty( $conf['storeDirectory'] ) ) {
-                                               $storeClass = 'LCStoreCDB';
-                                       } else {
-                                               $cacheDir = $wgCacheDirectory ?: wfTempDir();
-                                               if ( $cacheDir ) {
-                                                       $storeConf['directory'] = $cacheDir;
-                                                       $storeClass = 'LCStoreCDB';
-                                               } else {
-                                                       $storeClass = 'LCStoreDB';
-                                               }
-                                       }
-                                       break;
-                               default:
-                                       throw new MWException(
-                                               'Please set $wgLocalisationCacheConf[\'store\'] to something sensible.' );
-                       }
-               }
-
-               wfDebugLog( 'caches', get_class( $this ) . ": using store $storeClass" );
-               if ( !empty( $conf['storeDirectory'] ) ) {
-                       $storeConf['directory'] = $conf['storeDirectory'];
-               }
-
-               $this->store = new $storeClass( $storeConf );
-               foreach ( [ 'manualRecache', 'forceRecache' ] as $var ) {
-                       if ( isset( $conf[$var] ) ) {
-                               $this->$var = $conf[$var];
-                       }
-               }
-       }
-
-       /**
-        * Returns true if the given key is mergeable, that is, if it is an associative
-        * array which can be merged through a fallback sequence.
-        * @param string $key
-        * @return bool
-        */
-       public function isMergeableKey( $key ) {
-               if ( $this->mergeableKeys === null ) {
-                       $this->mergeableKeys = array_flip( array_merge(
-                               self::$mergeableMapKeys,
-                               self::$mergeableListKeys,
-                               self::$mergeableAliasListKeys,
-                               self::$optionalMergeKeys,
-                               self::$magicWordKeys
-                       ) );
-               }
-
-               return isset( $this->mergeableKeys[$key] );
-       }
-
-       /**
-        * Get a cache item.
-        *
-        * Warning: this may be slow for split items (messages), since it will
-        * need to fetch all of the subitems from the cache individually.
-        * @param string $code
-        * @param string $key
-        * @return mixed
-        */
-       public function getItem( $code, $key ) {
-               if ( !isset( $this->loadedItems[$code][$key] ) ) {
-                       $this->loadItem( $code, $key );
-               }
-
-               if ( $key === 'fallback' && isset( $this->shallowFallbacks[$code] ) ) {
-                       return $this->shallowFallbacks[$code];
-               }
-
-               return $this->data[$code][$key];
-       }
-
-       /**
-        * Get a subitem, for instance a single message for a given language.
-        * @param string $code
-        * @param string $key
-        * @param string $subkey
-        * @return mixed|null
-        */
-       public function getSubitem( $code, $key, $subkey ) {
-               if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) &&
-                       !isset( $this->loadedItems[$code][$key] )
-               ) {
-                       $this->loadSubitem( $code, $key, $subkey );
-               }
-
-               if ( isset( $this->data[$code][$key][$subkey] ) ) {
-                       return $this->data[$code][$key][$subkey];
-               } else {
-                       return null;
-               }
-       }
-
-       /**
-        * Get the list of subitem keys for a given item.
-        *
-        * This is faster than array_keys($lc->getItem(...)) for the items listed in
-        * self::$splitKeys.
-        *
-        * Will return null if the item is not found, or false if the item is not an
-        * array.
-        * @param string $code
-        * @param string $key
-        * @return bool|null|string
-        */
-       public function getSubitemList( $code, $key ) {
-               if ( in_array( $key, self::$splitKeys ) ) {
-                       return $this->getSubitem( $code, 'list', $key );
-               } else {
-                       $item = $this->getItem( $code, $key );
-                       if ( is_array( $item ) ) {
-                               return array_keys( $item );
-                       } else {
-                               return false;
-                       }
-               }
-       }
-
-       /**
-        * Load an item into the cache.
-        * @param string $code
-        * @param string $key
-        */
-       protected function loadItem( $code, $key ) {
-               if ( !isset( $this->initialisedLangs[$code] ) ) {
-                       $this->initLanguage( $code );
-               }
-
-               // Check to see if initLanguage() loaded it for us
-               if ( isset( $this->loadedItems[$code][$key] ) ) {
-                       return;
-               }
-
-               if ( isset( $this->shallowFallbacks[$code] ) ) {
-                       $this->loadItem( $this->shallowFallbacks[$code], $key );
-
-                       return;
-               }
-
-               if ( in_array( $key, self::$splitKeys ) ) {
-                       $subkeyList = $this->getSubitem( $code, 'list', $key );
-                       foreach ( $subkeyList as $subkey ) {
-                               if ( isset( $this->data[$code][$key][$subkey] ) ) {
-                                       continue;
-                               }
-                               $this->data[$code][$key][$subkey] = $this->getSubitem( $code, $key, $subkey );
-                       }
-               } else {
-                       $this->data[$code][$key] = $this->store->get( $code, $key );
-               }
-
-               $this->loadedItems[$code][$key] = true;
-       }
-
-       /**
-        * Load a subitem into the cache
-        * @param string $code
-        * @param string $key
-        * @param string $subkey
-        */
-       protected function loadSubitem( $code, $key, $subkey ) {
-               if ( !in_array( $key, self::$splitKeys ) ) {
-                       $this->loadItem( $code, $key );
-
-                       return;
-               }
-
-               if ( !isset( $this->initialisedLangs[$code] ) ) {
-                       $this->initLanguage( $code );
-               }
-
-               // Check to see if initLanguage() loaded it for us
-               if ( isset( $this->loadedItems[$code][$key] ) ||
-                       isset( $this->loadedSubitems[$code][$key][$subkey] )
-               ) {
-                       return;
-               }
-
-               if ( isset( $this->shallowFallbacks[$code] ) ) {
-                       $this->loadSubitem( $this->shallowFallbacks[$code], $key, $subkey );
-
-                       return;
-               }
-
-               $value = $this->store->get( $code, "$key:$subkey" );
-               $this->data[$code][$key][$subkey] = $value;
-               $this->loadedSubitems[$code][$key][$subkey] = true;
-       }
-
-       /**
-        * Returns true if the cache identified by $code is missing or expired.
-        *
-        * @param string $code
-        *
-        * @return bool
-        */
-       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 for some stores
-               if ( $deps === null || $keys === null || $preload === null ) {
-                       wfDebug( __METHOD__ . "($code): cache missing, need to make one\n" );
-
-                       return true;
-               }
-
-               foreach ( $deps as $dep ) {
-                       // Because we're unserializing stuff from cache, we
-                       // could receive objects of classes that don't exist
-                       // anymore (e.g. uninstalled extensions)
-                       // When this happens, always expire the cache
-                       if ( !$dep instanceof CacheDependency || $dep->isExpired() ) {
-                               wfDebug( __METHOD__ . "($code): cache for $code expired due to " .
-                                       get_class( $dep ) . "\n" );
-
-                               return true;
-                       }
-               }
-
-               return false;
-       }
-
-       /**
-        * Initialise a language in this object. Rebuild the cache if necessary.
-        * @param string $code
-        * @throws MWException
-        */
-       protected function initLanguage( $code ) {
-               if ( isset( $this->initialisedLangs[$code] ) ) {
-                       return;
-               }
-
-               $this->initialisedLangs[$code] = true;
-
-               # 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;
-               }
-
-               # Recache the data if necessary
-               if ( !$this->manualRecache && $this->isExpired( $code ) ) {
-                       if ( Language::isSupportedLanguage( $code ) ) {
-                               $this->recache( $code );
-                       } elseif ( $code === 'en' ) {
-                               throw new MWException( 'MessagesEn.php is missing.' );
-                       } else {
-                               $this->initShallowFallback( $code, 'en' );
-                       }
-
-                       return;
-               }
-
-               # Preload some stuff
-               $preload = $this->getItem( $code, 'preload' );
-               if ( $preload === null ) {
-                       if ( $this->manualRecache ) {
-                               // No Messages*.php file. Do shallow fallback to en.
-                               if ( $code === 'en' ) {
-                                       throw new MWException( 'No localisation cache found for English. ' .
-                                               'Please run maintenance/rebuildLocalisationCache.php.' );
-                               }
-                               $this->initShallowFallback( $code, 'en' );
-
-                               return;
-                       } else {
-                               throw new MWException( 'Invalid or missing localisation cache.' );
-                       }
-               }
-               $this->data[$code] = $preload;
-               foreach ( $preload as $key => $item ) {
-                       if ( in_array( $key, self::$splitKeys ) ) {
-                               foreach ( $item as $subkey => $subitem ) {
-                                       $this->loadedSubitems[$code][$key][$subkey] = true;
-                               }
-                       } else {
-                               $this->loadedItems[$code][$key] = true;
-                       }
-               }
-       }
-
-       /**
-        * Create a fallback from one language to another, without creating a
-        * complete persistent cache.
-        * @param string $primaryCode
-        * @param string $fallbackCode
-        */
-       public function initShallowFallback( $primaryCode, $fallbackCode ) {
-               $this->data[$primaryCode] =& $this->data[$fallbackCode];
-               $this->loadedItems[$primaryCode] =& $this->loadedItems[$fallbackCode];
-               $this->loadedSubitems[$primaryCode] =& $this->loadedSubitems[$fallbackCode];
-               $this->shallowFallbacks[$primaryCode] = $fallbackCode;
-       }
-
-       /**
-        * Read a PHP file containing localisation data.
-        * @param string $_fileName
-        * @param string $_fileType
-        * @throws MWException
-        * @return array
-        */
-       protected function readPHPFile( $_fileName, $_fileType ) {
-               // Disable APC caching
-               MediaWiki\suppressWarnings();
-               $_apcEnabled = ini_set( 'apc.cache_by_default', '0' );
-               MediaWiki\restoreWarnings();
-
-               include $_fileName;
-
-               MediaWiki\suppressWarnings();
-               ini_set( 'apc.cache_by_default', $_apcEnabled );
-               MediaWiki\restoreWarnings();
-
-               if ( $_fileType == 'core' || $_fileType == 'extension' ) {
-                       $data = compact( self::$allKeys );
-               } elseif ( $_fileType == 'aliases' ) {
-                       $data = compact( 'aliases' );
-               } else {
-                       throw new MWException( __METHOD__ . ": Invalid file type: $_fileType" );
-               }
-
-               return $data;
-       }
-
-       /**
-        * Read a JSON file containing localisation messages.
-        * @param string $fileName Name of file to read
-        * @throws MWException If there is a syntax error in the JSON file
-        * @return array Array with a 'messages' key, or empty array if the file doesn't exist
-        */
-       public function readJSONFile( $fileName ) {
-
-               if ( !is_readable( $fileName ) ) {
-                       return [];
-               }
-
-               $json = file_get_contents( $fileName );
-               if ( $json === false ) {
-                       return [];
-               }
-
-               $data = FormatJson::decode( $json, true );
-               if ( $data === null ) {
-
-                       throw new MWException( __METHOD__ . ": Invalid JSON file: $fileName" );
-               }
-
-               // Remove keys starting with '@', they're reserved for metadata and non-message data
-               foreach ( $data as $key => $unused ) {
-                       if ( $key === '' || $key[0] === '@' ) {
-                               unset( $data[$key] );
-                       }
-               }
-
-               // The JSON format only supports messages, none of the other variables, so wrap the data
-               return [ 'messages' => $data ];
-       }
-
-       /**
-        * Get the compiled plural rules for a given language from the XML files.
-        * @since 1.20
-        * @param string $code
-        * @return array|null
-        */
-       public function getCompiledPluralRules( $code ) {
-               $rules = $this->getPluralRules( $code );
-               if ( $rules === null ) {
-                       return null;
-               }
-               try {
-                       $compiledRules = Evaluator::compile( $rules );
-               } catch ( CLDRPluralRuleError $e ) {
-                       wfDebugLog( 'l10n', $e->getMessage() );
-
-                       return [];
-               }
-
-               return $compiledRules;
-       }
-
-       /**
-        * Get the plural rules for a given language from the XML files.
-        * Cached.
-        * @since 1.20
-        * @param string $code
-        * @return array|null
-        */
-       public function getPluralRules( $code ) {
-               if ( $this->pluralRules === null ) {
-                       $this->loadPluralFiles();
-               }
-               if ( !isset( $this->pluralRules[$code] ) ) {
-                       return null;
-               } else {
-                       return $this->pluralRules[$code];
-               }
-       }
-
-       /**
-        * Get the plural rule types for a given language from the XML files.
-        * Cached.
-        * @since 1.22
-        * @param string $code
-        * @return array|null
-        */
-       public function getPluralRuleTypes( $code ) {
-               if ( $this->pluralRuleTypes === null ) {
-                       $this->loadPluralFiles();
-               }
-               if ( !isset( $this->pluralRuleTypes[$code] ) ) {
-                       return null;
-               } else {
-                       return $this->pluralRuleTypes[$code];
-               }
-       }
-
-       /**
-        * Load the plural XML files.
-        */
-       protected function loadPluralFiles() {
-               global $IP;
-               $cldrPlural = "$IP/languages/data/plurals.xml";
-               $mwPlural = "$IP/languages/data/plurals-mediawiki.xml";
-               // Load CLDR plural rules
-               $this->loadPluralFile( $cldrPlural );
-               if ( file_exists( $mwPlural ) ) {
-                       // Override or extend
-                       $this->loadPluralFile( $mwPlural );
-               }
-       }
-
-       /**
-        * Load a plural XML file with the given filename, compile the relevant
-        * rules, and save the compiled rules in a process-local cache.
-        *
-        * @param string $fileName
-        * @throws MWException
-        */
-       protected function loadPluralFile( $fileName ) {
-               // Use file_get_contents instead of DOMDocument::load (T58439)
-               $xml = file_get_contents( $fileName );
-               if ( !$xml ) {
-                       throw new MWException( "Unable to read plurals file $fileName" );
-               }
-               $doc = new DOMDocument;
-               $doc->loadXML( $xml );
-               $rulesets = $doc->getElementsByTagName( "pluralRules" );
-               foreach ( $rulesets as $ruleset ) {
-                       $codes = $ruleset->getAttribute( 'locales' );
-                       $rules = [];
-                       $ruleTypes = [];
-                       $ruleElements = $ruleset->getElementsByTagName( "pluralRule" );
-                       foreach ( $ruleElements as $elt ) {
-                               $ruleType = $elt->getAttribute( 'count' );
-                               if ( $ruleType === 'other' ) {
-                                       // Don't record "other" rules, which have an empty condition
-                                       continue;
-                               }
-                               $rules[] = $elt->nodeValue;
-                               $ruleTypes[] = $ruleType;
-                       }
-                       foreach ( explode( ' ', $codes ) as $code ) {
-                               $this->pluralRules[$code] = $rules;
-                               $this->pluralRuleTypes[$code] = $ruleTypes;
-                       }
-               }
-       }
-
-       /**
-        * Read the data from the source files for a given language, and register
-        * the relevant dependencies in the $deps array. If the localisation
-        * exists, the data array is returned, otherwise false is returned.
-        *
-        * @param string $code
-        * @param array $deps
-        * @return array
-        */
-       protected function readSourceFilesAndRegisterDeps( $code, &$deps ) {
-               global $IP;
-
-               // This reads in the PHP i18n file with non-messages l10n data
-               $fileName = Language::getMessagesFileName( $code );
-               if ( !file_exists( $fileName ) ) {
-                       $data = [];
-               } else {
-                       $deps[] = new FileDependency( $fileName );
-                       $data = $this->readPHPFile( $fileName, 'core' );
-               }
-
-               # Load CLDR plural rules for JavaScript
-               $data['pluralRules'] = $this->getPluralRules( $code );
-               # And for PHP
-               $data['compiledPluralRules'] = $this->getCompiledPluralRules( $code );
-               # Load plural rule types
-               $data['pluralRuleTypes'] = $this->getPluralRuleTypes( $code );
-
-               $deps['plurals'] = new FileDependency( "$IP/languages/data/plurals.xml" );
-               $deps['plurals-mw'] = new FileDependency( "$IP/languages/data/plurals-mediawiki.xml" );
-
-               return $data;
-       }
-
-       /**
-        * Merge two localisation values, a primary and a fallback, overwriting the
-        * primary value in place.
-        * @param string $key
-        * @param mixed $value
-        * @param mixed $fallbackValue
-        */
-       protected function mergeItem( $key, &$value, $fallbackValue ) {
-               if ( !is_null( $value ) ) {
-                       if ( !is_null( $fallbackValue ) ) {
-                               if ( in_array( $key, self::$mergeableMapKeys ) ) {
-                                       $value = $value + $fallbackValue;
-                               } elseif ( in_array( $key, self::$mergeableListKeys ) ) {
-                                       $value = array_unique( array_merge( $fallbackValue, $value ) );
-                               } elseif ( in_array( $key, self::$mergeableAliasListKeys ) ) {
-                                       $value = array_merge_recursive( $value, $fallbackValue );
-                               } elseif ( in_array( $key, self::$optionalMergeKeys ) ) {
-                                       if ( !empty( $value['inherit'] ) ) {
-                                               $value = array_merge( $fallbackValue, $value );
-                                       }
-
-                                       if ( isset( $value['inherit'] ) ) {
-                                               unset( $value['inherit'] );
-                                       }
-                               } elseif ( in_array( $key, self::$magicWordKeys ) ) {
-                                       $this->mergeMagicWords( $value, $fallbackValue );
-                               }
-                       }
-               } else {
-                       $value = $fallbackValue;
-               }
-       }
-
-       /**
-        * @param mixed $value
-        * @param mixed $fallbackValue
-        */
-       protected function mergeMagicWords( &$value, $fallbackValue ) {
-               foreach ( $fallbackValue as $magicName => $fallbackInfo ) {
-                       if ( !isset( $value[$magicName] ) ) {
-                               $value[$magicName] = $fallbackInfo;
-                       } else {
-                               $oldSynonyms = array_slice( $fallbackInfo, 1 );
-                               $newSynonyms = array_slice( $value[$magicName], 1 );
-                               $synonyms = array_values( array_unique( array_merge(
-                                       $newSynonyms, $oldSynonyms ) ) );
-                               $value[$magicName] = array_merge( [ $fallbackInfo[0] ], $synonyms );
-                       }
-               }
-       }
-
-       /**
-        * Given an array mapping language code to localisation value, such as is
-        * found in extension *.i18n.php files, iterate through a fallback sequence
-        * to merge the given data with an existing primary value.
-        *
-        * Returns true if any data from the extension array was used, false
-        * otherwise.
-        * @param array $codeSequence
-        * @param string $key
-        * @param mixed $value
-        * @param mixed $fallbackValue
-        * @return bool
-        */
-       protected function mergeExtensionItem( $codeSequence, $key, &$value, $fallbackValue ) {
-               $used = false;
-               foreach ( $codeSequence as $code ) {
-                       if ( isset( $fallbackValue[$code] ) ) {
-                               $this->mergeItem( $key, $value, $fallbackValue[$code] );
-                               $used = true;
-                       }
-               }
-
-               return $used;
-       }
-
-       /**
-        * Gets the combined list of messages dirs from
-        * core and extensions
-        *
-        * @since 1.25
-        * @return array
-        */
-       public function getMessagesDirs() {
-               global $wgMessagesDirs, $IP;
-               return [
-                       'core' => "$IP/languages/i18n",
-                       'api' => "$IP/includes/api/i18n",
-                       'oojs-ui' => "$IP/resources/lib/oojs-ui/i18n",
-               ] + $wgMessagesDirs;
-       }
-
-       /**
-        * Load localisation data for a given language for both core and extensions
-        * and save it to the persistent cache store and the process cache
-        * @param string $code
-        * @throws MWException
-        */
-       public function recache( $code ) {
-               global $wgExtensionMessagesFiles;
-
-               if ( !$code ) {
-                       throw new MWException( "Invalid language code requested" );
-               }
-               $this->recachedLangs[$code] = true;
-
-               # Initial values
-               $initialData = array_fill_keys( self::$allKeys, null );
-               $coreData = $initialData;
-               $deps = [];
-
-               # Load the primary localisation from the source file
-               $data = $this->readSourceFilesAndRegisterDeps( $code, $deps );
-               if ( $data === false ) {
-                       wfDebug( __METHOD__ . ": no localisation file for $code, using fallback to en\n" );
-                       $coreData['fallback'] = 'en';
-               } else {
-                       wfDebug( __METHOD__ . ": got localisation for $code from source\n" );
-
-                       # Merge primary localisation
-                       foreach ( $data as $key => $value ) {
-                               $this->mergeItem( $key, $coreData[$key], $value );
-                       }
-               }
-
-               # Fill in the fallback if it's not there already
-               if ( is_null( $coreData['fallback'] ) ) {
-                       $coreData['fallback'] = $code === 'en' ? false : 'en';
-               }
-               if ( $coreData['fallback'] === false ) {
-                       $coreData['fallbackSequence'] = [];
-               } else {
-                       $coreData['fallbackSequence'] = array_map( 'trim', explode( ',', $coreData['fallback'] ) );
-                       $len = count( $coreData['fallbackSequence'] );
-
-                       # Ensure that the sequence ends at en
-                       if ( $coreData['fallbackSequence'][$len - 1] !== 'en' ) {
-                               $coreData['fallbackSequence'][] = 'en';
-                       }
-               }
-
-               $codeSequence = array_merge( [ $code ], $coreData['fallbackSequence'] );
-               $messageDirs = $this->getMessagesDirs();
-
-               # Load non-JSON localisation data for extensions
-               $extensionData = array_fill_keys( $codeSequence, $initialData );
-               foreach ( $wgExtensionMessagesFiles as $extension => $fileName ) {
-                       if ( isset( $messageDirs[$extension] ) ) {
-                               # This extension has JSON message data; skip the PHP shim
-                               continue;
-                       }
-
-                       $data = $this->readPHPFile( $fileName, 'extension' );
-                       $used = false;
-
-                       foreach ( $data as $key => $item ) {
-                               foreach ( $codeSequence as $csCode ) {
-                                       if ( isset( $item[$csCode] ) ) {
-                                               $this->mergeItem( $key, $extensionData[$csCode][$key], $item[$csCode] );
-                                               $used = true;
-                                       }
-                               }
-                       }
-
-                       if ( $used ) {
-                               $deps[] = new FileDependency( $fileName );
-                       }
-               }
-
-               # Load the localisation data for each fallback, then merge it into the full array
-               $allData = $initialData;
-               foreach ( $codeSequence as $csCode ) {
-                       $csData = $initialData;
-
-                       # Load core messages and the extension localisations.
-                       foreach ( $messageDirs as $dirs ) {
-                               foreach ( (array)$dirs as $dir ) {
-                                       $fileName = "$dir/$csCode.json";
-                                       $data = $this->readJSONFile( $fileName );
-
-                                       foreach ( $data as $key => $item ) {
-                                               $this->mergeItem( $key, $csData[$key], $item );
-                                       }
-
-                                       $deps[] = new FileDependency( $fileName );
-                               }
-                       }
-
-                       # Merge non-JSON extension data
-                       if ( isset( $extensionData[$csCode] ) ) {
-                               foreach ( $extensionData[$csCode] as $key => $item ) {
-                                       $this->mergeItem( $key, $csData[$key], $item );
-                               }
-                       }
-
-                       if ( $csCode === $code ) {
-                               # Merge core data into extension data
-                               foreach ( $coreData as $key => $item ) {
-                                       $this->mergeItem( $key, $csData[$key], $item );
-                               }
-                       } else {
-                               # Load the secondary localisation from the source file to
-                               # avoid infinite cycles on cyclic fallbacks
-                               $fbData = $this->readSourceFilesAndRegisterDeps( $csCode, $deps );
-                               if ( $fbData !== false ) {
-                                       # Only merge the keys that make sense to merge
-                                       foreach ( self::$allKeys as $key ) {
-                                               if ( !isset( $fbData[$key] ) ) {
-                                                       continue;
-                                               }
-
-                                               if ( is_null( $coreData[$key] ) || $this->isMergeableKey( $key ) ) {
-                                                       $this->mergeItem( $key, $csData[$key], $fbData[$key] );
-                                               }
-                                       }
-                               }
-                       }
-
-                       # Allow extensions an opportunity to adjust the data for this
-                       # fallback
-                       Hooks::run( 'LocalisationCacheRecacheFallback', [ $this, $csCode, &$csData ] );
-
-                       # Merge the data for this fallback into the final array
-                       if ( $csCode === $code ) {
-                               $allData = $csData;
-                       } else {
-                               foreach ( self::$allKeys as $key ) {
-                                       if ( !isset( $csData[$key] ) ) {
-                                               continue;
-                                       }
-
-                                       if ( is_null( $allData[$key] ) || $this->isMergeableKey( $key ) ) {
-                                               $this->mergeItem( $key, $allData[$key], $csData[$key] );
-                                       }
-                               }
-                       }
-               }
-
-               # Add cache dependencies for any referenced globals
-               $deps['wgExtensionMessagesFiles'] = new GlobalDependency( 'wgExtensionMessagesFiles' );
-               // $wgMessagesDirs is used in LocalisationCache::getMessagesDirs()
-               $deps['wgMessagesDirs'] = new GlobalDependency( 'wgMessagesDirs' );
-               $deps['version'] = new ConstantDependency( 'LocalisationCache::VERSION' );
-
-               # Add dependencies to the cache entry
-               $allData['deps'] = $deps;
-
-               # Replace spaces with underscores in namespace names
-               $allData['namespaceNames'] = str_replace( ' ', '_', $allData['namespaceNames'] );
-
-               # And do the same for special page aliases. $page is an array.
-               foreach ( $allData['specialPageAliases'] as &$page ) {
-                       $page = str_replace( ' ', '_', $page );
-               }
-               # Decouple the reference to prevent accidental damage
-               unset( $page );
-
-               # If there were no plural rules, return an empty array
-               if ( $allData['pluralRules'] === null ) {
-                       $allData['pluralRules'] = [];
-               }
-               if ( $allData['compiledPluralRules'] === null ) {
-                       $allData['compiledPluralRules'] = [];
-               }
-               # If there were no plural rule types, return an empty array
-               if ( $allData['pluralRuleTypes'] === null ) {
-                       $allData['pluralRuleTypes'] = [];
-               }
-
-               # Set the list keys
-               $allData['list'] = [];
-               foreach ( self::$splitKeys as $key ) {
-                       $allData['list'][$key] = array_keys( $allData[$key] );
-               }
-               # Run hooks
-               $purgeBlobs = true;
-               Hooks::run( 'LocalisationCacheRecache', [ $this, $code, &$allData, &$purgeBlobs ] );
-
-               if ( is_null( $allData['namespaceNames'] ) ) {
-                       throw new MWException( __METHOD__ . ': Localisation data failed sanity check! ' .
-                               'Check that your languages/messages/MessagesEn.php file is intact.' );
-               }
-
-               # Set the preload key
-               $allData['preload'] = $this->buildPreload( $allData );
-
-               # Save to the process cache and register the items loaded
-               $this->data[$code] = $allData;
-               foreach ( $allData as $key => $item ) {
-                       $this->loadedItems[$code][$key] = true;
-               }
-
-               # Save to the persistent cache
-               $this->store->startWrite( $code );
-               foreach ( $allData as $key => $value ) {
-                       if ( in_array( $key, self::$splitKeys ) ) {
-                               foreach ( $value as $subkey => $subvalue ) {
-                                       $this->store->set( "$key:$subkey", $subvalue );
-                               }
-                       } else {
-                               $this->store->set( $key, $value );
-                       }
-               }
-               $this->store->finishWrite();
-
-               # Clear out the MessageBlobStore
-               # HACK: If using a null (i.e. disabled) storage backend, we
-               # can't write to the MessageBlobStore either
-               if ( $purgeBlobs && !$this->store instanceof LCStoreNull ) {
-                       $blobStore = new MessageBlobStore();
-                       $blobStore->clear();
-               }
-
-       }
-
-       /**
-        * Build the preload item from the given pre-cache data.
-        *
-        * The preload item will be loaded automatically, improving performance
-        * for the commonly-requested items it contains.
-        * @param array $data
-        * @return array
-        */
-       protected function buildPreload( $data ) {
-               $preload = [ 'messages' => [] ];
-               foreach ( self::$preloadedKeys as $key ) {
-                       $preload[$key] = $data[$key];
-               }
-
-               foreach ( $data['preloadedMessages'] as $subkey ) {
-                       if ( isset( $data['messages'][$subkey] ) ) {
-                               $subitem = $data['messages'][$subkey];
-                       } else {
-                               $subitem = null;
-                       }
-                       $preload['messages'][$subkey] = $subitem;
-               }
-
-               return $preload;
-       }
-
-       /**
-        * Unload the data for a given language from the object cache.
-        * Reduces memory usage.
-        * @param string $code
-        */
-       public function unload( $code ) {
-               unset( $this->data[$code] );
-               unset( $this->loadedItems[$code] );
-               unset( $this->loadedSubitems[$code] );
-               unset( $this->initialisedLangs[$code] );
-               unset( $this->shallowFallbacks[$code] );
-
-               foreach ( $this->shallowFallbacks as $shallowCode => $fbCode ) {
-                       if ( $fbCode === $code ) {
-                               $this->unload( $shallowCode );
-                       }
-               }
-       }
-
-       /**
-        * Unload all data
-        */
-       public function unloadAll() {
-               foreach ( $this->initialisedLangs as $lang => $unused ) {
-                       $this->unload( $lang );
-               }
-       }
-
-       /**
-        * Disable the storage backend
-        */
-       public function disableBackend() {
-               $this->store = new LCStoreNull;
-               $this->manualRecache = false;
-       }
-}
-
-/**
- * Interface for the persistence layer of LocalisationCache.
- *
- * The persistence layer is two-level hierarchical cache. The first level
- * is the language, the second level is the item or subitem.
- *
- * Since the data for a whole language is rebuilt in one operation, it needs
- * to have a fast and atomic method for deleting or replacing all of the
- * current data for a given language. The interface reflects this bulk update
- * operation. Callers writing to the cache must first call startWrite(), then
- * will call set() a couple of thousand times, then will call finishWrite()
- * to commit the operation. When finishWrite() is called, the cache is
- * expected to delete all data previously stored for that language.
- *
- * The values stored are PHP variables suitable for serialize(). Implementations
- * of LCStore are responsible for serializing and unserializing.
- */
-interface LCStore {
-       /**
-        * Get a value.
-        * @param string $code Language code
-        * @param string $key Cache key
-        */
-       function get( $code, $key );
-
-       /**
-        * Start a write transaction.
-        * @param string $code Language code
-        */
-       function startWrite( $code );
-
-       /**
-        * Finish a write transaction.
-        */
-       function finishWrite();
-
-       /**
-        * Set a key to a given value. startWrite() must be called before this
-        * is called, and finishWrite() must be called afterwards.
-        * @param string $key
-        * @param mixed $value
-        */
-       function set( $key, $value );
-}
-
-/**
- * LCStore implementation which uses the standard DB functions to store data.
- * This will work on any MediaWiki installation.
- */
-class LCStoreDB implements LCStore {
-       /** @var string */
-       private $currentLang;
-       /** @var bool */
-       private $writesDone = false;
-       /** @var IDatabase */
-       private $dbw;
-       /** @var array */
-       private $batch = [];
-       /** @var bool */
-       private $readOnly = false;
-
-       public function get( $code, $key ) {
-               if ( $this->writesDone && $this->dbw ) {
-                       $db = $this->dbw; // see the changes in finishWrite()
-               } else {
-                       $db = wfGetDB( DB_SLAVE );
-               }
-
-               $value = $db->selectField(
-                       'l10n_cache',
-                       'lc_value',
-                       [ 'lc_lang' => $code, 'lc_key' => $key ],
-                       __METHOD__
-               );
-
-               return ( $value !== false ) ? unserialize( $db->decodeBlob( $value ) ) : null;
-       }
-
-       public function startWrite( $code ) {
-               if ( $this->readOnly ) {
-                       return;
-               } elseif ( !$code ) {
-                       throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
-               }
-
-               $this->dbw = wfGetDB( DB_MASTER );
-               $this->readOnly = $this->dbw->isReadOnly();
-
-               $this->currentLang = $code;
-               $this->batch = [];
-       }
-
-       public function finishWrite() {
-               if ( $this->readOnly ) {
-                       return;
-               } elseif ( is_null( $this->currentLang ) ) {
-                       throw new MWException( __CLASS__ . ': must call startWrite() before finishWrite()' );
-               }
-
-               $this->dbw->startAtomic( __METHOD__ );
-               try {
-                       $this->dbw->delete(
-                               'l10n_cache',
-                               [ 'lc_lang' => $this->currentLang ],
-                               __METHOD__
-                       );
-                       foreach ( array_chunk( $this->batch, 500 ) as $rows ) {
-                               $this->dbw->insert( 'l10n_cache', $rows, __METHOD__ );
-                       }
-                       $this->writesDone = true;
-               } catch ( DBQueryError $e ) {
-                       if ( $this->dbw->wasReadOnlyError() ) {
-                               $this->readOnly = true; // just avoid site down time
-                       } else {
-                               throw $e;
-                       }
-               }
-               $this->dbw->endAtomic( __METHOD__ );
-
-               $this->currentLang = null;
-               $this->batch = [];
-       }
-
-       public function set( $key, $value ) {
-               if ( $this->readOnly ) {
-                       return;
-               } elseif ( is_null( $this->currentLang ) ) {
-                       throw new MWException( __CLASS__ . ': must call startWrite() before set()' );
-               }
-
-               $this->batch[] = [
-                       'lc_lang' => $this->currentLang,
-                       'lc_key' => $key,
-                       'lc_value' => $this->dbw->encodeBlob( serialize( $value ) )
-               ];
-       }
-}
-
-/**
- * LCStore implementation which stores data as a collection of CDB files in the
- * directory given by $wgCacheDirectory. If $wgCacheDirectory is not set, this
- * will throw an exception.
- *
- * Profiling indicates that on Linux, this implementation outperforms MySQL if
- * the directory is on a local filesystem and there is ample kernel cache
- * space. The performance advantage is greater when the DBA extension is
- * available than it is with the PHP port.
- *
- * See Cdb.php and http://cr.yp.to/cdb.html
- */
-class LCStoreCDB implements LCStore {
-       /** @var CdbReader[] */
-       private $readers;
-
-       /** @var CdbWriter */
-       private $writer;
-
-       /** @var string Current language code */
-       private $currentLang;
-
-       /** @var bool|string Cache directory. False if not set */
-       private $directory;
-
-       function __construct( $conf = [] ) {
-               global $wgCacheDirectory;
-
-               if ( isset( $conf['directory'] ) ) {
-                       $this->directory = $conf['directory'];
-               } else {
-                       $this->directory = $wgCacheDirectory;
-               }
-       }
-
-       public function get( $code, $key ) {
-               if ( !isset( $this->readers[$code] ) ) {
-                       $fileName = $this->getFileName( $code );
-
-                       $this->readers[$code] = false;
-                       if ( file_exists( $fileName ) ) {
-                               try {
-                                       $this->readers[$code] = CdbReader::open( $fileName );
-                               } catch ( CdbException $e ) {
-                                       wfDebug( __METHOD__ . ": unable to open cdb file for reading\n" );
-                               }
-                       }
-               }
-
-               if ( !$this->readers[$code] ) {
-                       return null;
-               } else {
-                       $value = false;
-                       try {
-                               $value = $this->readers[$code]->get( $key );
-                       } catch ( CdbException $e ) {
-                               wfDebug( __METHOD__ . ": CdbException caught, error message was "
-                                       . $e->getMessage() . "\n" );
-                       }
-                       if ( $value === false ) {
-                               return null;
-                       }
-
-                       return unserialize( $value );
-               }
-       }
-
-       public function startWrite( $code ) {
-               if ( !file_exists( $this->directory ) ) {
-                       if ( !wfMkdirParents( $this->directory, null, __METHOD__ ) ) {
-                               throw new MWException( "Unable to create the localisation store " .
-                                       "directory \"{$this->directory}\"" );
-                       }
-               }
-
-               // Close reader to stop permission errors on write
-               if ( !empty( $this->readers[$code] ) ) {
-                       $this->readers[$code]->close();
-               }
-
-               try {
-                       $this->writer = CdbWriter::open( $this->getFileName( $code ) );
-               } catch ( CdbException $e ) {
-                       throw new MWException( $e->getMessage() );
-               }
-               $this->currentLang = $code;
-       }
-
-       public function finishWrite() {
-               // Close the writer
-               try {
-                       $this->writer->close();
-               } catch ( CdbException $e ) {
-                       throw new MWException( $e->getMessage() );
-               }
-               $this->writer = null;
-               unset( $this->readers[$this->currentLang] );
-               $this->currentLang = null;
-       }
-
-       public function set( $key, $value ) {
-               if ( is_null( $this->writer ) ) {
-                       throw new MWException( __CLASS__ . ': must call startWrite() before calling set()' );
-               }
-               try {
-                       $this->writer->set( $key, serialize( $value ) );
-               } catch ( CdbException $e ) {
-                       throw new MWException( $e->getMessage() );
-               }
-       }
-
-       protected function getFileName( $code ) {
-               if ( strval( $code ) === '' || strpos( $code, '/' ) !== false ) {
-                       throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
-               }
-
-               return "{$this->directory}/l10n_cache-$code.cdb";
-       }
-}
-
-/**
- * Null store backend, used to avoid DB errors during install
- */
-class LCStoreNull implements LCStore {
-       public function get( $code, $key ) {
-               return null;
-       }
-
-       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 LocalisationCacheBulkLoad extends LocalisationCache {
-       /**
-        * A cache of the contents of data files.
-        * Core files are serialized to avoid using ~1GB of RAM during a recache.
-        */
-       private $fileCache = [];
-
-       /**
-        * 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.
-        */
-       private $mruLangs = [];
-
-       /**
-        * Maximum number of languages that may be loaded into $this->data
-        */
-       private $maxLoadedLangs = 10;
-
-       /**
-        * @param string $fileName
-        * @param string $fileType
-        * @return array|mixed
-        */
-       protected function readPHPFile( $fileName, $fileType ) {
-               $serialize = $fileType === 'core';
-               if ( !isset( $this->fileCache[$fileName][$fileType] ) ) {
-                       $data = parent::readPHPFile( $fileName, $fileType );
-
-                       if ( $serialize ) {
-                               $encData = serialize( $data );
-                       } else {
-                               $encData = $data;
-                       }
-
-                       $this->fileCache[$fileName][$fileType] = $encData;
-
-                       return $data;
-               } elseif ( $serialize ) {
-                       return unserialize( $this->fileCache[$fileName][$fileType] );
-               } else {
-                       return $this->fileCache[$fileName][$fileType];
-               }
-       }
-
-       /**
-        * @param string $code
-        * @param string $key
-        * @return mixed
-        */
-       public function getItem( $code, $key ) {
-               unset( $this->mruLangs[$code] );
-               $this->mruLangs[$code] = true;
-
-               return parent::getItem( $code, $key );
-       }
-
-       /**
-        * @param string $code
-        * @param string $key
-        * @param string $subkey
-        * @return mixed
-        */
-       public function getSubitem( $code, $key, $subkey ) {
-               unset( $this->mruLangs[$code] );
-               $this->mruLangs[$code] = true;
-
-               return parent::getSubitem( $code, $key, $subkey );
-       }
-
-       /**
-        * @param string $code
-        */
-       public function recache( $code ) {
-               parent::recache( $code );
-               unset( $this->mruLangs[$code] );
-               $this->mruLangs[$code] = true;
-               $this->trimCache();
-       }
-
-       /**
-        * @param string $code
-        */
-       public function unload( $code ) {
-               unset( $this->mruLangs[$code] );
-               parent::unload( $code );
-       }
-
-       /**
-        * Unload cached languages until there are less than $this->maxLoadedLangs
-        */
-       protected function trimCache() {
-               while ( count( $this->data ) > $this->maxLoadedLangs && count( $this->mruLangs ) ) {
-                       reset( $this->mruLangs );
-                       $code = key( $this->mruLangs );
-                       wfDebug( __METHOD__ . ": unloading $code\n" );
-                       $this->unload( $code );
-               }
-       }
-}
diff --git a/includes/cache/localisation/LCStore.php b/includes/cache/localisation/LCStore.php
new file mode 100644 (file)
index 0000000..cb1e261
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Interface for the persistence layer of LocalisationCache.
+ *
+ * The persistence layer is two-level hierarchical cache. The first level
+ * is the language, the second level is the item or subitem.
+ *
+ * Since the data for a whole language is rebuilt in one operation, it needs
+ * to have a fast and atomic method for deleting or replacing all of the
+ * current data for a given language. The interface reflects this bulk update
+ * operation. Callers writing to the cache must first call startWrite(), then
+ * will call set() a couple of thousand times, then will call finishWrite()
+ * to commit the operation. When finishWrite() is called, the cache is
+ * expected to delete all data previously stored for that language.
+ *
+ * The values stored are PHP variables suitable for serialize(). Implementations
+ * of LCStore are responsible for serializing and unserializing.
+ */
+interface LCStore {
+
+       /**
+        * Get a value.
+        * @param string $code Language code
+        * @param string $key Cache key
+        */
+       function get( $code, $key );
+
+       /**
+        * Start a write transaction.
+        * @param string $code Language code
+        */
+       function startWrite( $code );
+
+       /**
+        * Finish a write transaction.
+        */
+       function finishWrite();
+
+       /**
+        * Set a key to a given value. startWrite() must be called before this
+        * is called, and finishWrite() must be called afterwards.
+        * @param string $key
+        * @param mixed $value
+        */
+       function set( $key, $value );
+
+}
diff --git a/includes/cache/localisation/LCStoreCDB.php b/includes/cache/localisation/LCStoreCDB.php
new file mode 100644 (file)
index 0000000..2c3f58f
--- /dev/null
@@ -0,0 +1,144 @@
+<?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
+ */
+use Cdb\Exception;
+use Cdb\Reader;
+use Cdb\Writer;
+
+/**
+ * LCStore implementation which stores data as a collection of CDB files in the
+ * directory given by $wgCacheDirectory. If $wgCacheDirectory is not set, this
+ * will throw an exception.
+ *
+ * Profiling indicates that on Linux, this implementation outperforms MySQL if
+ * the directory is on a local filesystem and there is ample kernel cache
+ * space. The performance advantage is greater when the DBA extension is
+ * available than it is with the PHP port.
+ *
+ * See Cdb.php and http://cr.yp.to/cdb.html
+ */
+class LCStoreCDB implements LCStore {
+
+       /** @var Reader[] */
+       private $readers;
+
+       /** @var Writer */
+       private $writer;
+
+       /** @var string Current language code */
+       private $currentLang;
+
+       /** @var bool|string Cache directory. False if not set */
+       private $directory;
+
+       function __construct( $conf = [] ) {
+               global $wgCacheDirectory;
+
+               if ( isset( $conf['directory'] ) ) {
+                       $this->directory = $conf['directory'];
+               } else {
+                       $this->directory = $wgCacheDirectory;
+               }
+       }
+
+       public function get( $code, $key ) {
+               if ( !isset( $this->readers[$code] ) ) {
+                       $fileName = $this->getFileName( $code );
+
+                       $this->readers[$code] = false;
+                       if ( file_exists( $fileName ) ) {
+                               try {
+                                       $this->readers[$code] = Reader::open( $fileName );
+                               } catch ( Exception $e ) {
+                                       wfDebug( __METHOD__ . ": unable to open cdb file for reading\n" );
+                               }
+                       }
+               }
+
+               if ( !$this->readers[$code] ) {
+                       return null;
+               } else {
+                       $value = false;
+                       try {
+                               $value = $this->readers[$code]->get( $key );
+                       } catch ( Exception $e ) {
+                               wfDebug( __METHOD__ . ": \Cdb\Exception caught, error message was "
+                                       . $e->getMessage() . "\n" );
+                       }
+                       if ( $value === false ) {
+                               return null;
+                       }
+
+                       return unserialize( $value );
+               }
+       }
+
+       public function startWrite( $code ) {
+               if ( !file_exists( $this->directory ) ) {
+                       if ( !wfMkdirParents( $this->directory, null, __METHOD__ ) ) {
+                               throw new MWException( "Unable to create the localisation store " .
+                                       "directory \"{$this->directory}\"" );
+                       }
+               }
+
+               // Close reader to stop permission errors on write
+               if ( !empty( $this->readers[$code] ) ) {
+                       $this->readers[$code]->close();
+               }
+
+               try {
+                       $this->writer = Writer::open( $this->getFileName( $code ) );
+               } catch ( Exception $e ) {
+                       throw new MWException( $e->getMessage() );
+               }
+               $this->currentLang = $code;
+       }
+
+       public function finishWrite() {
+               // Close the writer
+               try {
+                       $this->writer->close();
+               } catch ( Exception $e ) {
+                       throw new MWException( $e->getMessage() );
+               }
+               $this->writer = null;
+               unset( $this->readers[$this->currentLang] );
+               $this->currentLang = null;
+       }
+
+       public function set( $key, $value ) {
+               if ( is_null( $this->writer ) ) {
+                       throw new MWException( __CLASS__ . ': must call startWrite() before calling set()' );
+               }
+               try {
+                       $this->writer->set( $key, serialize( $value ) );
+               } catch ( Exception $e ) {
+                       throw new MWException( $e->getMessage() );
+               }
+       }
+
+       protected function getFileName( $code ) {
+               if ( strval( $code ) === '' || strpos( $code, '/' ) !== false ) {
+                       throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
+               }
+
+               return "{$this->directory}/l10n_cache-$code.cdb";
+       }
+
+}
diff --git a/includes/cache/localisation/LCStoreDB.php b/includes/cache/localisation/LCStoreDB.php
new file mode 100644 (file)
index 0000000..c350178
--- /dev/null
@@ -0,0 +1,114 @@
+<?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
+ */
+
+/**
+ * LCStore implementation which uses the standard DB functions to store data.
+ * This will work on any MediaWiki installation.
+ */
+class LCStoreDB implements LCStore {
+
+       /** @var string */
+       private $currentLang;
+       /** @var bool */
+       private $writesDone = false;
+       /** @var IDatabase */
+       private $dbw;
+       /** @var array */
+       private $batch = [];
+       /** @var bool */
+       private $readOnly = false;
+
+       public function get( $code, $key ) {
+               if ( $this->writesDone && $this->dbw ) {
+                       $db = $this->dbw; // see the changes in finishWrite()
+               } else {
+                       $db = wfGetDB( DB_SLAVE );
+               }
+
+               $value = $db->selectField(
+                       'l10n_cache',
+                       'lc_value',
+                       [ 'lc_lang' => $code, 'lc_key' => $key ],
+                       __METHOD__
+               );
+
+               return ( $value !== false ) ? unserialize( $db->decodeBlob( $value ) ) : null;
+       }
+
+       public function startWrite( $code ) {
+               if ( $this->readOnly ) {
+                       return;
+               } elseif ( !$code ) {
+                       throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
+               }
+
+               $this->dbw = wfGetDB( DB_MASTER );
+               $this->readOnly = $this->dbw->isReadOnly();
+
+               $this->currentLang = $code;
+               $this->batch = [];
+       }
+
+       public function finishWrite() {
+               if ( $this->readOnly ) {
+                       return;
+               } elseif ( is_null( $this->currentLang ) ) {
+                       throw new MWException( __CLASS__ . ': must call startWrite() before finishWrite()' );
+               }
+
+               $this->dbw->startAtomic( __METHOD__ );
+               try {
+                       $this->dbw->delete(
+                               'l10n_cache',
+                               [ 'lc_lang' => $this->currentLang ],
+                               __METHOD__
+                       );
+                       foreach ( array_chunk( $this->batch, 500 ) as $rows ) {
+                               $this->dbw->insert( 'l10n_cache', $rows, __METHOD__ );
+                       }
+                       $this->writesDone = true;
+               } catch ( DBQueryError $e ) {
+                       if ( $this->dbw->wasReadOnlyError() ) {
+                               $this->readOnly = true; // just avoid site down time
+                       } else {
+                               throw $e;
+                       }
+               }
+               $this->dbw->endAtomic( __METHOD__ );
+
+               $this->currentLang = null;
+               $this->batch = [];
+       }
+
+       public function set( $key, $value ) {
+               if ( $this->readOnly ) {
+                       return;
+               } elseif ( is_null( $this->currentLang ) ) {
+                       throw new MWException( __CLASS__ . ': must call startWrite() before set()' );
+               }
+
+               $this->batch[] = [
+                       'lc_lang' => $this->currentLang,
+                       'lc_key' => $key,
+                       'lc_value' => $this->dbw->encodeBlob( serialize( $value ) )
+               ];
+       }
+
+}
diff --git a/includes/cache/localisation/LCStoreNull.php b/includes/cache/localisation/LCStoreNull.php
new file mode 100644 (file)
index 0000000..62f88eb
--- /dev/null
@@ -0,0 +1,39 @@
+<?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
+ */
+
+/**
+ * Null store backend, used to avoid DB errors during install
+ */
+class LCStoreNull implements LCStore {
+
+       public function get( $code, $key ) {
+               return null;
+       }
+
+       public function startWrite( $code ) {
+       }
+
+       public function finishWrite() {
+       }
+
+       public function set( $key, $value ) {
+       }
+
+}
diff --git a/includes/cache/localisation/LCStoreStaticArray.php b/includes/cache/localisation/LCStoreStaticArray.php
new file mode 100644 (file)
index 0000000..1e20082
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+/**
+ *  Localisation cache storage based on PHP files and static arrays.
+ *
+ * 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
+ */
+
+/**
+ * @since 1.26
+ */
+class LCStoreStaticArray implements LCStore {
+       /** @var string|null Current language code. */
+       private $currentLang = null;
+
+       /** @var array Localisation data. */
+       private $data = [];
+
+       /** @var string File name. */
+       private $fname = null;
+
+       /** @var string Directory for cache files. */
+       private $directory;
+
+       public function __construct( $conf = [] ) {
+               global $wgCacheDirectory;
+
+               if ( isset( $conf['directory'] ) ) {
+                       $this->directory = $conf['directory'];
+               } else {
+                       $this->directory = $wgCacheDirectory;
+               }
+       }
+
+       public function startWrite( $code ) {
+               $this->currentLang = $code;
+               $this->fname = $this->directory . '/' . $code . '.l10n.php';
+               $this->data[$code] = [];
+               if ( file_exists( $this->fname ) ) {
+                       $this->data[$code] = require $this->fname;
+               }
+       }
+
+       public function set( $key, $value ) {
+               $this->data[$this->currentLang][$key] = self::encode( $value );
+       }
+
+       /**
+        * Encodes a value into an array format
+        *
+        * @param mixed $value
+        * @return array
+        * @throws RuntimeException
+        */
+       public static function encode( $value ) {
+               if ( is_scalar( $value ) || $value === null ) {
+                       // [V]alue
+                       return [ 'v', $value ];
+               }
+               if ( is_object( $value ) ) {
+                       // [S]erialized
+                       return [ 's', serialize( $value ) ];
+               }
+               if ( is_array( $value ) ) {
+                       // [A]rray
+                       return [ 'a', array_map( function ( $v ) {
+                               return LCStoreStaticArray::encode( $v );
+                       }, $value ) ];
+               }
+
+               throw new RuntimeException( 'Cannot encode ' . var_export( $value, true ) );
+       }
+
+       /**
+        * Decode something that was encoded with encode
+        *
+        * @param array $encoded
+        * @return array|mixed
+        * @throws RuntimeException
+        */
+       public static function decode( array $encoded ) {
+               $type = $encoded[0];
+               $data = $encoded[1];
+
+               switch ( $type ) {
+               case 'v':
+                       return $data;
+               case 's':
+                       return unserialize( $data );
+               case 'a':
+                       return array_map( function ( $v ) {
+                               return LCStoreStaticArray::decode( $v );
+                       }, $data );
+               default:
+                       throw new RuntimeException(
+                               'Unable to decode ' . var_export( $encoded, true ) );
+               }
+       }
+
+       public function finishWrite() {
+               file_put_contents(
+                       $this->fname,
+                       "<?php\n" .
+                       "// Generated by LCStoreStaticArray.php -- do not edit!\n" .
+                       "return " .
+                       var_export( $this->data[$this->currentLang], true ) . ';'
+               );
+               $this->currentLang = null;
+               $this->fname = null;
+       }
+
+       public function get( $code, $key ) {
+               if ( !array_key_exists( $code, $this->data ) ) {
+                       $fname = $this->directory . '/' . $code . '.l10n.php';
+                       if ( !file_exists( $fname ) ) {
+                               return null;
+                       }
+                       $this->data[$code] = require $fname;
+               }
+               $data = $this->data[$code];
+               if ( array_key_exists( $key, $data ) ) {
+                       return self::decode( $data[$key] );
+               }
+               return null;
+       }
+}
diff --git a/includes/cache/localisation/LocalisationCache.php b/includes/cache/localisation/LocalisationCache.php
new file mode 100644 (file)
index 0000000..dd7d81a
--- /dev/null
@@ -0,0 +1,1098 @@
+<?php
+/**
+ * Cache of the contents of localisation files.
+ *
+ * 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
+ */
+
+use Cdb\Reader as CdbReader;
+use Cdb\Writer as CdbWriter;
+use CLDRPluralRuleParser\Evaluator;
+
+/**
+ * Class for caching the contents of localisation files, Messages*.php
+ * and *.i18n.php.
+ *
+ * An instance of this class is available using Language::getLocalisationCache().
+ *
+ * The values retrieved from here are merged, containing items from extension
+ * files, core messages files and the language fallback sequence (e.g. zh-cn ->
+ * zh-hans -> en ). Some common errors are corrected, for example namespace
+ * names with spaces instead of underscores, but heavyweight processing, such
+ * as grammatical transformation, is done by the caller.
+ */
+class LocalisationCache {
+       const VERSION = 4;
+
+       /** Configuration associative array */
+       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.
+        */
+       private $manualRecache = false;
+
+       /**
+        * True to treat all files as expired until they are regenerated by this object.
+        */
+       private $forceRecache = false;
+
+       /**
+        * The cache data. 3-d array, where the first key is the language code,
+        * the second key is the item key e.g. 'messages', and the third key is
+        * an item specific subkey index. Some items are not arrays and so for those
+        * items, there are no subkeys.
+        */
+       protected $data = [];
+
+       /**
+        * The persistent store object. An instance of LCStore.
+        *
+        * @var LCStore
+        */
+       private $store;
+
+       /**
+        * A 2-d associative array, code/key, where presence indicates that the item
+        * is loaded. Value arbitrary.
+        *
+        * For split items, if set, this indicates that all of the subitems have been
+        * loaded.
+        */
+       private $loadedItems = [];
+
+       /**
+        * 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.
+        */
+       private $loadedSubitems = [];
+
+       /**
+        * 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.
+        */
+       private $initialisedLangs = [];
+
+       /**
+        * 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.
+        */
+       private $shallowFallbacks = [];
+
+       /**
+        * An array where the keys are codes that have been recached by this instance.
+        */
+       private $recachedLangs = [];
+
+       /**
+        * All item keys
+        */
+       static public $allKeys = [
+               'fallback', 'namespaceNames', 'bookstoreList',
+               'magicWords', 'messages', 'rtl', 'capitalizeAllNouns', 'digitTransformTable',
+               'separatorTransformTable', 'fallback8bitEncoding', 'linkPrefixExtension',
+               'linkTrail', 'linkPrefixCharset', 'namespaceAliases',
+               'dateFormats', 'datePreferences', 'datePreferenceMigrationMap',
+               'defaultDateFormat', 'extraUserToggles', 'specialPageAliases',
+               'imageFiles', 'preloadedMessages', 'namespaceGenderAliases',
+               'digitGroupingPattern', 'pluralRules', 'pluralRuleTypes', 'compiledPluralRules',
+       ];
+
+       /**
+        * Keys for items which consist of associative arrays, which may be merged
+        * by a fallback sequence.
+        */
+       static public $mergeableMapKeys = [ 'messages', 'namespaceNames',
+               'namespaceAliases', 'dateFormats', 'imageFiles', 'preloadedMessages'
+       ];
+
+       /**
+        * Keys for items which are a numbered array.
+        */
+       static public $mergeableListKeys = [ 'extraUserToggles' ];
+
+       /**
+        * Keys for items which contain an array of arrays of equivalent aliases
+        * for each subitem. The aliases may be merged by a fallback sequence.
+        */
+       static public $mergeableAliasListKeys = [ 'specialPageAliases' ];
+
+       /**
+        * Keys for items which contain an associative array, and may be merged if
+        * the primary value contains the special array key "inherit". That array
+        * key is removed after the first merge.
+        */
+       static public $optionalMergeKeys = [ 'bookstoreList' ];
+
+       /**
+        * Keys for items that are formatted like $magicWords
+        */
+       static public $magicWordKeys = [ 'magicWords' ];
+
+       /**
+        * Keys for items where the subitems are stored in the backend separately.
+        */
+       static public $splitKeys = [ 'messages' ];
+
+       /**
+        * Keys which are loaded automatically by initLanguage()
+        */
+       static public $preloadedKeys = [ 'dateFormats', 'namespaceNames' ];
+
+       /**
+        * Associative array of cached plural rules. The key is the language code,
+        * the value is an array of plural rules for that language.
+        */
+       private $pluralRules = null;
+
+       /**
+        * Associative array of cached plural rule types. The key is the language
+        * code, the value is an array of plural rule types for that language. For
+        * example, $pluralRuleTypes['ar'] = ['zero', 'one', 'two', 'few', 'many'].
+        * The index for each rule type matches the index for the rule in
+        * $pluralRules, thus allowing correlation between the two. The reason we
+        * don't just use the type names as the keys in $pluralRules is because
+        * Language::convertPlural applies the rules based on numeric order (or
+        * explicit numeric parameter), not based on the name of the rule type. For
+        * example, {{plural:count|wordform1|wordform2|wordform3}}, rather than
+        * {{plural:count|one=wordform1|two=wordform2|many=wordform3}}.
+        */
+       private $pluralRuleTypes = null;
+
+       private $mergeableKeys = null;
+
+       /**
+        * Constructor.
+        * For constructor parameters, see the documentation in DefaultSettings.php
+        * for $wgLocalisationCacheConf.
+        *
+        * @param array $conf
+        * @throws MWException
+        */
+       function __construct( $conf ) {
+               global $wgCacheDirectory;
+
+               $this->conf = $conf;
+               $storeConf = [];
+               if ( !empty( $conf['storeClass'] ) ) {
+                       $storeClass = $conf['storeClass'];
+               } else {
+                       switch ( $conf['store'] ) {
+                               case 'files':
+                               case 'file':
+                                       $storeClass = 'LCStoreCDB';
+                                       break;
+                               case 'db':
+                                       $storeClass = 'LCStoreDB';
+                                       break;
+                               case 'array':
+                                       $storeClass = 'LCStoreStaticArray';
+                                       break;
+                               case 'detect':
+                                       if ( !empty( $conf['storeDirectory'] ) ) {
+                                               $storeClass = 'LCStoreCDB';
+                                       } else {
+                                               $cacheDir = $wgCacheDirectory ?: wfTempDir();
+                                               if ( $cacheDir ) {
+                                                       $storeConf['directory'] = $cacheDir;
+                                                       $storeClass = 'LCStoreCDB';
+                                               } else {
+                                                       $storeClass = 'LCStoreDB';
+                                               }
+                                       }
+                                       break;
+                               default:
+                                       throw new MWException(
+                                               'Please set $wgLocalisationCacheConf[\'store\'] to something sensible.' );
+                       }
+               }
+
+               wfDebugLog( 'caches', get_class( $this ) . ": using store $storeClass" );
+               if ( !empty( $conf['storeDirectory'] ) ) {
+                       $storeConf['directory'] = $conf['storeDirectory'];
+               }
+
+               $this->store = new $storeClass( $storeConf );
+               foreach ( [ 'manualRecache', 'forceRecache' ] as $var ) {
+                       if ( isset( $conf[$var] ) ) {
+                               $this->$var = $conf[$var];
+                       }
+               }
+       }
+
+       /**
+        * Returns true if the given key is mergeable, that is, if it is an associative
+        * array which can be merged through a fallback sequence.
+        * @param string $key
+        * @return bool
+        */
+       public function isMergeableKey( $key ) {
+               if ( $this->mergeableKeys === null ) {
+                       $this->mergeableKeys = array_flip( array_merge(
+                               self::$mergeableMapKeys,
+                               self::$mergeableListKeys,
+                               self::$mergeableAliasListKeys,
+                               self::$optionalMergeKeys,
+                               self::$magicWordKeys
+                       ) );
+               }
+
+               return isset( $this->mergeableKeys[$key] );
+       }
+
+       /**
+        * Get a cache item.
+        *
+        * Warning: this may be slow for split items (messages), since it will
+        * need to fetch all of the subitems from the cache individually.
+        * @param string $code
+        * @param string $key
+        * @return mixed
+        */
+       public function getItem( $code, $key ) {
+               if ( !isset( $this->loadedItems[$code][$key] ) ) {
+                       $this->loadItem( $code, $key );
+               }
+
+               if ( $key === 'fallback' && isset( $this->shallowFallbacks[$code] ) ) {
+                       return $this->shallowFallbacks[$code];
+               }
+
+               return $this->data[$code][$key];
+       }
+
+       /**
+        * Get a subitem, for instance a single message for a given language.
+        * @param string $code
+        * @param string $key
+        * @param string $subkey
+        * @return mixed|null
+        */
+       public function getSubitem( $code, $key, $subkey ) {
+               if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) &&
+                       !isset( $this->loadedItems[$code][$key] )
+               ) {
+                       $this->loadSubitem( $code, $key, $subkey );
+               }
+
+               if ( isset( $this->data[$code][$key][$subkey] ) ) {
+                       return $this->data[$code][$key][$subkey];
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Get the list of subitem keys for a given item.
+        *
+        * This is faster than array_keys($lc->getItem(...)) for the items listed in
+        * self::$splitKeys.
+        *
+        * Will return null if the item is not found, or false if the item is not an
+        * array.
+        * @param string $code
+        * @param string $key
+        * @return bool|null|string
+        */
+       public function getSubitemList( $code, $key ) {
+               if ( in_array( $key, self::$splitKeys ) ) {
+                       return $this->getSubitem( $code, 'list', $key );
+               } else {
+                       $item = $this->getItem( $code, $key );
+                       if ( is_array( $item ) ) {
+                               return array_keys( $item );
+                       } else {
+                               return false;
+                       }
+               }
+       }
+
+       /**
+        * Load an item into the cache.
+        * @param string $code
+        * @param string $key
+        */
+       protected function loadItem( $code, $key ) {
+               if ( !isset( $this->initialisedLangs[$code] ) ) {
+                       $this->initLanguage( $code );
+               }
+
+               // Check to see if initLanguage() loaded it for us
+               if ( isset( $this->loadedItems[$code][$key] ) ) {
+                       return;
+               }
+
+               if ( isset( $this->shallowFallbacks[$code] ) ) {
+                       $this->loadItem( $this->shallowFallbacks[$code], $key );
+
+                       return;
+               }
+
+               if ( in_array( $key, self::$splitKeys ) ) {
+                       $subkeyList = $this->getSubitem( $code, 'list', $key );
+                       foreach ( $subkeyList as $subkey ) {
+                               if ( isset( $this->data[$code][$key][$subkey] ) ) {
+                                       continue;
+                               }
+                               $this->data[$code][$key][$subkey] = $this->getSubitem( $code, $key, $subkey );
+                       }
+               } else {
+                       $this->data[$code][$key] = $this->store->get( $code, $key );
+               }
+
+               $this->loadedItems[$code][$key] = true;
+       }
+
+       /**
+        * Load a subitem into the cache
+        * @param string $code
+        * @param string $key
+        * @param string $subkey
+        */
+       protected function loadSubitem( $code, $key, $subkey ) {
+               if ( !in_array( $key, self::$splitKeys ) ) {
+                       $this->loadItem( $code, $key );
+
+                       return;
+               }
+
+               if ( !isset( $this->initialisedLangs[$code] ) ) {
+                       $this->initLanguage( $code );
+               }
+
+               // Check to see if initLanguage() loaded it for us
+               if ( isset( $this->loadedItems[$code][$key] ) ||
+                       isset( $this->loadedSubitems[$code][$key][$subkey] )
+               ) {
+                       return;
+               }
+
+               if ( isset( $this->shallowFallbacks[$code] ) ) {
+                       $this->loadSubitem( $this->shallowFallbacks[$code], $key, $subkey );
+
+                       return;
+               }
+
+               $value = $this->store->get( $code, "$key:$subkey" );
+               $this->data[$code][$key][$subkey] = $value;
+               $this->loadedSubitems[$code][$key][$subkey] = true;
+       }
+
+       /**
+        * Returns true if the cache identified by $code is missing or expired.
+        *
+        * @param string $code
+        *
+        * @return bool
+        */
+       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 for some stores
+               if ( $deps === null || $keys === null || $preload === null ) {
+                       wfDebug( __METHOD__ . "($code): cache missing, need to make one\n" );
+
+                       return true;
+               }
+
+               foreach ( $deps as $dep ) {
+                       // Because we're unserializing stuff from cache, we
+                       // could receive objects of classes that don't exist
+                       // anymore (e.g. uninstalled extensions)
+                       // When this happens, always expire the cache
+                       if ( !$dep instanceof CacheDependency || $dep->isExpired() ) {
+                               wfDebug( __METHOD__ . "($code): cache for $code expired due to " .
+                                       get_class( $dep ) . "\n" );
+
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Initialise a language in this object. Rebuild the cache if necessary.
+        * @param string $code
+        * @throws MWException
+        */
+       protected function initLanguage( $code ) {
+               if ( isset( $this->initialisedLangs[$code] ) ) {
+                       return;
+               }
+
+               $this->initialisedLangs[$code] = true;
+
+               # 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;
+               }
+
+               # Recache the data if necessary
+               if ( !$this->manualRecache && $this->isExpired( $code ) ) {
+                       if ( Language::isSupportedLanguage( $code ) ) {
+                               $this->recache( $code );
+                       } elseif ( $code === 'en' ) {
+                               throw new MWException( 'MessagesEn.php is missing.' );
+                       } else {
+                               $this->initShallowFallback( $code, 'en' );
+                       }
+
+                       return;
+               }
+
+               # Preload some stuff
+               $preload = $this->getItem( $code, 'preload' );
+               if ( $preload === null ) {
+                       if ( $this->manualRecache ) {
+                               // No Messages*.php file. Do shallow fallback to en.
+                               if ( $code === 'en' ) {
+                                       throw new MWException( 'No localisation cache found for English. ' .
+                                               'Please run maintenance/rebuildLocalisationCache.php.' );
+                               }
+                               $this->initShallowFallback( $code, 'en' );
+
+                               return;
+                       } else {
+                               throw new MWException( 'Invalid or missing localisation cache.' );
+                       }
+               }
+               $this->data[$code] = $preload;
+               foreach ( $preload as $key => $item ) {
+                       if ( in_array( $key, self::$splitKeys ) ) {
+                               foreach ( $item as $subkey => $subitem ) {
+                                       $this->loadedSubitems[$code][$key][$subkey] = true;
+                               }
+                       } else {
+                               $this->loadedItems[$code][$key] = true;
+                       }
+               }
+       }
+
+       /**
+        * Create a fallback from one language to another, without creating a
+        * complete persistent cache.
+        * @param string $primaryCode
+        * @param string $fallbackCode
+        */
+       public function initShallowFallback( $primaryCode, $fallbackCode ) {
+               $this->data[$primaryCode] =& $this->data[$fallbackCode];
+               $this->loadedItems[$primaryCode] =& $this->loadedItems[$fallbackCode];
+               $this->loadedSubitems[$primaryCode] =& $this->loadedSubitems[$fallbackCode];
+               $this->shallowFallbacks[$primaryCode] = $fallbackCode;
+       }
+
+       /**
+        * Read a PHP file containing localisation data.
+        * @param string $_fileName
+        * @param string $_fileType
+        * @throws MWException
+        * @return array
+        */
+       protected function readPHPFile( $_fileName, $_fileType ) {
+               // Disable APC caching
+               MediaWiki\suppressWarnings();
+               $_apcEnabled = ini_set( 'apc.cache_by_default', '0' );
+               MediaWiki\restoreWarnings();
+
+               include $_fileName;
+
+               MediaWiki\suppressWarnings();
+               ini_set( 'apc.cache_by_default', $_apcEnabled );
+               MediaWiki\restoreWarnings();
+
+               if ( $_fileType == 'core' || $_fileType == 'extension' ) {
+                       $data = compact( self::$allKeys );
+               } elseif ( $_fileType == 'aliases' ) {
+                       $data = compact( 'aliases' );
+               } else {
+                       throw new MWException( __METHOD__ . ": Invalid file type: $_fileType" );
+               }
+
+               return $data;
+       }
+
+       /**
+        * Read a JSON file containing localisation messages.
+        * @param string $fileName Name of file to read
+        * @throws MWException If there is a syntax error in the JSON file
+        * @return array Array with a 'messages' key, or empty array if the file doesn't exist
+        */
+       public function readJSONFile( $fileName ) {
+
+               if ( !is_readable( $fileName ) ) {
+                       return [];
+               }
+
+               $json = file_get_contents( $fileName );
+               if ( $json === false ) {
+                       return [];
+               }
+
+               $data = FormatJson::decode( $json, true );
+               if ( $data === null ) {
+
+                       throw new MWException( __METHOD__ . ": Invalid JSON file: $fileName" );
+               }
+
+               // Remove keys starting with '@', they're reserved for metadata and non-message data
+               foreach ( $data as $key => $unused ) {
+                       if ( $key === '' || $key[0] === '@' ) {
+                               unset( $data[$key] );
+                       }
+               }
+
+               // The JSON format only supports messages, none of the other variables, so wrap the data
+               return [ 'messages' => $data ];
+       }
+
+       /**
+        * Get the compiled plural rules for a given language from the XML files.
+        * @since 1.20
+        * @param string $code
+        * @return array|null
+        */
+       public function getCompiledPluralRules( $code ) {
+               $rules = $this->getPluralRules( $code );
+               if ( $rules === null ) {
+                       return null;
+               }
+               try {
+                       $compiledRules = Evaluator::compile( $rules );
+               } catch ( CLDRPluralRuleError $e ) {
+                       wfDebugLog( 'l10n', $e->getMessage() );
+
+                       return [];
+               }
+
+               return $compiledRules;
+       }
+
+       /**
+        * Get the plural rules for a given language from the XML files.
+        * Cached.
+        * @since 1.20
+        * @param string $code
+        * @return array|null
+        */
+       public function getPluralRules( $code ) {
+               if ( $this->pluralRules === null ) {
+                       $this->loadPluralFiles();
+               }
+               if ( !isset( $this->pluralRules[$code] ) ) {
+                       return null;
+               } else {
+                       return $this->pluralRules[$code];
+               }
+       }
+
+       /**
+        * Get the plural rule types for a given language from the XML files.
+        * Cached.
+        * @since 1.22
+        * @param string $code
+        * @return array|null
+        */
+       public function getPluralRuleTypes( $code ) {
+               if ( $this->pluralRuleTypes === null ) {
+                       $this->loadPluralFiles();
+               }
+               if ( !isset( $this->pluralRuleTypes[$code] ) ) {
+                       return null;
+               } else {
+                       return $this->pluralRuleTypes[$code];
+               }
+       }
+
+       /**
+        * Load the plural XML files.
+        */
+       protected function loadPluralFiles() {
+               global $IP;
+               $cldrPlural = "$IP/languages/data/plurals.xml";
+               $mwPlural = "$IP/languages/data/plurals-mediawiki.xml";
+               // Load CLDR plural rules
+               $this->loadPluralFile( $cldrPlural );
+               if ( file_exists( $mwPlural ) ) {
+                       // Override or extend
+                       $this->loadPluralFile( $mwPlural );
+               }
+       }
+
+       /**
+        * Load a plural XML file with the given filename, compile the relevant
+        * rules, and save the compiled rules in a process-local cache.
+        *
+        * @param string $fileName
+        * @throws MWException
+        */
+       protected function loadPluralFile( $fileName ) {
+               // Use file_get_contents instead of DOMDocument::load (T58439)
+               $xml = file_get_contents( $fileName );
+               if ( !$xml ) {
+                       throw new MWException( "Unable to read plurals file $fileName" );
+               }
+               $doc = new DOMDocument;
+               $doc->loadXML( $xml );
+               $rulesets = $doc->getElementsByTagName( "pluralRules" );
+               foreach ( $rulesets as $ruleset ) {
+                       $codes = $ruleset->getAttribute( 'locales' );
+                       $rules = [];
+                       $ruleTypes = [];
+                       $ruleElements = $ruleset->getElementsByTagName( "pluralRule" );
+                       foreach ( $ruleElements as $elt ) {
+                               $ruleType = $elt->getAttribute( 'count' );
+                               if ( $ruleType === 'other' ) {
+                                       // Don't record "other" rules, which have an empty condition
+                                       continue;
+                               }
+                               $rules[] = $elt->nodeValue;
+                               $ruleTypes[] = $ruleType;
+                       }
+                       foreach ( explode( ' ', $codes ) as $code ) {
+                               $this->pluralRules[$code] = $rules;
+                               $this->pluralRuleTypes[$code] = $ruleTypes;
+                       }
+               }
+       }
+
+       /**
+        * Read the data from the source files for a given language, and register
+        * the relevant dependencies in the $deps array. If the localisation
+        * exists, the data array is returned, otherwise false is returned.
+        *
+        * @param string $code
+        * @param array $deps
+        * @return array
+        */
+       protected function readSourceFilesAndRegisterDeps( $code, &$deps ) {
+               global $IP;
+
+               // This reads in the PHP i18n file with non-messages l10n data
+               $fileName = Language::getMessagesFileName( $code );
+               if ( !file_exists( $fileName ) ) {
+                       $data = [];
+               } else {
+                       $deps[] = new FileDependency( $fileName );
+                       $data = $this->readPHPFile( $fileName, 'core' );
+               }
+
+               # Load CLDR plural rules for JavaScript
+               $data['pluralRules'] = $this->getPluralRules( $code );
+               # And for PHP
+               $data['compiledPluralRules'] = $this->getCompiledPluralRules( $code );
+               # Load plural rule types
+               $data['pluralRuleTypes'] = $this->getPluralRuleTypes( $code );
+
+               $deps['plurals'] = new FileDependency( "$IP/languages/data/plurals.xml" );
+               $deps['plurals-mw'] = new FileDependency( "$IP/languages/data/plurals-mediawiki.xml" );
+
+               return $data;
+       }
+
+       /**
+        * Merge two localisation values, a primary and a fallback, overwriting the
+        * primary value in place.
+        * @param string $key
+        * @param mixed $value
+        * @param mixed $fallbackValue
+        */
+       protected function mergeItem( $key, &$value, $fallbackValue ) {
+               if ( !is_null( $value ) ) {
+                       if ( !is_null( $fallbackValue ) ) {
+                               if ( in_array( $key, self::$mergeableMapKeys ) ) {
+                                       $value = $value + $fallbackValue;
+                               } elseif ( in_array( $key, self::$mergeableListKeys ) ) {
+                                       $value = array_unique( array_merge( $fallbackValue, $value ) );
+                               } elseif ( in_array( $key, self::$mergeableAliasListKeys ) ) {
+                                       $value = array_merge_recursive( $value, $fallbackValue );
+                               } elseif ( in_array( $key, self::$optionalMergeKeys ) ) {
+                                       if ( !empty( $value['inherit'] ) ) {
+                                               $value = array_merge( $fallbackValue, $value );
+                                       }
+
+                                       if ( isset( $value['inherit'] ) ) {
+                                               unset( $value['inherit'] );
+                                       }
+                               } elseif ( in_array( $key, self::$magicWordKeys ) ) {
+                                       $this->mergeMagicWords( $value, $fallbackValue );
+                               }
+                       }
+               } else {
+                       $value = $fallbackValue;
+               }
+       }
+
+       /**
+        * @param mixed $value
+        * @param mixed $fallbackValue
+        */
+       protected function mergeMagicWords( &$value, $fallbackValue ) {
+               foreach ( $fallbackValue as $magicName => $fallbackInfo ) {
+                       if ( !isset( $value[$magicName] ) ) {
+                               $value[$magicName] = $fallbackInfo;
+                       } else {
+                               $oldSynonyms = array_slice( $fallbackInfo, 1 );
+                               $newSynonyms = array_slice( $value[$magicName], 1 );
+                               $synonyms = array_values( array_unique( array_merge(
+                                       $newSynonyms, $oldSynonyms ) ) );
+                               $value[$magicName] = array_merge( [ $fallbackInfo[0] ], $synonyms );
+                       }
+               }
+       }
+
+       /**
+        * Given an array mapping language code to localisation value, such as is
+        * found in extension *.i18n.php files, iterate through a fallback sequence
+        * to merge the given data with an existing primary value.
+        *
+        * Returns true if any data from the extension array was used, false
+        * otherwise.
+        * @param array $codeSequence
+        * @param string $key
+        * @param mixed $value
+        * @param mixed $fallbackValue
+        * @return bool
+        */
+       protected function mergeExtensionItem( $codeSequence, $key, &$value, $fallbackValue ) {
+               $used = false;
+               foreach ( $codeSequence as $code ) {
+                       if ( isset( $fallbackValue[$code] ) ) {
+                               $this->mergeItem( $key, $value, $fallbackValue[$code] );
+                               $used = true;
+                       }
+               }
+
+               return $used;
+       }
+
+       /**
+        * Gets the combined list of messages dirs from
+        * core and extensions
+        *
+        * @since 1.25
+        * @return array
+        */
+       public function getMessagesDirs() {
+               global $wgMessagesDirs, $IP;
+               return [
+                       'core' => "$IP/languages/i18n",
+                       'api' => "$IP/includes/api/i18n",
+                       'oojs-ui' => "$IP/resources/lib/oojs-ui/i18n",
+               ] + $wgMessagesDirs;
+       }
+
+       /**
+        * Load localisation data for a given language for both core and extensions
+        * and save it to the persistent cache store and the process cache
+        * @param string $code
+        * @throws MWException
+        */
+       public function recache( $code ) {
+               global $wgExtensionMessagesFiles;
+
+               if ( !$code ) {
+                       throw new MWException( "Invalid language code requested" );
+               }
+               $this->recachedLangs[$code] = true;
+
+               # Initial values
+               $initialData = array_fill_keys( self::$allKeys, null );
+               $coreData = $initialData;
+               $deps = [];
+
+               # Load the primary localisation from the source file
+               $data = $this->readSourceFilesAndRegisterDeps( $code, $deps );
+               if ( $data === false ) {
+                       wfDebug( __METHOD__ . ": no localisation file for $code, using fallback to en\n" );
+                       $coreData['fallback'] = 'en';
+               } else {
+                       wfDebug( __METHOD__ . ": got localisation for $code from source\n" );
+
+                       # Merge primary localisation
+                       foreach ( $data as $key => $value ) {
+                               $this->mergeItem( $key, $coreData[$key], $value );
+                       }
+               }
+
+               # Fill in the fallback if it's not there already
+               if ( is_null( $coreData['fallback'] ) ) {
+                       $coreData['fallback'] = $code === 'en' ? false : 'en';
+               }
+               if ( $coreData['fallback'] === false ) {
+                       $coreData['fallbackSequence'] = [];
+               } else {
+                       $coreData['fallbackSequence'] = array_map( 'trim', explode( ',', $coreData['fallback'] ) );
+                       $len = count( $coreData['fallbackSequence'] );
+
+                       # Ensure that the sequence ends at en
+                       if ( $coreData['fallbackSequence'][$len - 1] !== 'en' ) {
+                               $coreData['fallbackSequence'][] = 'en';
+                       }
+               }
+
+               $codeSequence = array_merge( [ $code ], $coreData['fallbackSequence'] );
+               $messageDirs = $this->getMessagesDirs();
+
+               # Load non-JSON localisation data for extensions
+               $extensionData = array_fill_keys( $codeSequence, $initialData );
+               foreach ( $wgExtensionMessagesFiles as $extension => $fileName ) {
+                       if ( isset( $messageDirs[$extension] ) ) {
+                               # This extension has JSON message data; skip the PHP shim
+                               continue;
+                       }
+
+                       $data = $this->readPHPFile( $fileName, 'extension' );
+                       $used = false;
+
+                       foreach ( $data as $key => $item ) {
+                               foreach ( $codeSequence as $csCode ) {
+                                       if ( isset( $item[$csCode] ) ) {
+                                               $this->mergeItem( $key, $extensionData[$csCode][$key], $item[$csCode] );
+                                               $used = true;
+                                       }
+                               }
+                       }
+
+                       if ( $used ) {
+                               $deps[] = new FileDependency( $fileName );
+                       }
+               }
+
+               # Load the localisation data for each fallback, then merge it into the full array
+               $allData = $initialData;
+               foreach ( $codeSequence as $csCode ) {
+                       $csData = $initialData;
+
+                       # Load core messages and the extension localisations.
+                       foreach ( $messageDirs as $dirs ) {
+                               foreach ( (array)$dirs as $dir ) {
+                                       $fileName = "$dir/$csCode.json";
+                                       $data = $this->readJSONFile( $fileName );
+
+                                       foreach ( $data as $key => $item ) {
+                                               $this->mergeItem( $key, $csData[$key], $item );
+                                       }
+
+                                       $deps[] = new FileDependency( $fileName );
+                               }
+                       }
+
+                       # Merge non-JSON extension data
+                       if ( isset( $extensionData[$csCode] ) ) {
+                               foreach ( $extensionData[$csCode] as $key => $item ) {
+                                       $this->mergeItem( $key, $csData[$key], $item );
+                               }
+                       }
+
+                       if ( $csCode === $code ) {
+                               # Merge core data into extension data
+                               foreach ( $coreData as $key => $item ) {
+                                       $this->mergeItem( $key, $csData[$key], $item );
+                               }
+                       } else {
+                               # Load the secondary localisation from the source file to
+                               # avoid infinite cycles on cyclic fallbacks
+                               $fbData = $this->readSourceFilesAndRegisterDeps( $csCode, $deps );
+                               if ( $fbData !== false ) {
+                                       # Only merge the keys that make sense to merge
+                                       foreach ( self::$allKeys as $key ) {
+                                               if ( !isset( $fbData[$key] ) ) {
+                                                       continue;
+                                               }
+
+                                               if ( is_null( $coreData[$key] ) || $this->isMergeableKey( $key ) ) {
+                                                       $this->mergeItem( $key, $csData[$key], $fbData[$key] );
+                                               }
+                                       }
+                               }
+                       }
+
+                       # Allow extensions an opportunity to adjust the data for this
+                       # fallback
+                       Hooks::run( 'LocalisationCacheRecacheFallback', [ $this, $csCode, &$csData ] );
+
+                       # Merge the data for this fallback into the final array
+                       if ( $csCode === $code ) {
+                               $allData = $csData;
+                       } else {
+                               foreach ( self::$allKeys as $key ) {
+                                       if ( !isset( $csData[$key] ) ) {
+                                               continue;
+                                       }
+
+                                       if ( is_null( $allData[$key] ) || $this->isMergeableKey( $key ) ) {
+                                               $this->mergeItem( $key, $allData[$key], $csData[$key] );
+                                       }
+                               }
+                       }
+               }
+
+               # Add cache dependencies for any referenced globals
+               $deps['wgExtensionMessagesFiles'] = new GlobalDependency( 'wgExtensionMessagesFiles' );
+               // $wgMessagesDirs is used in LocalisationCache::getMessagesDirs()
+               $deps['wgMessagesDirs'] = new GlobalDependency( 'wgMessagesDirs' );
+               $deps['version'] = new ConstantDependency( 'LocalisationCache::VERSION' );
+
+               # Add dependencies to the cache entry
+               $allData['deps'] = $deps;
+
+               # Replace spaces with underscores in namespace names
+               $allData['namespaceNames'] = str_replace( ' ', '_', $allData['namespaceNames'] );
+
+               # And do the same for special page aliases. $page is an array.
+               foreach ( $allData['specialPageAliases'] as &$page ) {
+                       $page = str_replace( ' ', '_', $page );
+               }
+               # Decouple the reference to prevent accidental damage
+               unset( $page );
+
+               # If there were no plural rules, return an empty array
+               if ( $allData['pluralRules'] === null ) {
+                       $allData['pluralRules'] = [];
+               }
+               if ( $allData['compiledPluralRules'] === null ) {
+                       $allData['compiledPluralRules'] = [];
+               }
+               # If there were no plural rule types, return an empty array
+               if ( $allData['pluralRuleTypes'] === null ) {
+                       $allData['pluralRuleTypes'] = [];
+               }
+
+               # Set the list keys
+               $allData['list'] = [];
+               foreach ( self::$splitKeys as $key ) {
+                       $allData['list'][$key] = array_keys( $allData[$key] );
+               }
+               # Run hooks
+               $purgeBlobs = true;
+               Hooks::run( 'LocalisationCacheRecache', [ $this, $code, &$allData, &$purgeBlobs ] );
+
+               if ( is_null( $allData['namespaceNames'] ) ) {
+                       throw new MWException( __METHOD__ . ': Localisation data failed sanity check! ' .
+                               'Check that your languages/messages/MessagesEn.php file is intact.' );
+               }
+
+               # Set the preload key
+               $allData['preload'] = $this->buildPreload( $allData );
+
+               # Save to the process cache and register the items loaded
+               $this->data[$code] = $allData;
+               foreach ( $allData as $key => $item ) {
+                       $this->loadedItems[$code][$key] = true;
+               }
+
+               # Save to the persistent cache
+               $this->store->startWrite( $code );
+               foreach ( $allData as $key => $value ) {
+                       if ( in_array( $key, self::$splitKeys ) ) {
+                               foreach ( $value as $subkey => $subvalue ) {
+                                       $this->store->set( "$key:$subkey", $subvalue );
+                               }
+                       } else {
+                               $this->store->set( $key, $value );
+                       }
+               }
+               $this->store->finishWrite();
+
+               # Clear out the MessageBlobStore
+               # HACK: If using a null (i.e. disabled) storage backend, we
+               # can't write to the MessageBlobStore either
+               if ( $purgeBlobs && !$this->store instanceof LCStoreNull ) {
+                       $blobStore = new MessageBlobStore();
+                       $blobStore->clear();
+               }
+
+       }
+
+       /**
+        * Build the preload item from the given pre-cache data.
+        *
+        * The preload item will be loaded automatically, improving performance
+        * for the commonly-requested items it contains.
+        * @param array $data
+        * @return array
+        */
+       protected function buildPreload( $data ) {
+               $preload = [ 'messages' => [] ];
+               foreach ( self::$preloadedKeys as $key ) {
+                       $preload[$key] = $data[$key];
+               }
+
+               foreach ( $data['preloadedMessages'] as $subkey ) {
+                       if ( isset( $data['messages'][$subkey] ) ) {
+                               $subitem = $data['messages'][$subkey];
+                       } else {
+                               $subitem = null;
+                       }
+                       $preload['messages'][$subkey] = $subitem;
+               }
+
+               return $preload;
+       }
+
+       /**
+        * Unload the data for a given language from the object cache.
+        * Reduces memory usage.
+        * @param string $code
+        */
+       public function unload( $code ) {
+               unset( $this->data[$code] );
+               unset( $this->loadedItems[$code] );
+               unset( $this->loadedSubitems[$code] );
+               unset( $this->initialisedLangs[$code] );
+               unset( $this->shallowFallbacks[$code] );
+
+               foreach ( $this->shallowFallbacks as $shallowCode => $fbCode ) {
+                       if ( $fbCode === $code ) {
+                               $this->unload( $shallowCode );
+                       }
+               }
+       }
+
+       /**
+        * Unload all data
+        */
+       public function unloadAll() {
+               foreach ( $this->initialisedLangs as $lang => $unused ) {
+                       $this->unload( $lang );
+               }
+       }
+
+       /**
+        * Disable the storage backend
+        */
+       public function disableBackend() {
+               $this->store = new LCStoreNull;
+               $this->manualRecache = false;
+       }
+
+}
diff --git a/includes/cache/localisation/LocalisationCacheBulkLoad.php b/includes/cache/localisation/LocalisationCacheBulkLoad.php
new file mode 100644 (file)
index 0000000..30c7d37
--- /dev/null
@@ -0,0 +1,126 @@
+<?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
+ */
+
+/**
+ * A localisation cache optimised for loading large amounts of data for many
+ * languages. Used by rebuildLocalisationCache.php.
+ */
+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.
+        */
+       private $fileCache = [];
+
+       /**
+        * 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.
+        */
+       private $mruLangs = [];
+
+       /**
+        * Maximum number of languages that may be loaded into $this->data
+        */
+       private $maxLoadedLangs = 10;
+
+       /**
+        * @param string $fileName
+        * @param string $fileType
+        * @return array|mixed
+        */
+       protected function readPHPFile( $fileName, $fileType ) {
+               $serialize = $fileType === 'core';
+               if ( !isset( $this->fileCache[$fileName][$fileType] ) ) {
+                       $data = parent::readPHPFile( $fileName, $fileType );
+
+                       if ( $serialize ) {
+                               $encData = serialize( $data );
+                       } else {
+                               $encData = $data;
+                       }
+
+                       $this->fileCache[$fileName][$fileType] = $encData;
+
+                       return $data;
+               } elseif ( $serialize ) {
+                       return unserialize( $this->fileCache[$fileName][$fileType] );
+               } else {
+                       return $this->fileCache[$fileName][$fileType];
+               }
+       }
+
+       /**
+        * @param string $code
+        * @param string $key
+        * @return mixed
+        */
+       public function getItem( $code, $key ) {
+               unset( $this->mruLangs[$code] );
+               $this->mruLangs[$code] = true;
+
+               return parent::getItem( $code, $key );
+       }
+
+       /**
+        * @param string $code
+        * @param string $key
+        * @param string $subkey
+        * @return mixed
+        */
+       public function getSubitem( $code, $key, $subkey ) {
+               unset( $this->mruLangs[$code] );
+               $this->mruLangs[$code] = true;
+
+               return parent::getSubitem( $code, $key, $subkey );
+       }
+
+       /**
+        * @param string $code
+        */
+       public function recache( $code ) {
+               parent::recache( $code );
+               unset( $this->mruLangs[$code] );
+               $this->mruLangs[$code] = true;
+               $this->trimCache();
+       }
+
+       /**
+        * @param string $code
+        */
+       public function unload( $code ) {
+               unset( $this->mruLangs[$code] );
+               parent::unload( $code );
+       }
+
+       /**
+        * Unload cached languages until there are less than $this->maxLoadedLangs
+        */
+       protected function trimCache() {
+               while ( count( $this->data ) > $this->maxLoadedLangs && count( $this->mruLangs ) ) {
+                       reset( $this->mruLangs );
+                       $code = key( $this->mruLangs );
+                       wfDebug( __METHOD__ . ": unloading $code\n" );
+                       $this->unload( $code );
+               }
+       }
+
+}
index 637eb88..cf97afb 100644 (file)
@@ -344,9 +344,9 @@ class ChangesList extends ContextSource {
        /**
         * @param string $s HTML to update
         * @param RecentChange $rc
-        * @param bool $unpatrolled
+        * @param bool|null $unpatrolled Unused variable, since 1.27.
         */
-       public function insertDiffHist( &$s, &$rc, $unpatrolled ) {
+       public function insertDiffHist( &$s, &$rc, $unpatrolled = null ) {
                # Diff link
                if (
                        $rc->mAttribs['rc_type'] == RC_NEW ||
index 4a028bb..d79f316 100644 (file)
@@ -157,8 +157,10 @@ class EnhancedChangesList extends ChangesList {
         * Enhanced RC group
         * @param RCCacheEntry[] $block
         * @return string
+        * @throws DomainException
         */
        protected function recentChangesBlockGroup( $block ) {
+               $recentChangesFlags = $this->getConfig()->get( 'RecentChangesFlags' );
 
                # Add the namespace and title of the block as part of the class
                $tableClasses = [ 'mw-collapsible', 'mw-collapsed', 'mw-enhanced-rc' ];
@@ -186,20 +188,24 @@ class EnhancedChangesList extends ChangesList {
                $namehidden = true;
                $allLogs = true;
                $RCShowChangedSize = $this->getConfig()->get( 'RCShowChangedSize' );
-               $collectedRcFlags = [
-                       // All are by bots?
-                       'bot' => true,
-                       // Includes a new page?
-                       'newpage' => false,
-                       // All are minor edits?
-                       'minor' => true,
-                       // Contains an unpatrolled edit?
-                       'unpatrolled' => false,
-               ];
-               foreach ( $block as $rcObj ) {
-                       if ( $rcObj->mAttribs['rc_type'] == RC_NEW ) {
-                               $collectedRcFlags['newpage'] = true;
+
+               # Default values for RC flags
+               $collectedRcFlags = [];
+               foreach ( $recentChangesFlags as $key => $value ) {
+                       $flagGrouping = ( isset( $recentChangesFlags[$key]['grouping'] ) ?
+                                       $recentChangesFlags[$key]['grouping'] : 'any' );
+                       switch ( $flagGrouping ) {
+                               case 'all':
+                                       $collectedRcFlags[$key] = true;
+                                       break;
+                               case 'any':
+                                       $collectedRcFlags[$key] = false;
+                                       break;
+                               default:
+                                       throw new DomainException( "Unknown grouping type \"{$flagGrouping}\"" );
                        }
+               }
+               foreach ( $block as $rcObj ) {
                        // If all log actions to this page were hidden, then don't
                        // give the name of the affected page for this block!
                        if ( !$this->isDeleted( $rcObj, LogPage::DELETED_ACTION ) ) {
@@ -209,9 +215,6 @@ class EnhancedChangesList extends ChangesList {
                        if ( !isset( $userlinks[$u] ) ) {
                                $userlinks[$u] = 0;
                        }
-                       if ( $rcObj->unpatrolled ) {
-                               $collectedRcFlags['unpatrolled'] = true;
-                       }
                        if ( $rcObj->mAttribs['rc_type'] != RC_LOG ) {
                                $allLogs = false;
                        }
@@ -221,13 +224,6 @@ class EnhancedChangesList extends ChangesList {
                                $curId = $rcObj->mAttribs['rc_cur_id'];
                        }
 
-                       if ( !$rcObj->mAttribs['rc_bot'] ) {
-                               $collectedRcFlags['bot'] = false;
-                       }
-                       if ( !$rcObj->mAttribs['rc_minor'] ) {
-                               $collectedRcFlags['minor'] = false;
-                       }
-
                        $userlinks[$u]++;
                }
 
@@ -267,6 +263,27 @@ class EnhancedChangesList extends ChangesList {
                                // completely ignore this RC entry if we don't want to render it
                                unset( $block[$i] );
                        }
+
+                       // Roll up flags
+                       foreach ( $line['recentChangesFlagsRaw'] as $key => $value ) {
+                               $flagGrouping = ( isset( $recentChangesFlags[$key]['grouping'] ) ?
+                                       $recentChangesFlags[$key]['grouping'] : 'any' );
+                               switch ( $flagGrouping ) {
+                                       case 'all':
+                                               if ( !$value ) {
+                                                       $collectedRcFlags[$key] = false;
+                                               }
+                                               break;
+                                       case 'any':
+                                               if ( $value ) {
+                                                       $collectedRcFlags[$key] = true;
+                                               }
+                                               break;
+                                       default:
+                                               throw new DomainException( "Unknown grouping type \"{$flagGrouping}\"" );
+                               }
+                       }
+
                        $lines[] = $line;
                }
                // Further down are some assumptions that $block is a 0-indexed array
@@ -436,8 +453,11 @@ class EnhancedChangesList extends ChangesList {
                        return [];
                }
 
+               $lineParams['recentChangesFlagsRaw'] = [];
                if ( isset( $data['recentChangesFlags'] ) ) {
                        $lineParams['recentChangesFlags'] = $this->recentChangesFlags( $data['recentChangesFlags'] );
+                       # FIXME: This is used by logic, don't return it in the template params.
+                       $lineParams['recentChangesFlagsRaw'] = $data['recentChangesFlags'];
                        unset( $data['recentChangesFlags'] );
                }
 
@@ -503,10 +523,11 @@ class EnhancedChangesList extends ChangesList {
                /** @var $block0 RecentChange */
                $block0 = $block[0];
                $last = $block[count( $block ) - 1];
-               if ( !$allLogs && $rcObj->mAttribs['rc_type'] != RC_CATEGORIZE ) {
-                       if ( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ) {
-                               $links['total-changes'] = $nchanges[$n];
-                       } elseif ( $isnew ) {
+               if ( !$allLogs ) {
+                       if ( !ChangesList::userCan( $rcObj, Revision::DELETED_TEXT, $this->getUser() ) ||
+                               $isnew ||
+                               $rcObj->mAttribs['rc_type'] == RC_CATEGORIZE
+                       ) {
                                $links['total-changes'] = $nchanges[$n];
                        } else {
                                $links['total-changes'] = Linker::link(
index 576718a..8eb06ce 100644 (file)
@@ -87,7 +87,7 @@ class OldChangesList extends ChangesList {
                        }
                // Regular entries
                } else {
-                       $this->insertDiffHist( $html, $rc, $unpatrolled );
+                       $this->insertDiffHist( $html, $rc );
                        # M, N, b and ! (minor, new, bot and unpatrolled)
                        $html .= $this->recentChangesFlags(
                                [
index b6a0868..2508304 100644 (file)
@@ -461,6 +461,7 @@ class RecentChange {
         */
        public function doMarkPatrolled( User $user, $auto = false, $tags = null ) {
                global $wgUseRCPatrol, $wgUseNPPatrol, $wgUseFilePatrol;
+
                $errors = [];
                // If recentchanges patrol is disabled, only new pages or new file versions
                // can be patrolled, provided the appropriate config variable is set
@@ -497,8 +498,8 @@ class RecentChange {
                PatrolLog::record( $this, $auto, $user, $tags );
 
                Hooks::run(
-                                       'MarkPatrolledComplete',
-                                       [ $this->getAttribute( 'rc_id' ), &$user, false, $auto ]
+                       'MarkPatrolledComplete',
+                       [ $this->getAttribute( 'rc_id' ), &$user, false, $auto ]
                );
 
                return [];
@@ -719,11 +720,12 @@ class RecentChange {
         * @param int $newId
         * @param string $actionCommentIRC
         * @param int $revId Id of associated revision, if any
+        * @param bool $isPatrollable Whether this log entry is patrollable
         * @return RecentChange
         */
        public static function newLogEntry( $timestamp, &$title, &$user, $actionComment, $ip,
                $type, $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '',
-               $revId = 0 ) {
+               $revId = 0, $isPatrollable = false ) {
                global $wgRequest;
 
                # # Get pageStatus for email notification
@@ -747,9 +749,8 @@ class RecentChange {
                                break;
                }
 
-               // Allow unpatrolled status when an associated rev id is passed
-               // May be used in core by moves and uploads
-               $markPatrolled = ( $revId > 0 ) ? $user->isAllowed( 'autopatrol' ) : true;
+               // Allow unpatrolled status for patrollable log entries
+               $markPatrolled = $isPatrollable ? $user->isAllowed( 'autopatrol' ) : true;
 
                $rc = new RecentChange;
                $rc->mTitle = $target;
index 24bded7..2dc953c 100644 (file)
@@ -73,8 +73,8 @@ class ChangeTagsLogItem extends RevisionItemBase {
                $loglink = Linker::link(
                        SpecialPage::getTitleFor( 'Log' ),
                        $this->list->msg( 'log' )->escaped(),
-                       array(),
-                       array( 'page' => $title->getPrefixedText() )
+                       [],
+                       [ 'page' => $title->getPrefixedText() ]
                );
                $loglink = $this->list->msg( 'parentheses' )->rawParams( $loglink )->escaped();
                // User links and action text
@@ -88,7 +88,7 @@ class ChangeTagsLogItem extends RevisionItemBase {
                }
 
                $content = "$loglink $date $action $comment";
-               $attribs = array();
+               $attribs = [];
                $tags = $this->getTags();
                if ( $tags ) {
                        list( $tagSummary, $classes ) = ChangeTags::formatSummaryRow(
diff --git a/includes/collation/Collation.php b/includes/collation/Collation.php
new file mode 100644 (file)
index 0000000..9fb0660
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Database row sorting.
+ *
+ * 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
+ */
+
+/**
+ * @since 1.16.3
+ * @author Tim Starling
+ */
+abstract class Collation {
+       private static $instance;
+
+       /**
+        * @since 1.16.3
+        * @return Collation
+        */
+       public static function singleton() {
+               if ( !self::$instance ) {
+                       global $wgCategoryCollation;
+                       self::$instance = self::factory( $wgCategoryCollation );
+               }
+               return self::$instance;
+       }
+
+       /**
+        * @since 1.16.3
+        * @throws MWException
+        * @param string $collationName
+        * @return Collation
+        */
+       public static function factory( $collationName ) {
+               switch ( $collationName ) {
+                       case 'uppercase':
+                               return new UppercaseCollation;
+                       case 'identity':
+                               return new IdentityCollation;
+                       case 'uca-default':
+                               return new IcuCollation( 'root' );
+                       case 'xx-uca-ckb':
+                               return new CollationCkb;
+                       case 'xx-uca-et':
+                               return new CollationEt;
+                       default:
+                               $match = [];
+                               if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
+                                       return new IcuCollation( $match[1] );
+                               }
+
+                               # Provide a mechanism for extensions to hook in.
+                               $collationObject = null;
+                               Hooks::run( 'Collation::factory', [ $collationName, &$collationObject ] );
+
+                               if ( $collationObject instanceof Collation ) {
+                                       return $collationObject;
+                               }
+
+                               // If all else fails...
+                               throw new MWException( __METHOD__ . ": unknown collation type \"$collationName\"" );
+               }
+       }
+
+       /**
+        * Given a string, convert it to a (hopefully short) key that can be used
+        * for efficient sorting.  A binary sort according to the sortkeys
+        * corresponds to a logical sort of the corresponding strings.  Current
+        * code expects that a line feed character should sort before all others, but
+        * has no other particular expectations (and that one can be changed if
+        * necessary).
+        *
+        * @since 1.16.3
+        *
+        * @param string $string UTF-8 string
+        * @return string Binary sortkey
+        */
+       abstract function getSortKey( $string );
+
+       /**
+        * Given a string, return the logical "first letter" to be used for
+        * grouping on category pages and so on.  This has to be coordinated
+        * carefully with convertToSortkey(), or else the sorted list might jump
+        * back and forth between the same "initial letters" or other pathological
+        * behavior.  For instance, if you just return the first character, but "a"
+        * sorts the same as "A" based on getSortKey(), then you might get a
+        * list like
+        *
+        * == A ==
+        * * [[Aardvark]]
+        *
+        * == a ==
+        * * [[antelope]]
+        *
+        * == A ==
+        * * [[Ape]]
+        *
+        * etc., assuming for the sake of argument that $wgCapitalLinks is false.
+        *
+        * @since 1.16.3
+        *
+        * @param string $string UTF-8 string
+        * @return string UTF-8 string corresponding to the first letter of input
+        */
+       abstract function getFirstLetter( $string );
+
+}
diff --git a/includes/collation/CollationCkb.php b/includes/collation/CollationCkb.php
new file mode 100644 (file)
index 0000000..01a4f7f
--- /dev/null
@@ -0,0 +1,35 @@
+<?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
+ */
+
+/**
+ * Workaround for the lack of support of Sorani Kurdish / Central Kurdish language ('ckb') in ICU.
+ *
+ * Uses the same collation rules as Persian / Farsi ('fa'), but different characters for digits.
+ *
+ * @since 1.23
+ */
+class CollationCkb extends IcuCollation {
+       public function __construct() {
+               // This will set $locale and collators, which affect the actual sorting order
+               parent::__construct( 'fa' );
+               // Override the 'fa' language set by parent constructor, which affects #getFirstLetterData()
+               $this->digitTransformLanguage = Language::factory( 'ckb' );
+       }
+}
diff --git a/includes/collation/CollationEt.php b/includes/collation/CollationEt.php
new file mode 100644 (file)
index 0000000..5dc9fa2
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Workaround for incorrect collation of Estonian language ('et') in ICU (bug 54168).
+ *
+ * 'W' and 'V' should not be considered the same letter for the purposes of collation in modern
+ * Estonian. We work around this by replacing 'W' and 'w' with 'ᴡ' U+1D21 'LATIN LETTER SMALL
+ * CAPITAL W' for sortkey generation, which is collated like 'W' and is not tailored to have the
+ * same primary weight as 'V' in Estonian.
+ *
+ * @since 1.24
+ */
+class CollationEt extends IcuCollation {
+       public function __construct() {
+               parent::__construct( 'et' );
+       }
+
+       private static function mangle( $string ) {
+               return str_replace(
+                       [ 'w', 'W' ],
+                       'ᴡ', // U+1D21 'LATIN LETTER SMALL CAPITAL W'
+                       $string
+               );
+       }
+
+       private static function unmangle( $string ) {
+               // Casing data is lost…
+               return str_replace(
+                       'ᴡ', // U+1D21 'LATIN LETTER SMALL CAPITAL W'
+                       'W',
+                       $string
+               );
+       }
+
+       public function getSortKey( $string ) {
+               return parent::getSortKey( self::mangle( $string ) );
+       }
+
+       public function getFirstLetter( $string ) {
+               return self::unmangle( parent::getFirstLetter( self::mangle( $string ) ) );
+       }
+}
diff --git a/includes/collation/IcuCollation.php b/includes/collation/IcuCollation.php
new file mode 100644 (file)
index 0000000..0aa1406
--- /dev/null
@@ -0,0 +1,481 @@
+<?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
+ */
+
+/**
+ * @since 1.16.3
+ */
+class IcuCollation extends Collation {
+       const FIRST_LETTER_VERSION = 2;
+
+       /** @var Collator */
+       private $primaryCollator;
+
+       /** @var Collator */
+       private $mainCollator;
+
+       /** @var string */
+       private $locale;
+
+       /** @var Language */
+       protected $digitTransformLanguage;
+
+       /** @var array */
+       private $firstLetterData;
+
+       /**
+        * Unified CJK blocks.
+        *
+        * The same definition of a CJK block must be used for both Collation and
+        * generateCollationData.php. These blocks are omitted from the first
+        * letter data, as an optimisation measure and because the default UCA table
+        * is pretty useless for sorting Chinese text anyway. Japanese and Korean
+        * blocks are not included here, because they are smaller and more useful.
+        */
+       private static $cjkBlocks = [
+               [ 0x2E80, 0x2EFF ], // CJK Radicals Supplement
+               [ 0x2F00, 0x2FDF ], // Kangxi Radicals
+               [ 0x2FF0, 0x2FFF ], // Ideographic Description Characters
+               [ 0x3000, 0x303F ], // CJK Symbols and Punctuation
+               [ 0x31C0, 0x31EF ], // CJK Strokes
+               [ 0x3200, 0x32FF ], // Enclosed CJK Letters and Months
+               [ 0x3300, 0x33FF ], // CJK Compatibility
+               [ 0x3400, 0x4DBF ], // CJK Unified Ideographs Extension A
+               [ 0x4E00, 0x9FFF ], // CJK Unified Ideographs
+               [ 0xF900, 0xFAFF ], // CJK Compatibility Ideographs
+               [ 0xFE30, 0xFE4F ], // CJK Compatibility Forms
+               [ 0x20000, 0x2A6DF ], // CJK Unified Ideographs Extension B
+               [ 0x2A700, 0x2B73F ], // CJK Unified Ideographs Extension C
+               [ 0x2B740, 0x2B81F ], // CJK Unified Ideographs Extension D
+               [ 0x2F800, 0x2FA1F ], // CJK Compatibility Ideographs Supplement
+       ];
+
+       /**
+        * Additional characters (or character groups) to be considered separate
+        * letters for given languages, or to be removed from the list of such
+        * letters (denoted by keys starting with '-').
+        *
+        * These are additions to (or subtractions from) the data stored in the
+        * first-letters-root.ser file (which among others includes full basic latin,
+        * cyrillic and greek alphabets).
+        *
+        * "Separate letter" is a letter that would have a separate heading/section
+        * for it in a dictionary or a phone book in this language. This data isn't
+        * used for sorting (the ICU library handles that), only for deciding which
+        * characters (or character groups) to use as headings.
+        *
+        * Initially generated based on the primary level of Unicode collation
+        * tailorings available at http://developer.mimer.com/charts/tailorings.htm ,
+        * later modified.
+        *
+        * Empty arrays are intended; this signifies that the data for the language is
+        * available and that there are, in fact, no additional letters to consider.
+        */
+       private static $tailoringFirstLetters = [
+               // Verified by native speakers
+               'be' => [ "Ё" ],
+               'be-tarask' => [ "Ё" ],
+               'cy' => [ "Ch", "Dd", "Ff", "Ng", "Ll", "Ph", "Rh", "Th" ],
+               'en' => [],
+               'fa' => [ "آ", "ء", "ه" ],
+               'fi' => [ "Å", "Ä", "Ö" ],
+               'fr' => [],
+               'hu' => [ "Cs", "Dz", "Dzs", "Gy", "Ly", "Ny", "Ö", "Sz", "Ty", "Ü", "Zs" ],
+               'is' => [ "Á", "Ð", "É", "Í", "Ó", "Ú", "Ý", "Þ", "Æ", "Ö", "Å" ],
+               'it' => [],
+               'lv' => [ "Č", "Ģ", "Ķ", "Ļ", "Ņ", "Š", "Ž" ],
+               'pl' => [ "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ],
+               'pt' => [],
+               'ru' => [],
+               'sv' => [ "Å", "Ä", "Ö" ],
+               'sv@collation=standard' => [ "Å", "Ä", "Ö" ],
+               'uk' => [ "Ґ", "Ь" ],
+               'vi' => [ "Ă", "Â", "Đ", "Ê", "Ô", "Ơ", "Ư" ],
+               // Not verified, but likely correct
+               'af' => [],
+               'ast' => [ "Ch", "Ll", "Ñ" ],
+               'az' => [ "Ç", "Ə", "Ğ", "İ", "Ö", "Ş", "Ü" ],
+               'bg' => [],
+               'br' => [ "Ch", "C'h" ],
+               'bs' => [ "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ],
+               'ca' => [],
+               'co' => [],
+               'cs' => [ "Č", "Ch", "Ř", "Š", "Ž" ],
+               'da' => [ "Æ", "Ø", "Å" ],
+               'de' => [],
+               'dsb' => [ "Č", "Ć", "Dź", "Ě", "Ch", "Ł", "Ń", "Ŕ", "Š", "Ś", "Ž", "Ź" ],
+               'el' => [],
+               'eo' => [ "Ĉ", "Ĝ", "Ĥ", "Ĵ", "Ŝ", "Ŭ" ],
+               'es' => [ "Ñ" ],
+               'et' => [ "Š", "Ž", "Õ", "Ä", "Ö", "Ü", "W" ], // added W for CollationEt (xx-uca-et)
+               'eu' => [ "Ñ" ],
+               'fo' => [ "Á", "Ð", "Í", "Ó", "Ú", "Ý", "Æ", "Ø", "Å" ],
+               'fur' => [ "À", "Á", "Â", "È", "Ì", "Ò", "Ù" ],
+               'fy' => [],
+               'ga' => [],
+               'gd' => [],
+               'gl' => [ "Ch", "Ll", "Ñ" ],
+               'hr' => [ "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ],
+               'hsb' => [ "Č", "Dź", "Ě", "Ch", "Ł", "Ń", "Ř", "Š", "Ć", "Ž" ],
+               'kk' => [ "Ү", "І" ],
+               'kl' => [ "Æ", "Ø", "Å" ],
+               'ku' => [ "Ç", "Ê", "Î", "Ş", "Û" ],
+               'ky' => [ "Ё" ],
+               'la' => [],
+               'lb' => [],
+               'lt' => [ "Č", "Š", "Ž" ],
+               'mk' => [],
+               'mo' => [ "Ă", "Â", "Î", "Ş", "Ţ" ],
+               'mt' => [ "Ċ", "Ġ", "Għ", "Ħ", "Ż" ],
+               'nl' => [],
+               'no' => [ "Æ", "Ø", "Å" ],
+               'oc' => [],
+               'rm' => [],
+               'ro' => [ "Ă", "Â", "Î", "Ş", "Ţ" ],
+               'rup' => [ "Ă", "Â", "Î", "Ľ", "Ń", "Ş", "Ţ" ],
+               'sco' => [],
+               'sk' => [ "Ä", "Č", "Ch", "Ô", "Š", "Ž" ],
+               'sl' => [ "Č", "Š", "Ž" ],
+               'smn' => [ "Á", "Č", "Đ", "Ŋ", "Š", "Ŧ", "Ž", "Æ", "Ø", "Å", "Ä", "Ö" ],
+               'sq' => [ "Ç", "Dh", "Ë", "Gj", "Ll", "Nj", "Rr", "Sh", "Th", "Xh", "Zh" ],
+               'sr' => [],
+               'tk' => [ "Ç", "Ä", "Ž", "Ň", "Ö", "Ş", "Ü", "Ý" ],
+               'tl' => [ "Ñ", "Ng" ],
+               'tr' => [ "Ç", "Ğ", "İ", "Ö", "Ş", "Ü" ],
+               'tt' => [ "Ә", "Ө", "Ү", "Җ", "Ң", "Һ" ],
+               'uz' => [ "Ch", "G'", "Ng", "O'", "Sh" ],
+       ];
+
+       /**
+        * @since 1.16.3
+        */
+       const RECORD_LENGTH = 14;
+
+       public function __construct( $locale ) {
+               if ( !extension_loaded( 'intl' ) ) {
+                       throw new MWException( 'An ICU collation was requested, ' .
+                               'but the intl extension is not available.' );
+               }
+
+               $this->locale = $locale;
+               // Drop everything after the '@' in locale's name
+               $localeParts = explode( '@', $locale );
+               $this->digitTransformLanguage = Language::factory( $locale === 'root' ? 'en' : $localeParts[0] );
+
+               $this->mainCollator = Collator::create( $locale );
+               if ( !$this->mainCollator ) {
+                       throw new MWException( "Invalid ICU locale specified for collation: $locale" );
+               }
+
+               $this->primaryCollator = Collator::create( $locale );
+               $this->primaryCollator->setStrength( Collator::PRIMARY );
+       }
+
+       public function getSortKey( $string ) {
+               // intl extension produces non null-terminated
+               // strings. Appending '' fixes it so that it doesn't generate
+               // a warning on each access in debug php.
+               MediaWiki\suppressWarnings();
+               $key = $this->mainCollator->getSortKey( $string ) . '';
+               MediaWiki\restoreWarnings();
+               return $key;
+       }
+
+       public function getPrimarySortKey( $string ) {
+               MediaWiki\suppressWarnings();
+               $key = $this->primaryCollator->getSortKey( $string ) . '';
+               MediaWiki\restoreWarnings();
+               return $key;
+       }
+
+       public function getFirstLetter( $string ) {
+               $string = strval( $string );
+               if ( $string === '' ) {
+                       return '';
+               }
+
+               // Check for CJK
+               $firstChar = mb_substr( $string, 0, 1, 'UTF-8' );
+               if ( ord( $firstChar ) > 0x7f && self::isCjk( UtfNormal\Utils::utf8ToCodepoint( $firstChar ) ) ) {
+                       return $firstChar;
+               }
+
+               $sortKey = $this->getPrimarySortKey( $string );
+
+               // Do a binary search to find the correct letter to sort under
+               $min = ArrayUtils::findLowerBound(
+                       [ $this, 'getSortKeyByLetterIndex' ],
+                       $this->getFirstLetterCount(),
+                       'strcmp',
+                       $sortKey );
+
+               if ( $min === false ) {
+                       // Before the first letter
+                       return '';
+               }
+               return $this->getLetterByIndex( $min );
+       }
+
+       /**
+        * @since 1.16.3
+        */
+       public function getFirstLetterData() {
+               if ( $this->firstLetterData !== null ) {
+                       return $this->firstLetterData;
+               }
+
+               $cache = wfGetCache( CACHE_ANYTHING );
+               $cacheKey = wfMemcKey(
+                       'first-letters',
+                       $this->locale,
+                       $this->digitTransformLanguage->getCode(),
+                       self::getICUVersion()
+               );
+               $cacheEntry = $cache->get( $cacheKey );
+
+               if ( $cacheEntry && isset( $cacheEntry['version'] )
+                       && $cacheEntry['version'] == self::FIRST_LETTER_VERSION
+               ) {
+                       $this->firstLetterData = $cacheEntry;
+                       return $this->firstLetterData;
+               }
+
+               // Generate data from serialized data file
+
+               if ( isset( self::$tailoringFirstLetters[$this->locale] ) ) {
+                       $letters = wfGetPrecompiledData( "first-letters-root.ser" );
+                       // Append additional characters
+                       $letters = array_merge( $letters, self::$tailoringFirstLetters[$this->locale] );
+                       // Remove unnecessary ones, if any
+                       if ( isset( self::$tailoringFirstLetters['-' . $this->locale] ) ) {
+                               $letters = array_diff( $letters, self::$tailoringFirstLetters['-' . $this->locale] );
+                       }
+                       // Apply digit transforms
+                       $digits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
+                       $letters = array_diff( $letters, $digits );
+                       foreach ( $digits as $digit ) {
+                               $letters[] = $this->digitTransformLanguage->formatNum( $digit, true );
+                       }
+               } else {
+                       $letters = wfGetPrecompiledData( "first-letters-{$this->locale}.ser" );
+                       if ( $letters === false ) {
+                               throw new MWException( "MediaWiki does not support ICU locale " .
+                                       "\"{$this->locale}\"" );
+                       }
+               }
+
+               /* Sort the letters.
+                *
+                * It's impossible to have the precompiled data file properly sorted,
+                * because the sort order changes depending on ICU version. If the
+                * array is not properly sorted, the binary search will return random
+                * results.
+                *
+                * We also take this opportunity to remove primary collisions.
+                */
+               $letterMap = [];
+               foreach ( $letters as $letter ) {
+                       $key = $this->getPrimarySortKey( $letter );
+                       if ( isset( $letterMap[$key] ) ) {
+                               // Primary collision
+                               // Keep whichever one sorts first in the main collator
+                               if ( $this->mainCollator->compare( $letter, $letterMap[$key] ) < 0 ) {
+                                       $letterMap[$key] = $letter;
+                               }
+                       } else {
+                               $letterMap[$key] = $letter;
+                       }
+               }
+               ksort( $letterMap, SORT_STRING );
+
+               /* Remove duplicate prefixes. Basically if something has a sortkey
+                * which is a prefix of some other sortkey, then it is an
+                * expansion and probably should not be considered a section
+                * header.
+                *
+                * For example 'þ' is sometimes sorted as if it is the letters
+                * 'th'. Other times it is its own primary element. Another
+                * example is '₨'. Sometimes its a currency symbol. Sometimes it
+                * is an 'R' followed by an 's'.
+                *
+                * Additionally an expanded element should always sort directly
+                * after its first element due to they way sortkeys work.
+                *
+                * UCA sortkey elements are of variable length but no collation
+                * element should be a prefix of some other element, so I think
+                * this is safe. See:
+                * - https://ssl.icu-project.org/repos/icu/icuhtml/trunk/design/collation/ICU_collation_design.htm
+                * - http://site.icu-project.org/design/collation/uca-weight-allocation
+                *
+                * Additionally, there is something called primary compression to
+                * worry about. Basically, if you have two primary elements that
+                * are more than one byte and both start with the same byte then
+                * the first byte is dropped on the second primary. Additionally
+                * either \x03 or \xFF may be added to mean that the next primary
+                * does not start with the first byte of the first primary.
+                *
+                * This shouldn't matter much, as the first primary is not
+                * changed, and that is what we are comparing against.
+                *
+                * tl;dr: This makes some assumptions about how icu implements
+                * collations. It seems incredibly unlikely these assumptions
+                * will change, but nonetheless they are assumptions.
+                */
+
+               $prev = false;
+               $duplicatePrefixes = [];
+               foreach ( $letterMap as $key => $value ) {
+                       // Remove terminator byte. Otherwise the prefix
+                       // comparison will get hung up on that.
+                       $trimmedKey = rtrim( $key, "\0" );
+                       if ( $prev === false || $prev === '' ) {
+                               $prev = $trimmedKey;
+                               // We don't yet have a collation element
+                               // to compare against, so continue.
+                               continue;
+                       }
+
+                       // Due to the fact the array is sorted, we only have
+                       // to compare with the element directly previous
+                       // to the current element (skipping expansions).
+                       // An element "X" will always sort directly
+                       // before "XZ" (Unless we have "XY", but we
+                       // do not update $prev in that case).
+                       if ( substr( $trimmedKey, 0, strlen( $prev ) ) === $prev ) {
+                               $duplicatePrefixes[] = $key;
+                               // If this is an expansion, we don't want to
+                               // compare the next element to this element,
+                               // but to what is currently $prev
+                               continue;
+                       }
+                       $prev = $trimmedKey;
+               }
+               foreach ( $duplicatePrefixes as $badKey ) {
+                       wfDebug( "Removing '{$letterMap[$badKey]}' from first letters.\n" );
+                       unset( $letterMap[$badKey] );
+                       // This code assumes that unsetting does not change sort order.
+               }
+               $data = [
+                       'chars' => array_values( $letterMap ),
+                       'keys' => array_keys( $letterMap ),
+                       'version' => self::FIRST_LETTER_VERSION,
+               ];
+
+               // Reduce memory usage before caching
+               unset( $letterMap );
+
+               // Save to cache
+               $this->firstLetterData = $data;
+               $cache->set( $cacheKey, $data, $cache::TTL_WEEK );
+               return $data;
+       }
+
+       /**
+        * @since 1.16.3
+        */
+       public function getLetterByIndex( $index ) {
+               if ( $this->firstLetterData === null ) {
+                       $this->getFirstLetterData();
+               }
+               return $this->firstLetterData['chars'][$index];
+       }
+
+       /**
+        * @since 1.16.3
+        */
+       public function getSortKeyByLetterIndex( $index ) {
+               if ( $this->firstLetterData === null ) {
+                       $this->getFirstLetterData();
+               }
+               return $this->firstLetterData['keys'][$index];
+       }
+
+       /**
+        * @since 1.16.3
+        */
+       public function getFirstLetterCount() {
+               if ( $this->firstLetterData === null ) {
+                       $this->getFirstLetterData();
+               }
+               return count( $this->firstLetterData['chars'] );
+       }
+
+       /**
+        * @since 1.16.3
+        */
+       public static function isCjk( $codepoint ) {
+               foreach ( self::$cjkBlocks as $block ) {
+                       if ( $codepoint >= $block[0] && $codepoint <= $block[1] ) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Return the version of ICU library used by PHP's intl extension,
+        * or false when the extension is not installed of the version
+        * can't be determined.
+        *
+        * The constant INTL_ICU_VERSION this function refers to isn't really
+        * documented. It is available since PHP 5.3.7 (see PHP bug 54561).
+        * This function will return false on older PHPs.
+        *
+        * @since 1.21
+        * @return string|bool
+        */
+       static function getICUVersion() {
+               return defined( 'INTL_ICU_VERSION' ) ? INTL_ICU_VERSION : false;
+       }
+
+       /**
+        * Return the version of Unicode appropriate for the version of ICU library
+        * currently in use, or false when it can't be determined.
+        *
+        * @since 1.21
+        * @return string|bool
+        */
+       static function getUnicodeVersionForICU() {
+               $icuVersion = IcuCollation::getICUVersion();
+               if ( !$icuVersion ) {
+                       return false;
+               }
+
+               $versionPrefix = substr( $icuVersion, 0, 3 );
+               // Source: http://site.icu-project.org/download
+               $map = [
+                       '50.' => '6.2',
+                       '49.' => '6.1',
+                       '4.8' => '6.0',
+                       '4.6' => '6.0',
+                       '4.4' => '5.2',
+                       '4.2' => '5.1',
+                       '4.0' => '5.1',
+                       '3.8' => '5.0',
+                       '3.6' => '5.0',
+                       '3.4' => '4.1',
+               ];
+
+               if ( isset( $map[$versionPrefix] ) ) {
+                       return $map[$versionPrefix];
+               } else {
+                       return false;
+               }
+       }
+}
diff --git a/includes/collation/IdentityCollation.php b/includes/collation/IdentityCollation.php
new file mode 100644 (file)
index 0000000..46e7f38
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Collation class that's essentially a no-op.
+ *
+ * Does sorting based on binary value of the string.
+ * Like how things were pre 1.17.
+ *
+ * @since 1.18
+ */
+class IdentityCollation extends Collation {
+
+       public function getSortKey( $string ) {
+               return $string;
+       }
+
+       public function getFirstLetter( $string ) {
+               global $wgContLang;
+               // Copied from UppercaseCollation.
+               // I'm kind of unclear on when this could happen...
+               if ( $string[0] == "\0" ) {
+                       $string = substr( $string, 1 );
+               }
+               return $wgContLang->firstChar( $string );
+       }
+}
diff --git a/includes/collation/UppercaseCollation.php b/includes/collation/UppercaseCollation.php
new file mode 100644 (file)
index 0000000..92a4c3b
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.16.3
+ *
+ * @file
+ */
+
+class UppercaseCollation extends Collation {
+
+       private $lang;
+
+       public function __construct() {
+               // Get a language object so that we can use the generic UTF-8 uppercase
+               // function there
+               $this->lang = Language::factory( 'en' );
+       }
+
+       public function getSortKey( $string ) {
+               return $this->lang->uc( $string );
+       }
+
+       public function getFirstLetter( $string ) {
+               if ( $string[0] == "\0" ) {
+                       $string = substr( $string, 1 );
+               }
+               return $this->lang->ucfirst( $this->lang->firstChar( $string ) );
+       }
+
+}
index d52103c..4b803d8 100644 (file)
@@ -42,36 +42,12 @@ class ConfigFactory {
        protected $configs = [];
 
        /**
-        * @var ConfigFactory
-        */
-       private static $self;
-
-       /**
+        * @deprecated since 1.27, use MediaWikiServices::getConfigFactory() instead.
+        *
         * @return ConfigFactory
         */
        public static function getDefaultInstance() {
-               if ( !self::$self ) {
-                       self::$self = new self;
-                       global $wgConfigRegistry;
-                       foreach ( $wgConfigRegistry as $name => $callback ) {
-                               self::$self->register( $name, $callback );
-                       }
-               }
-               return self::$self;
-       }
-
-       /**
-        * Destroy the default instance
-        * Should only be called inside unit tests
-        * @throws MWException
-        * @codeCoverageIgnore
-        */
-       public static function destroyDefaultInstance() {
-               if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
-                       throw new MWException( __METHOD__ . ' was called outside of unit tests' );
-               }
-
-               self::$self = null;
+               return \MediaWiki\MediaWikiServices::getInstance()->getConfigFactory();
        }
 
        /**
index 9ab11f3..7430caf 100644 (file)
@@ -55,7 +55,7 @@ class MWUnknownContentModelException extends MWException {
 
        /** @return string */
        public function getModelId() {
-               return $modelId;
+               return $this->modelId;
        }
 }
 
@@ -777,7 +777,7 @@ abstract class ContentHandler {
         * @return string
         */
        protected function getDiffEngineClass() {
-               return 'DifferenceEngine';
+               return DifferenceEngine::class;
        }
 
        /**
index f5e8783..ad40cd9 100644 (file)
@@ -32,7 +32,7 @@ class TextContentHandler extends ContentHandler {
 
        // @codingStandardsIgnoreStart bug 57585
        public function __construct( $modelId = CONTENT_MODEL_TEXT,
-               $formats = array( CONTENT_FORMAT_TEXT ) ) {
+               $formats = [ CONTENT_FORMAT_TEXT ] ) {
                parent::__construct( $modelId, $formats );
        }
        // @codingStandardsIgnoreEnd
index 1e27205..13be911 100644 (file)
@@ -34,6 +34,8 @@ abstract class DatabaseMysqlBase extends Database {
        protected $lastKnownSlavePos;
        /** @var string Method to detect slave lag */
        protected $lagDetectionMethod;
+       /** @var array Method to detect slave lag */
+       protected $lagDetectionOptions = [];
 
        /** @var string|null */
        private $serverVersion = null;
@@ -44,6 +46,10 @@ abstract class DatabaseMysqlBase extends Database {
         *                          pt-heartbeat assumes the table is at heartbeat.heartbeat
         *                          and uses UTC timestamps in the heartbeat.ts column.
         *                          (https://www.percona.com/doc/percona-toolkit/2.2/pt-heartbeat.html)
+        *   - lagDetectionOptions : if using pt-heartbeat, this can be set to an array map to change
+        *                           the default behavior. Normally, the heartbeat row with the server
+        *                           ID of this server's master will be used. Set the "conds" field to
+        *                           override the query conditions, e.g. ['shard' => 's1'].
         * @param array $params
         */
        function __construct( array $params ) {
@@ -52,6 +58,9 @@ abstract class DatabaseMysqlBase extends Database {
                $this->lagDetectionMethod = isset( $params['lagDetectionMethod'] )
                        ? $params['lagDetectionMethod']
                        : 'Seconds_Behind_Master';
+               $this->lagDetectionOptions = isset( $params['lagDetectionOptions'] )
+                       ? $params['lagDetectionOptions']
+                       : [];
        }
 
        /**
@@ -652,19 +661,30 @@ abstract class DatabaseMysqlBase extends Database {
         * @return bool|float
         */
        protected function getLagFromPtHeartbeat() {
-               $masterInfo = $this->getMasterServerInfo();
-               if ( !$masterInfo ) {
-                       wfLogDBError(
-                               "Unable to query master of {db_server} for server ID",
-                               $this->getLogContext( [
-                                       'method' => __METHOD__
-                               ] )
-                       );
+               $options = $this->lagDetectionOptions;
+
+               if ( isset( $options['conds'] ) ) {
+                       // Best method for multi-DC setups: use logical channel names
+                       $data = $this->getHeartbeatData( $options['conds'] );
+               } else {
+                       // Standard method: use master server ID (works with stock pt-heartbeat)
+                       $masterInfo = $this->getMasterServerInfo();
+                       if ( !$masterInfo ) {
+                               wfLogDBError(
+                                       "Unable to query master of {db_server} for server ID",
+                                       $this->getLogContext( [
+                                               'method' => __METHOD__
+                                       ] )
+                               );
+
+                               return false; // could not get master server ID
+                       }
 
-                       return false; // could not get master server ID
+                       $conds = [ 'server_id' => intval( $masterInfo['serverId'] ) ];
+                       $data = $this->getHeartbeatData( $conds );
                }
 
-               list( $time, $nowUnix ) = $this->getHeartbeatData( $masterInfo['serverId'] );
+               list( $time, $nowUnix ) = $data;
                if ( $time !== null ) {
                        // @time is in ISO format like "2015-09-25T16:48:10.000510"
                        $dateTime = new DateTime( $time, new DateTimeZone( 'UTC' ) );
@@ -722,17 +742,17 @@ abstract class DatabaseMysqlBase extends Database {
        }
 
        /**
-        * @param string $masterId Server ID
-        * @return array (heartbeat `ts` column value or null, UNIX timestamp)
+        * @param array $conds WHERE clause conditions to find a row
+        * @return array (heartbeat `ts` column value or null, UNIX timestamp) for the newest beat
         * @see https://www.percona.com/doc/percona-toolkit/2.1/pt-heartbeat.html
         */
-       protected function getHeartbeatData( $masterId ) {
-               // Get the status row for this master; use the oldest for sanity in case the master
-               // has entries listed under different server IDs (which should really not happen).
-               // Note: this would use "MAX(TIMESTAMPDIFF(MICROSECOND,ts,UTC_TIMESTAMP(6)))" but the
+       protected function getHeartbeatData( array $conds ) {
+               $whereSQL = $this->makeList( $conds, LIST_AND );
+               // Use ORDER BY for channel based queries since that field might not be UNIQUE.
+               // Note: this would use "TIMESTAMPDIFF(MICROSECOND,ts,UTC_TIMESTAMP(6))" but the
                // percision field is not supported in MySQL <= 5.5.
                $res = $this->query(
-                       "SELECT ts FROM heartbeat.heartbeat WHERE server_id=" . intval( $masterId )
+                       "SELECT ts FROM heartbeat.heartbeat WHERE $whereSQL ORDER BY ts DESC LIMIT 1"
                );
                $row = $res ? $res->fetchObject() : false;
 
index 8ca2362..d45805a 100644 (file)
@@ -322,7 +322,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
         * @return string
         */
        public function __toString() {
-               if ( $this->mConn instanceof Mysqli ) {
+               if ( $this->mConn instanceof mysqli ) {
                        return (string)$this->mConn->thread_id;
                } else {
                        // mConn might be false or something.
index d428710..839d6a0 100644 (file)
@@ -392,9 +392,7 @@ class DatabasePostgres extends Database {
        }
 
        public function doQuery( $sql ) {
-               if ( function_exists( 'mb_convert_encoding' ) ) {
-                       $sql = mb_convert_encoding( $sql, 'UTF-8' );
-               }
+               $sql = mb_convert_encoding( $sql, 'UTF-8' );
                // Clear previously left over PQresult
                while ( $res = pg_get_result( $this->mConn ) ) {
                        pg_free_result( $res );
@@ -840,7 +838,7 @@ __INDEXATTR__;
                                        $tempres = (bool)$this->query( $tempsql, $fname, $savepoint );
 
                                        if ( $savepoint ) {
-                                               $bar = pg_last_error();
+                                               $bar = pg_result_error( $this->mLastResult );
                                                if ( $bar != false ) {
                                                        $savepoint->rollback();
                                                } else {
@@ -865,7 +863,7 @@ __INDEXATTR__;
                        $sql .= '(' . $this->makeList( $args ) . ')';
                        $res = (bool)$this->query( $sql, $fname, $savepoint );
                        if ( $savepoint ) {
-                               $bar = pg_last_error();
+                               $bar = pg_result_error( $this->mLastResult );
                                if ( $bar != false ) {
                                        $savepoint->rollback();
                                } else {
@@ -948,7 +946,7 @@ __INDEXATTR__;
 
                $res = (bool)$this->query( $sql, $fname, $savepoint );
                if ( $savepoint ) {
-                       $bar = pg_last_error();
+                       $bar = pg_result_error( $this->mLastResult );
                        if ( $bar != false ) {
                                $savepoint->rollback();
                        } else {
index 997efa6..741999c 100644 (file)
@@ -161,19 +161,6 @@ class LoadBalancer {
                return wfSetVar( $this->mParentInfo, $x );
        }
 
-       /**
-        * Given an array of non-normalised probabilities, this function will select
-        * an element and return the appropriate key
-        *
-        * @deprecated since 1.21, use ArrayUtils::pickRandom()
-        *
-        * @param array $weights
-        * @return bool|int|string
-        */
-       public function pickRandom( array $weights ) {
-               return ArrayUtils::pickRandom( $weights );
-       }
-
        /**
         * @param array $loads
         * @param bool|string $wiki Wiki to get non-lagged for
index 13b80be..0ad9b15 100644 (file)
@@ -99,7 +99,7 @@ class LineFormatter extends MonologLineFormatter {
         * @param Exception $e
         * @return string
         */
-       protected function normalizeException( Exception $e ) {
+       protected function normalizeException( $e ) {
                return $this->normalizeExceptionArray( $this->exceptionAsArray( $e ) );
        }
 
index 7f60f2e..ad939a0 100644 (file)
@@ -21,7 +21,8 @@
 namespace MediaWiki\Logger\Monolog;
 
 /**
- * Injects `wfHostname()`, `wfWikiID()` and `$wgVersion` in all records.
+ * Annotate log records with request-global metadata, such as the hostname,
+ * wiki / request ID, and MediaWiki version.
  *
  * @since 1.25
  * @author Bryan Davis <bd808@wikimedia.org>
@@ -41,6 +42,7 @@ class WikiProcessor {
                                'host' => wfHostname(),
                                'wiki' => wfWikiID(),
                                'mwversion' => $wgVersion,
+                               'reqId' => \WebRequest::getRequestId(),
                        ]
                );
                return $record;
index 1cf3918..1508cf1 100644 (file)
@@ -232,7 +232,7 @@ class DifferenceEngine extends ContextSource {
                        ->params( $this->getLanguage()->listToText( $missing ) )
                        ->numParams( count( $missing ) )
                        ->parseAsBlock();
-               $out->addHtml( $msg );
+               $out->addHTML( $msg );
        }
 
        public function showDiffPage( $diffOnly = false ) {
@@ -573,7 +573,7 @@ class DifferenceEngine extends ContextSource {
                <h2 class='diff-currentversion-title'>{$revHeader}</h2>\n" );
                # Page content may be handled by a hooked call instead...
                # @codingStandardsIgnoreStart Ignoring long lines.
-               if ( Hooks::run( 'ArticleContentOnDiff', array( $this, $out ) ) ) {
+               if ( Hooks::run( 'ArticleContentOnDiff', [ $this, $out ] ) ) {
                        $this->loadNewText();
                        $out->setRevisionId( $this->mNewid );
                        $out->setRevisionTimestamp( $this->mNewRev->getTimestamp() );
@@ -584,7 +584,7 @@ class DifferenceEngine extends ContextSource {
                                // This needs to be synchronised with Article::showCssOrJsPage(), which sucks
                                // Give hooks a chance to customise the output
                                // @todo standardize this crap into one function
-                               if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
+                               if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
                                        // NOTE: deprecated hook, B/C only
                                        // use the content object's own rendering
                                        $cnt = $this->mNewRev->getContent();
@@ -593,9 +593,9 @@ class DifferenceEngine extends ContextSource {
                                                $out->addParserOutputContent( $po );
                                        }
                                }
-                       } elseif ( !Hooks::run( 'ArticleContentViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
+                       } elseif ( !Hooks::run( 'ArticleContentViewCustom', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
                                // Handled by extension
-                       } elseif ( !ContentHandler::runLegacyHooks( 'ArticleViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) {
+                       } elseif ( !ContentHandler::runLegacyHooks( 'ArticleViewCustom', [ $this->mNewContent, $this->mNewPage, $out ] ) ) {
                                // NOTE: deprecated hook, B/C only
                                // Handled by extension
                        } else {
@@ -715,7 +715,7 @@ class DifferenceEngine extends ContextSource {
                }
                // Short-circuit
                if ( $this->mOldRev === false || ( $this->mOldRev && $this->mNewRev
-                       && $this->mOldRev->getID() == $this->mNewRev->getID() )
+                       && $this->mOldRev->getId() == $this->mNewRev->getId() )
                ) {
                        return '';
                }
@@ -846,8 +846,13 @@ class DifferenceEngine extends ContextSource {
 
                $result = $this->textDiff( $otext, $ntext );
 
-               $time = microtime( true ) - $time;
+               $time = intval( ( microtime( true ) - $time ) * 1000 );
                $this->getStats()->timing( 'diff_time', $time );
+               // Log requests slower than 99th percentile
+               if ( $time > 100 && $this->mOldPage && $this->mNewPage ) {
+                       wfDebugLog( 'diff',
+                               "$time ms diff: {$this->mOldid} -> {$this->mNewid} {$this->mNewPage}" );
+               }
 
                return $result;
        }
@@ -1055,12 +1060,12 @@ class DifferenceEngine extends ContextSource {
                $title = $rev->getTitle();
 
                $header = Linker::linkKnown( $title, $header, [],
-                       [ 'oldid' => $rev->getID() ] );
+                       [ 'oldid' => $rev->getId() ] );
 
                if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) {
                        $editQuery = [ 'action' => 'edit' ];
                        if ( !$rev->isCurrent() ) {
-                               $editQuery['oldid'] = $rev->getID();
+                               $editQuery['oldid'] = $rev->getId();
                        }
 
                        $key = $title->quickUserCan( 'edit', $user ) ? 'editold' : 'viewsourceold';
@@ -1147,19 +1152,6 @@ class DifferenceEngine extends ContextSource {
                return $header . $diff . "</table>";
        }
 
-       /**
-        * Use specified text instead of loading from the database
-        * @deprecated since 1.21, use setContent() instead.
-        */
-       public function setText( $oldText, $newText ) {
-               ContentHandler::deprecated( __METHOD__, "1.21" );
-
-               $oldContent = ContentHandler::makeContent( $oldText, $this->getTitle() );
-               $newContent = ContentHandler::makeContent( $newText, $this->getTitle() );
-
-               $this->setContent( $oldContent, $newContent );
-       }
-
        /**
         * Use specified text instead of loading from the database
         * @param Content $oldContent
index e1d7e6c..bebd915 100644 (file)
@@ -141,7 +141,7 @@ class MWException extends Exception {
                        nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) .
                        "</p>\n";
                } else {
-                       $logId = MWExceptionHandler::getLogId( $this );
+                       $logId = WebRequest::getRequestId();
                        $type = get_class( $this );
                        return "<div class=\"errorbox\">" .
                        '[' . $logId . '] ' .
index b71f92c..63adc29 100644 (file)
@@ -445,14 +445,13 @@ TXT;
         * $wgShowExceptionDetails is set to false), to the entry in the debug log.
         *
         * @since 1.22
+        * @deprecated since 1.27: Exception IDs are synonymous with request IDs.
         * @param Exception|Throwable $e
         * @return string
         */
        public static function getLogId( $e ) {
-               if ( !isset( $e->_mwLogId ) ) {
-                       $e->_mwLogId = wfRandomString( 8 );
-               }
-               return $e->_mwLogId;
+               wfDeprecated( __METHOD__, '1.27' );
+               return WebRequest::getRequestId();
        }
 
        /**
@@ -478,7 +477,7 @@ TXT;
         * @return string
         */
        public static function getLogMessage( $e ) {
-               $id = self::getLogId( $e );
+               $id = WebRequest::getRequestId();
                $type = get_class( $e );
                $file = $e->getFile();
                $line = $e->getLine();
@@ -489,9 +488,9 @@ TXT;
        }
 
        public static function getPublicLogMessage( Exception $e ) {
-               $logId = self::getLogId( $e );
+               $reqId = WebRequest::getRequestId();
                $type = get_class( $e );
-               return '[' . $logId . '] '
+               return '[' . $reqId . '] '
                        . gmdate( 'Y-m-d H:i:s' ) . ': '
                        . 'Fatal exception of type ' . $type;
        }
@@ -509,7 +508,7 @@ TXT;
        public static function getLogContext( $e ) {
                return [
                        'exception' => $e,
-                       'exception_id' => static::getLogId( $e ),
+                       'exception_id' => WebRequest::getRequestId(),
                ];
        }
 
@@ -527,7 +526,7 @@ TXT;
        public static function getStructuredExceptionData( $e ) {
                global $wgLogExceptionBacktrace;
                $data = [
-                       'id' => self::getLogId( $e ),
+                       'id' => WebRequest::getRequestId(),
                        'type' => get_class( $e ),
                        'file' => $e->getFile(),
                        'line' => $e->getLine(),
index 6ad2e37..bd0b120 100644 (file)
 class PermissionsError extends ErrorPageError {
        public $permission, $errors;
 
+       /**
+        * @param string $permission A permission name.
+        * @param string[] $errors Error message keys
+        */
        public function __construct( $permission, $errors = [] ) {
                global $wgLang;
 
index a3ec66c..42168d7 100644 (file)
@@ -405,7 +405,7 @@ class XmlDumpWriter {
                        "      " . $comment . "\n" .
                        "      " . Xml::element( 'filename', null, $file->getName() ) . "\n" .
                        $archiveName .
-                       "      " . Xml::element( 'src', null, $file->getCanonicalURL() ) . "\n" .
+                       "      " . Xml::element( 'src', null, $file->getCanonicalUrl() ) . "\n" .
                        "      " . Xml::element( 'size', null, $file->getSize() ) . "\n" .
                        "      " . Xml::element( 'sha1base36', null, $file->getSha1() ) . "\n" .
                        "      " . Xml::element( 'rel', null, $file->getRel() ) . "\n" .
index 317346e..0f7e4b5 100644 (file)
@@ -153,7 +153,7 @@ class SwiftFileBackend extends FileBackendStore {
        }
 
        protected function resolveContainerPath( $container, $relStoragePath ) {
-               if ( !mb_check_encoding( $relStoragePath, 'UTF-8' ) ) { // mb_string required by CF
+               if ( !mb_check_encoding( $relStoragePath, 'UTF-8' ) ) {
                        return null; // not UTF-8, makes it hard to use CF and the swift HTTP API
                } elseif ( strlen( urlencode( $relStoragePath ) ) > 1024 ) {
                        return null; // too long for Swift
@@ -802,7 +802,7 @@ class SwiftFileBackend extends FileBackendStore {
        protected function doDirectoryExists( $fullCont, $dir, array $params ) {
                $prefix = ( $dir == '' ) ? null : "{$dir}/";
                $status = $this->objectListing( $fullCont, 'names', 1, null, $prefix );
-               if ( $status->isOk() ) {
+               if ( $status->isOK() ) {
                        return ( count( $status->value ) ) > 0;
                }
 
@@ -854,7 +854,7 @@ class SwiftFileBackend extends FileBackendStore {
                // Non-recursive: only list dirs right under $dir
                if ( !empty( $params['topOnly'] ) ) {
                        $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix, '/' );
-                       if ( !$status->isOk() ) {
+                       if ( !$status->isOK() ) {
                                throw new FileBackendError( "Iterator page I/O error: {$status->getMessage()}" );
                        }
                        $objects = $status->value;
@@ -873,7 +873,7 @@ class SwiftFileBackend extends FileBackendStore {
                        $lastDir = $getParentDir( $after ); // must be first page
                        $status = $this->objectListing( $fullCont, 'names', $limit, $after, $prefix );
 
-                       if ( !$status->isOk() ) {
+                       if ( !$status->isOK() ) {
                                throw new FileBackendError( "Iterator page I/O error: {$status->getMessage()}" );
                        }
 
@@ -949,7 +949,7 @@ class SwiftFileBackend extends FileBackendStore {
                }
 
                // Reformat this list into a list of (name, stat array or null) entries
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        throw new FileBackendError( "Iterator page I/O error: {$status->getMessage()}" );
                }
 
index f3c2abf..15821ea 100644 (file)
@@ -1158,7 +1158,7 @@ class FileRepo {
         * Options to $options include:
         *   - headers : name/value map of HTTP headers to use in response to GET/HEAD requests
         *
-        * @param string $srcPath The source file system path, storage path, or URL
+        * @param string|FSFile $src The source file system path, storage path, or URL
         * @param string $dstRel The destination relative path
         * @param string $archiveRel The relative path where the existing file is to
         *   be archived, if there is one. Relative to the public zone root.
@@ -1168,12 +1168,12 @@ class FileRepo {
         * @return FileRepoStatus
         */
        public function publish(
-               $srcPath, $dstRel, $archiveRel, $flags = 0, array $options = []
+               $src, $dstRel, $archiveRel, $flags = 0, array $options = []
        ) {
                $this->assertWritableRepo(); // fail out if read-only
 
                $status = $this->publishBatch(
-                       [ [ $srcPath, $dstRel, $archiveRel, $options ] ], $flags );
+                       [ [ $src, $dstRel, $archiveRel, $options ] ], $flags );
                if ( $status->successCount == 0 ) {
                        $status->ok = false;
                }
@@ -1212,7 +1212,9 @@ class FileRepo {
                $sourceFSFilesToDelete = []; // cleanup for disk source files
                // Validate each triplet and get the store operation...
                foreach ( $ntuples as $ntuple ) {
-                       list( $srcPath, $dstRel, $archiveRel ) = $ntuple;
+                       list( $src, $dstRel, $archiveRel ) = $ntuple;
+                       $srcPath = ( $src instanceof FSFile ) ? $src->getPath() : $src;
+
                        $options = isset( $ntuple[3] ) ? $ntuple[3] : [];
                        // Resolve source to a storage path if virtual
                        $srcPath = $this->resolveToStoragePath( $srcPath );
@@ -1275,7 +1277,7 @@ class FileRepo {
                        } else { // FS source path
                                $operations[] = [
                                        'op' => 'store',
-                                       'src' => $srcPath,
+                                       'src' => $src, // prefer FSFile objects
                                        'dst' => $dstPath,
                                        'overwrite' => true, // replace current
                                        'headers' => $headers
@@ -1904,7 +1906,7 @@ class FileRepo {
 
        /**
         * Returns whether or not storage is SHA-1 based
-        * @return boolean
+        * @return bool
         */
        public function hasSha1Storage() {
                return $this->hasSha1Storage;
@@ -1912,7 +1914,7 @@ class FileRepo {
 
        /**
         * Returns whether or not repo supports having originals SHA-1s in the thumb URLs
-        * @return boolean
+        * @return bool
         */
        public function supportsSha1URLs() {
                return $this->supportsSha1URLs;
index 5e9a4a9..8248699 100644 (file)
@@ -226,7 +226,8 @@ class LocalRepo extends FileRepo {
                                return ( $row && $row->rd_namespace == NS_FILE )
                                        ? Title::makeTitle( $row->rd_namespace, $row->rd_title )->getDBkey()
                                        : ''; // negative cache
-                       }
+                       },
+                       [ 'pcTTL' => 30 ]
                );
 
                // @note: also checks " " for b/c
@@ -532,7 +533,7 @@ class LocalRepo extends FileRepo {
        }
 
        public function publish(
-               $srcPath,
+               $src,
                $dstRel,
                $archiveRel,
                $flags = 0,
index 6a1bb92..7e00793 100644 (file)
@@ -393,10 +393,10 @@ abstract class File implements IDBAccessObject {
                                wfDebug( __METHOD__ . ': supposed to render ' . $this->getName() .
                                        ' (' . $this->getMimeType() . "), but can't!\n" );
 
-                               return $this->getURL(); # hm... return NULL?
+                               return $this->getUrl(); # hm... return NULL?
                        }
                } else {
-                       return $this->getURL();
+                       return $this->getUrl();
                }
        }
 
@@ -1802,7 +1802,7 @@ abstract class File implements IDBAccessObject {
         * Options to $options include:
         *   - headers : name/value map of HTTP headers to use in response to GET/HEAD requests
         *
-        * @param string $srcPath Local filesystem path to the source image
+        * @param string|FSFile $src Local filesystem path to the source image
         * @param int $flags A bitwise combination of:
         *   File::DELETE_SOURCE    Delete the source file, i.e. move rather than copy
         * @param array $options Optional additional parameters
@@ -1812,7 +1812,7 @@ abstract class File implements IDBAccessObject {
         * STUB
         * Overridden by LocalFile
         */
-       function publish( $srcPath, $flags = 0, array $options = [] ) {
+       function publish( $src, $flags = 0, array $options = [] ) {
                $this->readOnlyError();
        }
 
index c97f38f..9677f5d 100644 (file)
@@ -242,7 +242,7 @@ class LocalFile extends File {
         * Try to load file metadata from memcached. Returns true on success.
         * @return bool
         */
-       function loadFromCache() {
+       private function loadFromCache() {
                $this->dataLoaded = false;
                $this->extraDataLoaded = false;
                $key = $this->getCacheKey();
@@ -279,7 +279,7 @@ class LocalFile extends File {
        /**
         * Save the file metadata to memcached
         */
-       function saveToCache() {
+       private function saveToCache() {
                $this->load();
 
                $key = $this->getCacheKey();
@@ -915,6 +915,7 @@ class LocalFile extends File {
                // Purge any custom thumbnail caches
                Hooks::run( 'LocalFilePurgeThumbnails', [ $this, $archiveName ] );
 
+               // Delete thumbnails
                $dir = array_shift( $files );
                $this->purgeThumbList( $dir, $files );
 
@@ -931,7 +932,6 @@ class LocalFile extends File {
         * @param array $options
         */
        public function purgeThumbnails( $options = [] ) {
-               // Delete thumbnails
                $files = $this->getThumbnails();
                // Always purge all files from CDN regardless of handler filters
                $urls = [];
@@ -951,6 +951,7 @@ class LocalFile extends File {
                // Purge any custom thumbnail caches
                Hooks::run( 'LocalFilePurgeThumbnails', [ $this, false ] );
 
+               // Delete thumbnails
                $dir = array_shift( $files );
                $this->purgeThumbList( $dir, $files );
 
@@ -1108,7 +1109,7 @@ class LocalFile extends File {
 
        /**
         * Upload a file and record it in the DB
-        * @param string $srcPath Source storage path, virtual URL, or filesystem path
+        * @param string|FSFile $src Source storage path, virtual URL, or filesystem path
         * @param string $comment Upload description
         * @param string $pageText Text to use for the new description page,
         *   if a new description page is created
@@ -1124,7 +1125,7 @@ class LocalFile extends File {
         * @return FileRepoStatus On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
         */
-       function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false,
+       function upload( $src, $comment, $pageText, $flags = 0, $props = false,
                $timestamp = false, $user = null, $tags = []
        ) {
                global $wgContLang;
@@ -1133,6 +1134,7 @@ class LocalFile extends File {
                        return $this->readOnlyFatalStatus();
                }
 
+               $srcPath = ( $src instanceof FSFile ) ? $src->getPath() : $src;
                if ( !$props ) {
                        if ( $this->repo->isVirtualUrl( $srcPath )
                                || FileBackend::isStoragePath( $srcPath )
@@ -1158,7 +1160,7 @@ class LocalFile extends File {
                // non-nicely (dangling multi-byte chars, non-truncated version in cache).
                $comment = $wgContLang->truncate( $comment, 255 );
                $this->lock(); // begin
-               $status = $this->publish( $srcPath, $flags, $options );
+               $status = $this->publish( $src, $flags, $options );
 
                if ( $status->successCount >= 2 ) {
                        // There will be a copy+(one of move,copy,store).
@@ -1484,6 +1486,9 @@ class LocalFile extends File {
                                $logEntry->setTags( $tags );
                        }
 
+                       # Uploads can be patrolled
+                       $logEntry->setIsPatrollable( true );
+
                        # Now that the log entry is up-to-date, make an RC entry.
                        $logEntry->publish( $logId );
 
@@ -1523,15 +1528,15 @@ class LocalFile extends File {
         * The archive name should be passed through to recordUpload for database
         * registration.
         *
-        * @param string $srcPath Local filesystem path or virtual URL to the source image
+        * @param string|FSFile $src Local filesystem path or virtual URL to the source image
         * @param int $flags A bitwise combination of:
         *     File::DELETE_SOURCE    Delete the source file, i.e. move rather than copy
         * @param array $options Optional additional parameters
         * @return FileRepoStatus On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
         */
-       function publish( $srcPath, $flags = 0, array $options = [] ) {
-               return $this->publishTo( $srcPath, $this->getRel(), $flags, $options );
+       function publish( $src, $flags = 0, array $options = [] ) {
+               return $this->publishTo( $src, $this->getRel(), $flags, $options );
        }
 
        /**
@@ -1541,7 +1546,7 @@ class LocalFile extends File {
         * The archive name should be passed through to recordUpload for database
         * registration.
         *
-        * @param string $srcPath Local filesystem path or virtual URL to the source image
+        * @param string|FSFile $src Local filesystem path or virtual URL to the source image
         * @param string $dstRel Target relative path
         * @param int $flags A bitwise combination of:
         *     File::DELETE_SOURCE    Delete the source file, i.e. move rather than copy
@@ -1549,7 +1554,9 @@ class LocalFile extends File {
         * @return FileRepoStatus On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
         */
-       function publishTo( $srcPath, $dstRel, $flags = 0, array $options = [] ) {
+       function publishTo( $src, $dstRel, $flags = 0, array $options = [] ) {
+               $srcPath = ( $src instanceof FSFile ) ? $src->getPath() : $src;
+
                $repo = $this->getRepo();
                if ( $repo->getReadOnlyReason() !== false ) {
                        return $this->readOnlyFatalStatus();
@@ -1563,9 +1570,9 @@ class LocalFile extends File {
                if ( $repo->hasSha1Storage() ) {
                        $sha1 = $repo->isVirtualUrl( $srcPath )
                                ? $repo->getFileSha1( $srcPath )
-                               : File::sha1Base36( $srcPath );
+                               : FSFile::getSha1Base36FromPath( $srcPath );
                        $dst = $repo->getBackend()->getPathForSHA1( $sha1 );
-                       $status = $repo->quickImport( $srcPath, $dst );
+                       $status = $repo->quickImport( $src, $dst );
                        if ( $flags & File::DELETE_SOURCE ) {
                                unlink( $srcPath );
                        }
@@ -2767,7 +2774,7 @@ class LocalFileMoveBatch {
                $this->newName = $this->file->repo->getNameFromTitle( $this->target );
                $this->oldRel = $this->oldHash . $this->oldName;
                $this->newRel = $this->newHash . $this->newName;
-               $this->db = $file->getRepo()->getMasterDb();
+               $this->db = $file->getRepo()->getMasterDB();
        }
 
        /**
index f76b38b..31e62ec 100644 (file)
@@ -332,16 +332,13 @@ class OldLocalFile extends LocalFile {
         * @param string $timestamp
         * @param string $comment
         * @param User $user
-        * @param int $flags
         * @return FileRepoStatus
         */
-       function uploadOld( $srcPath, $archiveName, $timestamp, $comment, $user, $flags = 0 ) {
+       function uploadOld( $srcPath, $archiveName, $timestamp, $comment, $user ) {
                $this->lock();
 
                $dstRel = 'archive/' . $this->getHashPath() . $archiveName;
-               $status = $this->publishTo( $srcPath, $dstRel,
-                       $flags & File::DELETE_SOURCE ? FileRepo::DELETE_SOURCE : 0
-               );
+               $status = $this->publishTo( $srcPath, $dstRel );
 
                if ( $status->isGood() ) {
                        if ( !$this->recordOldUpload( $srcPath, $archiveName, $timestamp, $comment, $user ) ) {
index 1f077a4..76a88d5 100644 (file)
@@ -53,7 +53,7 @@ class HTMLAutoCompleteSelectField extends HTMLTextField {
                $this->getOptions();
                if ( $this->mOptions && !in_array( 'other', $this->mOptions, true ) ) {
                        if ( isset( $params['other-message'] ) ) {
-                               $msg = wfMessage( $params['other-message'] )->text();
+                               $msg = $this->getMessage( $params['other-message'] )->text();
                        } elseif ( isset( $params['other'] ) ) {
                                $msg = $params['other'];
                        } else {
@@ -101,11 +101,11 @@ class HTMLAutoCompleteSelectField extends HTMLTextField {
        }
 
        // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
-       public function getAttributes( array $list, array $mappings = null ) {
+       public function getAttributes( array $list ) {
                $attribs = [
                        'type' => 'text',
                        'data-autocomplete' => FormatJson::encode( array_keys( $this->autocomplete ) ),
-               ] + parent::getAttributes( $list, $mappings );
+               ] + parent::getAttributes( $list );
 
                if ( $this->getOptions() ) {
                        $attribs['data-hide-if'] = FormatJson::encode(
index 211089f..64fe7ed 100644 (file)
@@ -6,7 +6,7 @@
  * wish to add a submit button to a form.
  *
  * Additional recognized configuration parameters include:
- * - flags: OOUI flags for the button, see OOUI\\FlaggedElement
+ * - flags: OOUI flags for the button, see OOUI\FlaggedElement
  * - buttonlabel-message: Message to use for the button display text, instead
  *   of the value from 'default'. Overrides 'buttonlabel' and 'buttonlabel-raw'.
  * - buttonlabel: Text to display for the button display text, instead
@@ -35,16 +35,7 @@ class HTMLButtonField extends HTMLFormField {
 
                # Generate the label from a message, if possible
                if ( isset( $info['buttonlabel-message'] ) ) {
-                       $msgInfo = $info['buttonlabel-message'];
-
-                       if ( is_array( $msgInfo ) ) {
-                               $msg = array_shift( $msgInfo );
-                       } else {
-                               $msg = $msgInfo;
-                               $msgInfo = [];
-                       }
-
-                       $this->buttonLabel = $this->msg( $msg, $msgInfo )->parse();
+                       $this->buttonLabel = $this->getMessage( $info['buttonlabel-message'] )->parse();
                } elseif ( isset( $info['buttonlabel'] ) ) {
                        if ( $info['buttonlabel'] === '&#160;' ) {
                                // Apparently some things set &nbsp directly and in an odd format
@@ -56,6 +47,8 @@ class HTMLButtonField extends HTMLFormField {
                        $this->buttonLabel = $info['buttonlabel-raw'];
                }
 
+               $this->setShowEmptyLabel( false );
+
                parent::__construct( $info );
        }
 
@@ -77,13 +70,14 @@ class HTMLButtonField extends HTMLFormField {
                        'id' => $this->mID,
                        'type' => $this->buttonType,
                        'name' => $this->mName,
-                       'value' => $value,
+                       'value' => $this->getDefault(),
                ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
 
                if ( $this->isBadIE() ) {
                        return Html::element( 'input', $attr );
                } else {
-                       return Html::rawElement( 'button', $attr, $this->buttonLabel ?: htmlspecialchars( $value ) );
+                       return Html::rawElement( 'button', $attr,
+                               $this->buttonLabel ?: htmlspecialchars( $this->getDefault() ) );
                }
        }
 
@@ -95,16 +89,18 @@ class HTMLButtonField extends HTMLFormField {
        public function getInputOOUI( $value ) {
                return new OOUI\ButtonInputWidget( [
                        'name' => $this->mName,
-                       'value' => $value,
+                       'value' => $this->getDefault(),
                        'label' => !$this->isBadIE() && $this->buttonLabel
                                ? new OOUI\HtmlSnippet( $this->buttonLabel )
-                               : $value,
+                               : $this->getDefault(),
                        'type' => $this->buttonType,
                        'classes' => [ 'mw-htmlform-submit', $this->mClass ],
                        'id' => $this->mID,
                        'flags' => $this->mFlags,
                        'useInputTag' => $this->isBadIE(),
-               ] + $this->getAttributes( [ 'disabled', 'tabindex' ], [ 'tabindex' => 'tabIndex' ] ) );
+               ] + OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               ) );
        }
 
        protected function needsLabel() {
index 13f30c2..a59b15e 100644 (file)
@@ -56,9 +56,8 @@ class HTMLCheckField extends HTMLFormField {
                $attr['id'] = $this->mID;
                $attr['name'] = $this->mName;
 
-               $attr += $this->getAttributes(
-                       [ 'disabled', 'tabindex' ],
-                       [ 'tabindex' => 'tabIndex' ]
+               $attr += OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
                );
 
                if ( $this->mClass !== '' ) {
index 6a4bec8..9f67233 100644 (file)
@@ -85,13 +85,7 @@ class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
                $rows = $this->mParams['rows'];
                $columns = $this->mParams['columns'];
 
-               $mappings = [];
-
-               if ( $this->mParent instanceof OOUIHTMLForm ) {
-                       $mappings['tabindex'] = 'tabIndex';
-               }
-
-               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ], $mappings );
+               $attribs = $this->getAttributes( [ 'disabled', 'tabindex' ] );
 
                // Build the column headers
                $headerContents = Html::rawElement( 'td', [], '&#160;' );
@@ -156,8 +150,9 @@ class HTMLCheckMatrix extends HTMLFormField implements HTMLNestedFilterable {
                        return new OOUI\CheckboxInputWidget( [
                                'name' => "{$this->mName}[]",
                                'selected' => $checked,
-                               'value' => $attribs['value'],
-                       ] + $attribs );
+                       ] + OOUI\Element::configFromHtmlAttributes(
+                               $attribs
+                       ) );
                } else {
                        $checkbox = Xml::check( "{$this->mName}[]", $checked, $attribs );
                        if ( $this->mParent->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
index a0f248f..778aedb 100644 (file)
  */
 class HTMLComboboxField extends HTMLTextField {
        // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
-       public function getAttributes( array $list, array $mappings = null ) {
+       public function getAttributes( array $list ) {
                $attribs = [
                        'type' => 'text',
                        'list' => $this->mName . '-datalist',
-               ] + parent::getAttributes( $list, $mappings );
+               ] + parent::getAttributes( $list );
 
                return $attribs;
        }
@@ -36,7 +36,9 @@ class HTMLComboboxField extends HTMLTextField {
        function getInputOOUI( $value ) {
                $disabled = false;
                $allowedParams = [ 'tabindex' ];
-               $attribs = $this->getAttributes( $allowedParams, [ 'tabindex' => 'tabIndex' ] );
+               $attribs = OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
 
                if ( $this->mClass !== '' ) {
                        $attribs['classes'] = [ $this->mClass ];
index 77924ef..1b5d1fb 100644 (file)
@@ -39,7 +39,7 @@ class HTMLEditTools extends HTMLFormField {
                if ( empty( $this->mParams['message'] ) ) {
                        $msg = $this->msg( 'edittools' );
                } else {
-                       $msg = $this->msg( $this->mParams['message'] );
+                       $msg = $this->getMessage( $this->mParams['message'] );
                        if ( $msg->isDisabled() ) {
                                $msg = $this->msg( 'edittools' );
                        }
index ba43244..d50fac0 100644 (file)
  *                             Some field types support multi-level arrays.
  *    'options-messages'    -- associative array mapping message keys to values.
  *                             Some field types support multi-level arrays.
- *    'options-message'     -- message key to be parsed to extract the list of
+ *    'options-message'     -- message key or object to be parsed to extract the list of
  *                             options (like 'ipbreason-dropdown').
- *    'label-message'       -- message key for a message to use as the label.
+ *    'label-message'       -- message key or object for a message to use as the label.
  *                             can be an array of msg key and then parameters to
  *                             the message.
  *    'label'               -- alternatively, a raw text message. Overridden by
  *                             label-message
  *    'help'                -- message text for a message to use as a help text.
- *    'help-message'        -- message key for a message to use as a help text.
+ *    'help-message'        -- message key or object for a message to use as a help text.
  *                             can be an array of msg key and then parameters to
  *                             the message.
  *                             Overwrites 'help-messages' and 'help'.
- *    'help-messages'       -- array of message key. As above, each item can
+ *    'help-messages'       -- array of message keys/objects. As above, each item can
  *                             be an array of msg key and then parameters.
  *                             Overwrites 'help'.
  *    'required'            -- passed through to the object, indicating that it
@@ -180,6 +180,7 @@ class HTMLForm extends ContextSource {
        protected $mSectionFooters = [];
        protected $mPost = '';
        protected $mId;
+       protected $mName;
        protected $mTableId = '';
 
        protected $mSubmitID;
@@ -198,6 +199,13 @@ class HTMLForm extends ContextSource {
         */
        protected $mAction = false;
 
+       /**
+        * Form attribute autocomplete. false does not set the attribute
+        * @since 1.27
+        * @var bool|string
+        */
+       protected $mAutocomplete = false;
+
        protected $mUseMultipart = false;
        protected $mHiddenFields = [];
        protected $mButtons = [];
@@ -996,6 +1004,12 @@ class HTMLForm extends ContextSource {
                if ( !empty( $this->mId ) ) {
                        $attribs['id'] = $this->mId;
                }
+               if ( !empty( $this->mAutocomplete ) ) {
+                       $attribs['autocomplete'] = $this->mAutocomplete;
+               }
+               if ( !empty ( $this->mName ) ) {
+                       $attribs['name'] = $this->mName;
+               }
                return $attribs;
        }
 
@@ -1337,6 +1351,16 @@ class HTMLForm extends ContextSource {
                return $this;
        }
 
+       /**
+        * @param string $name 'name' attribute for the form
+        * @return HTMLForm $this for chaining calls
+        */
+       public function setName( $name ) {
+               $this->mName = $name;
+
+               return $this;
+       }
+
        /**
         * Prompt the whole form to be wrapped in a "<fieldset>", with
         * this text as its "<legend>" element.
@@ -1677,4 +1701,20 @@ class HTMLForm extends ContextSource {
 
                return $this->getTitle()->getLocalURL();
        }
+
+       /**
+        * Set the value for the autocomplete attribute of the form.
+        * When set to false (which is the default state), the attribute get not set.
+        *
+        * @since 1.27
+        *
+        * @param string|bool $autocomplete
+        *
+        * @return HTMLForm $this for chaining calls
+        */
+       public function setAutocomplete( $autocomplete ) {
+               $this->mAutocomplete = $autocomplete;
+
+               return $this;
+       }
 }
index ebbe323..e86d4c4 100644 (file)
@@ -179,7 +179,7 @@ abstract class HTMLFormField {
                                        return true;
 
                                case 'OR':
-                                       foreach ( $params as $p ) {
+                                       foreach ( $params as $i => $p ) {
                                                if ( !is_array( $p ) ) {
                                                        throw new MWException(
                                                                "Expected array, found " . gettype( $p ) . " at index $i"
@@ -205,7 +205,7 @@ abstract class HTMLFormField {
                                        return false;
 
                                case 'NOR':
-                                       foreach ( $params as $p ) {
+                                       foreach ( $params as $i => $p ) {
                                                if ( !is_array( $p ) ) {
                                                        throw new MWException(
                                                                "Expected array, found " . gettype( $p ) . " at index $i"
@@ -381,16 +381,7 @@ abstract class HTMLFormField {
 
                # Generate the label from a message, if possible
                if ( isset( $params['label-message'] ) ) {
-                       $msgInfo = $params['label-message'];
-
-                       if ( is_array( $msgInfo ) ) {
-                               $msg = array_shift( $msgInfo );
-                       } else {
-                               $msg = $msgInfo;
-                               $msgInfo = [];
-                       }
-
-                       $this->mLabel = $this->msg( $msg, $msgInfo )->parse();
+                       $this->mLabel = $this->getMessage( $params['label-message'] )->parse();
                } elseif ( isset( $params['label'] ) ) {
                        if ( $params['label'] === '&#160;' ) {
                                // Apparently some things set &nbsp directly and in an odd format
@@ -610,12 +601,17 @@ abstract class HTMLFormField {
                $config = [
                        'classes' => [ "mw-htmlform-field-$fieldType", $this->mClass ],
                        'align' => $this->getLabelAlignOOUI(),
-                       'label' => new OOUI\HtmlSnippet( $this->getLabel() ),
                        'help' => $helpText !== null ? new OOUI\HtmlSnippet( $helpText ) : null,
                        'errors' => $errors,
                        'infusable' => $infusable,
                ];
 
+               // the element could specify, that the label doesn't need to be added
+               $label = $this->getLabel();
+               if ( $label ) {
+                       $config['label'] = new OOUI\HtmlSnippet( $label );
+               }
+
                return $this->getFieldLayoutOOUI( $inputField, $config );
        }
 
@@ -778,9 +774,8 @@ abstract class HTMLFormField {
                }
 
                if ( isset( $this->mParams['help-messages'] ) ) {
-                       foreach ( $this->mParams['help-messages'] as $name ) {
-                               $helpMessage = (array)$name;
-                               $msg = $this->msg( array_shift( $helpMessage ), $helpMessage );
+                       foreach ( $this->mParams['help-messages'] as $msg ) {
+                               $msg = $this->getMessage( $msg );
 
                                if ( $msg->exists() ) {
                                        if ( is_null( $helptext ) ) {
@@ -912,45 +907,23 @@ abstract class HTMLFormField {
                return Linker::tooltipAndAccesskeyAttribs( $this->mParams['tooltip'] );
        }
 
-       /**
-        * Get a translated key if necessary.
-        * @param array|null $mappings Array of mappings, 'original' => 'translated'
-        * @param string $key
-        * @return string
-        */
-       protected function getMappedKey( $mappings, $key ) {
-               if ( !is_array( $mappings ) ) {
-                       return $key;
-               }
-
-               if ( !empty( $mappings[$key] ) ) {
-                       return $mappings[$key];
-               }
-
-               return $key;
-       }
-
        /**
         * Returns the given attributes from the parameters
         *
         * @param array $list List of attributes to get
-        * @param array $mappings Optional - Key/value map of attribute names to use
-        *   instead of the ones passed in.
         * @return array Attributes
         */
-       public function getAttributes( array $list, array $mappings = null ) {
+       public function getAttributes( array $list ) {
                static $boolAttribs = [ 'disabled', 'required', 'autofocus', 'multiple', 'readonly' ];
 
                $ret = [];
                foreach ( $list as $key ) {
-                       $mappedKey = $this->getMappedKey( $mappings, $key );
-
                        if ( in_array( $key, $boolAttribs ) ) {
                                if ( !empty( $this->mParams[$key] ) ) {
-                                       $ret[$mappedKey] = $mappedKey;
+                                       $ret[$key] = '';
                                }
                        } elseif ( isset( $this->mParams[$key] ) ) {
-                               $ret[$mappedKey] = $this->mParams[$key];
+                               $ret[$key] = $this->mParams[$key];
                        }
                }
 
@@ -1005,7 +978,7 @@ abstract class HTMLFormField {
                                $this->mOptions = self::forceToStringRecursive( $this->mParams['options'] );
                        } elseif ( array_key_exists( 'options-message', $this->mParams ) ) {
                                /** @todo This is copied from Xml::listDropDown(), deprecate/avoid duplication? */
-                               $message = $this->msg( $this->mParams['options-message'] )->inContentLanguage()->plain();
+                               $message = $this->getMessage( $this->mParams['options-message'] )->inContentLanguage()->plain();
 
                                $optgroup = false;
                                $this->mOptions = [];
@@ -1114,4 +1087,23 @@ abstract class HTMLFormField {
                        return Html::rawElement( 'span', [ 'class' => 'error' ], $errors );
                }
        }
+
+       /**
+        * Turns a *-message parameter (which could be a MessageSpecifier, or a message name, or a
+        * name + parameters array) into a Message.
+        * @param mixed $value
+        * @return Message
+        */
+       protected function getMessage( $value ) {
+               if ( $value instanceof Message ) {
+                       return $value;
+               } elseif ( $value instanceof MessageSpecifier ) {
+                       return Message::newFromKey( $value );
+               } elseif ( is_array( $value ) ) {
+                       $msg = array_shift( $value );
+                       return $this->msg( $msg, $value );
+               } else {
+                       return $this->msg( $value, [] );
+               }
+       }
 }
index 6553b56..4f2460f 100644 (file)
@@ -14,9 +14,9 @@
  *     'table', 'div', or 'raw'.
  *   row-legend - If non-empty, each group of subfields will be enclosed in a
  *     fieldset. The value is the name of a message key to use as the legend.
- *   create-button-message - Message key to use as the text of the button to
+ *   create-button-message - Message to use as the text of the button to
  *     add an additional group of fields.
- *   delete-button-message - Message key to use as the text of automatically-
+ *   delete-button-message - Message to use as the text of automatically-
  *     generated 'delete' button. Ignored if 'delete' is included in 'fields'.
  *
  * In the generated HTML, the subfields will be named along the lines of
@@ -299,7 +299,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                                'name' => $name,
                                'id' => Sanitizer::escapeId( "{$this->mID}--$key--delete" ),
                                'cssclass' => 'mw-htmlform-cloner-delete-button',
-                               'default' => $this->msg( $label )->text(),
+                               'default' => $this->getMessage( $label )->text(),
                        ], $this->mParent );
                        $v = $field->getDefault();
 
@@ -371,7 +371,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                        'name' => $name,
                        'id' => Sanitizer::escapeId( "{$this->mID}--create" ),
                        'cssclass' => 'mw-htmlform-cloner-create-button',
-                       'default' => $this->msg( $label )->text(),
+                       'default' => $this->getMessage( $label )->text(),
                ], $this->mParent );
                $html .= $field->getInputHTML( $field->getDefault() );
 
index 272af15..bcb07bd 100644 (file)
@@ -19,7 +19,7 @@ class HTMLFormFieldWithButton extends HTMLFormField {
        protected $mButtonValue;
 
        /** @var string $mButtonType Value for the button in this field */
-       protected $mButtonFlags = [ 'primary', 'progressive' ];
+       protected $mButtonFlags = [ 'progressive' ];
 
        public function __construct( $info ) {
                if ( isset( $info['buttonclass'] ) ) {
@@ -59,7 +59,9 @@ class HTMLFormFieldWithButton extends HTMLFormField {
                        'type' => $this->mButtonType,
                        'label' => $this->mButtonValue,
                        'flags' => $this->mButtonFlags,
-               ] );
+               ] + OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               ) );
        }
 
        /**
index 251bb05..1aaa3e8 100644 (file)
@@ -72,8 +72,9 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
                                new OOUI\CheckboxInputWidget( [
                                        'name' => "{$this->mName}[]",
                                        'selected' => $checked,
-                                       'value' => $attribs['value'],
-                               ] + $attribs ),
+                               ] + OOUI\Element::configFromHtmlAttributes(
+                                       $attribs
+                               ) ),
                                [
                                        'label' => $label,
                                        'align' => 'inline',
index ecca6ff..12a8a1f 100644 (file)
@@ -53,7 +53,9 @@ class HTMLRadioField extends HTMLFormField {
                        'value' => $value,
                        'options' => $options,
                        'classes' => 'mw-htmlform-flatlist-item',
-               ] + $this->getAttributes( [ 'disabled', 'tabindex' ], [ 'tabindex' => 'tabIndex' ] ) );
+               ] + OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( [ 'disabled', 'tabindex' ] )
+               ) );
        }
 
        function formatOptions( $options, $value ) {
index e44ffa3..e75c2b2 100644 (file)
@@ -15,9 +15,9 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
                if ( array_key_exists( 'other', $params ) ) {
                        // Do nothing
                } elseif ( array_key_exists( 'other-message', $params ) ) {
-                       $params['other'] = wfMessage( $params['other-message'] )->plain();
+                       $params['other'] = $this->getMessage( $params['other-message'] )->plain();
                } else {
-                       $params['other'] = wfMessage( 'htmlform-selectorother-other' )->plain();
+                       $params['other'] = $this->msg( 'htmlform-selectorother-other' )->plain();
                }
 
                parent::__construct( $params );
index 6191665..b6ad46c 100644 (file)
@@ -45,7 +45,9 @@ class HTMLSelectField extends HTMLFormField {
        function getInputOOUI( $value ) {
                $disabled = false;
                $allowedParams = [ 'tabindex' ];
-               $attribs = $this->getAttributes( $allowedParams, [ 'tabindex' => 'tabIndex' ] );
+               $attribs = OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
 
                if ( $this->mClass !== '' ) {
                        $attribs['classes'] = [ $this->mClass ];
index b05fd7c..8ffff43 100644 (file)
@@ -4,6 +4,24 @@ class HTMLTextAreaField extends HTMLFormField {
        const DEFAULT_COLS = 80;
        const DEFAULT_ROWS = 25;
 
+       protected $mPlaceholder = '';
+
+       /**
+        * @param array $params
+        *   - cols, rows: textarea size
+        *   - placeholder/placeholder-message: set HTML placeholder attribute
+        *   - spellcheck: set HTML spellcheck attribute
+        */
+       public function __construct( $params ) {
+               parent::__construct( $params );
+
+               if ( isset( $params['placeholder-message'] ) ) {
+                       $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->parse();
+               } elseif ( isset( $params['placeholder'] ) ) {
+                       $this->mPlaceholder = $params['placeholder'];
+               }
+       }
+
        function getCols() {
                return isset( $this->mParams['cols'] ) ? $this->mParams['cols'] : static::DEFAULT_COLS;
        }
@@ -32,9 +50,11 @@ class HTMLTextAreaField extends HTMLFormField {
                if ( $this->mClass !== '' ) {
                        $attribs['class'] = $this->mClass;
                }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
 
                $allowedParams = [
-                       'placeholder',
                        'tabindex',
                        'disabled',
                        'readonly',
@@ -56,9 +76,11 @@ class HTMLTextAreaField extends HTMLFormField {
                if ( $this->mClass !== '' ) {
                        $attribs['classes'] = [ $this->mClass ];
                }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
 
                $allowedParams = [
-                       'placeholder',
                        'tabindex',
                        'disabled',
                        'readonly',
@@ -66,10 +88,9 @@ class HTMLTextAreaField extends HTMLFormField {
                        'autofocus',
                ];
 
-               $attribs += $this->getAttributes( $allowedParams, [
-                       'tabindex' => 'tabIndex',
-                       'readonly' => 'readOnly',
-               ] );
+               $attribs += OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
 
                return new OOUI\TextInputWidget( [
                        'id' => $this->mID,
index fb7584b..3ab7176 100644 (file)
@@ -1,6 +1,27 @@
 <?php
 
 class HTMLTextField extends HTMLFormField {
+       protected $mPlaceholder = '';
+
+       /**
+        * @param array $params
+        *   - type: HTML textfield type
+        *   - size: field size in characters (defaults to 45)
+        *   - placeholder/placeholder-message: set HTML placeholder attribute
+        *   - spellcheck: set HTML spellcheck attribute
+        *   - persistent: upon unsuccessful requests, retain the value (defaults to true, except
+        *     for password fields)
+        */
+       public function __construct( $params ) {
+               parent::__construct( $params );
+
+               if ( isset( $params['placeholder-message'] ) ) {
+                       $this->mPlaceholder = $this->getMessage( $params['placeholder-message'] )->parse();
+               } elseif ( isset( $params['placeholder'] ) ) {
+                       $this->mPlaceholder = $params['placeholder'];
+               }
+       }
+
        function getSize() {
                return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 45;
        }
@@ -14,7 +35,19 @@ class HTMLTextField extends HTMLFormField {
                return null;
        }
 
+       public function isPersistent() {
+               if ( isset( $this->mParams['persistent'] ) ) {
+                       return $this->mParams['persistent'];
+               }
+               // don't put passwords into the HTML body, they could get cached or otherwise leaked
+               return !( isset( $this->mParams['type'] ) && $this->mParams['type'] === 'password' );
+       }
+
        function getInputHTML( $value ) {
+               if ( !$this->isPersistent() ) {
+                       $value = '';
+               }
+
                $attribs = [
                                'id' => $this->mID,
                                'name' => $this->mName,
@@ -27,6 +60,9 @@ class HTMLTextField extends HTMLFormField {
                if ( $this->mClass !== '' ) {
                        $attribs['class'] = $this->mClass;
                }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
 
                # @todo Enforce pattern, step, required, readonly on the server side as
                # well
@@ -37,7 +73,6 @@ class HTMLTextField extends HTMLFormField {
                        'pattern',
                        'title',
                        'step',
-                       'placeholder',
                        'list',
                        'maxlength',
                        'tabindex',
@@ -85,11 +120,18 @@ class HTMLTextField extends HTMLFormField {
        }
 
        function getInputOOUI( $value ) {
+               if ( !$this->isPersistent() ) {
+                       $value = '';
+               }
+
                $attribs = $this->getTooltipAndAccessKey();
 
                if ( $this->mClass !== '' ) {
                        $attribs['classes'] = [ $this->mClass ];
                }
+               if ( $this->mPlaceholder !== '' ) {
+                       $attribs['placeholder'] = $this->mPlaceholder;
+               }
 
                # @todo Enforce pattern, step, required, readonly on the server side as
                # well
@@ -100,18 +142,15 @@ class HTMLTextField extends HTMLFormField {
                        'flags',
                        'indicator',
                        'maxlength',
-                       'placeholder',
                        'readonly',
                        'required',
                        'tabindex',
                        'type',
                ];
 
-               $attribs += $this->getAttributes( $allowedParams, [
-                       'maxlength' => 'maxLength',
-                       'readonly' => 'readOnly',
-                       'tabindex' => 'tabIndex',
-               ] );
+               $attribs += OOUI\Element::configFromHtmlAttributes(
+                       $this->getAttributes( $allowedParams )
+               );
 
                $type = $this->getType( $attribs );
 
index 410d15d..fcf721a 100644 (file)
@@ -86,7 +86,7 @@ class HTMLTitleTextField extends HTMLTextField {
                $this->mClass .= 'mw-searchInput';
 
                // return the HTMLTextField html
-               return parent::getInputHtml( $value );
+               return parent::getInputHTML( $value );
        }
 
        protected function getDataAttribs() {
index 92b35a8..5a7e0b9 100644 (file)
@@ -51,6 +51,6 @@ class HTMLUserTextField extends HTMLTextField {
                $this->mClass .= ' mw-autocomplete-user';
 
                // return parent html
-               return parent::getInputHtml( $value );
+               return parent::getInputHTML( $value );
        }
 }
index f0f961e..c446615 100644 (file)
@@ -27,7 +27,7 @@
 class VFormHTMLForm extends HTMLForm {
        /**
         * Wrapper and its legend are never generated in VForm mode.
-        * @var boolean
+        * @var bool
         */
        protected $mWrapperLegend = false;
 
index b6740d2..259d514 100644 (file)
@@ -604,7 +604,7 @@ class WikiImporter {
                $normalFields = [ 'sitename', 'base', 'generator', 'case' ];
 
                while ( $this->reader->read() ) {
-                       if ( $this->reader->nodeType == XmlReader::END_ELEMENT &&
+                       if ( $this->reader->nodeType == XMLReader::END_ELEMENT &&
                                        $this->reader->localName == 'siteinfo' ) {
                                break;
                        }
@@ -693,7 +693,7 @@ class WikiImporter {
                if ( !isset( $logInfo['contributor']['username'] ) ) {
                        $revision->setUsername( 'Unknown user' );
                } else {
-                       $revision->setUserName( $logInfo['contributor']['username'] );
+                       $revision->setUsername( $logInfo['contributor']['username'] );
                }
 
                return $this->logItemCallback( $revision );
@@ -886,9 +886,9 @@ class WikiImporter {
                if ( isset( $revisionInfo['contributor']['ip'] ) ) {
                        $revision->setUserIP( $revisionInfo['contributor']['ip'] );
                } elseif ( isset( $revisionInfo['contributor']['username'] ) ) {
-                       $revision->setUserName( $revisionInfo['contributor']['username'] );
+                       $revision->setUsername( $revisionInfo['contributor']['username'] );
                } else {
-                       $revision->setUserName( 'Unknown user' );
+                       $revision->setUsername( 'Unknown user' );
                }
                $revision->setNoUpdates( $this->mNoUpdates );
 
@@ -992,7 +992,7 @@ class WikiImporter {
                        $revision->setUserIP( $uploadInfo['contributor']['ip'] );
                }
                if ( isset( $uploadInfo['contributor']['username'] ) ) {
-                       $revision->setUserName( $uploadInfo['contributor']['username'] );
+                       $revision->setUsername( $uploadInfo['contributor']['username'] );
                }
                $revision->setNoUpdates( $this->mNoUpdates );
 
index d4db765..356a79f 100644 (file)
@@ -640,22 +640,24 @@ class WikiRevision {
 
                # Get the file source or download if necessary
                $source = $this->getFileSrc();
-               $flags = $this->isTempSrc() ? File::DELETE_SOURCE : 0;
-               if ( !$source ) {
+               $autoDeleteSource = $this->isTempSrc();
+               if ( !strlen( $source ) ) {
                        $source = $this->downloadSource();
-                       $flags |= File::DELETE_SOURCE;
+                       $autoDeleteSource = true;
                }
-               if ( !$source ) {
+               if ( !strlen( $source ) ) {
                        wfDebug( __METHOD__ . ": Could not fetch remote file.\n" );
                        return false;
                }
+
+               $tmpFile = new TempFSFile( $source );
+               if ( $autoDeleteSource ) {
+                       $tmpFile->autocollect();
+               }
+
                $sha1File = ltrim( sha1_file( $source ), '0' );
                $sha1 = $this->getSha1();
                if ( $sha1 && ( $sha1 !== $sha1File ) ) {
-                       if ( $flags & File::DELETE_SOURCE ) {
-                               # Broken file; delete it if it is a temporary file
-                               unlink( $source );
-                       }
                        wfDebug( __METHOD__ . ": Corrupt file $source.\n" );
                        return false;
                }
@@ -665,8 +667,9 @@ class WikiRevision {
                # Do the actual upload
                if ( $archiveName ) {
                        $status = $file->uploadOld( $source, $archiveName,
-                               $this->getTimestamp(), $this->getComment(), $user, $flags );
+                               $this->getTimestamp(), $this->getComment(), $user );
                } else {
+                       $flags = 0;
                        $status = $file->upload( $source, $this->getComment(), $this->getComment(),
                                $flags, false, $this->getTimestamp(), $user );
                }
index 7ecb71c..661c3ec 100644 (file)
@@ -199,7 +199,7 @@ class CliInstaller extends Installer {
                        }
                }
 
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        echo "\n";
                        exit( 1 );
                }
index 152f33a..79bd961 100644 (file)
@@ -202,7 +202,7 @@ abstract class DatabaseInstaller {
                        $this->db->commit( __METHOD__ );
                }
                // Resume normal operations
-               if ( $status->isOk() ) {
+               if ( $status->isOK() ) {
                        $this->enableLB();
                }
 
index 03f091b..6a20abc 100644 (file)
@@ -63,18 +63,18 @@ abstract class DatabaseUpdater {
        protected $shared = false;
 
        /**
-        * Scripts to run after database update
+        * @var string[] Scripts to run after database update
         * Should be a subclass of LoggedUpdateMaintenance
         */
        protected $postDatabaseUpdateMaintenance = [
-               'DeleteDefaultMessages',
-               'PopulateRevisionLength',
-               'PopulateRevisionSha1',
-               'PopulateImageSha1',
-               'FixExtLinksProtocolRelative',
-               'PopulateFilearchiveSha1',
-               'PopulateBacklinkNamespace',
-               'FixDefaultJsonContentPages'
+               DeleteDefaultMessages::class,
+               PopulateRevisionLength::class,
+               PopulateRevisionSha1::class,
+               PopulateImageSha1::class,
+               FixExtLinksProtocolRelative::class,
+               PopulateFilearchiveSha1::class,
+               PopulateBacklinkNamespace::class,
+               FixDefaultJsonContentPages::class,
        ];
 
        /**
@@ -375,7 +375,7 @@ abstract class DatabaseUpdater {
        /**
         * @since 1.17
         *
-        * @return array
+        * @return string[]
         */
        public function getPostDatabaseUpdateMaintenance() {
                return $this->postDatabaseUpdateMaintenance;
index 442baf7..3d1c860 100644 (file)
@@ -757,6 +757,12 @@ abstract class Installer {
                        return false;
                }
 
+               if ( !function_exists( 'mb_substr' ) ) {
+                       $this->showError( 'config-mbstring-absent' );
+
+                       return false;
+               }
+
                return true;
        }
 
index f70401b..c6b8960 100644 (file)
@@ -634,7 +634,7 @@ class MssqlInstaller extends DatabaseInstaller {
                $status = parent::createTables();
 
                // Do last-minute stuff like fulltext indexes (since they can't be inside a transaction)
-               if ( $status->isOk() ) {
+               if ( $status->isOK() ) {
                        $searchindex = $this->db->tableName( 'searchindex' );
                        $schema = $this->db->addIdentifierQuotes( $this->getVar( 'wgDBmwschema' ) );
                        try {
index b3675f8..bdaf4c8 100644 (file)
@@ -68,6 +68,7 @@ class MssqlUpdater extends DatabaseUpdater {
                        // 1.27
                        [ 'dropTable', 'msg_resource_links' ],
                        [ 'dropTable', 'msg_resource' ],
+                       [ 'addField', 'watchlist', 'wl_id', 'patch-watchlist-wl_id.sql' ],
                ];
        }
 
index 154f7c3..d414d90 100644 (file)
@@ -182,7 +182,6 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'dropIndex', 'iwlinks', 'iwl_prefix', 'patch-kill-iwl_prefix.sql' ],
                        [ 'addField', 'categorylinks', 'cl_collation', 'patch-categorylinks-better-collation.sql' ],
                        [ 'doClFieldsUpdate' ],
-                       [ 'doCollationUpdate' ],
                        [ 'addTable', 'module_deps', 'patch-module_deps.sql' ],
                        [ 'dropIndex', 'archive', 'ar_page_revid', 'patch-archive_kill_ar_page_revid.sql' ],
                        [ 'addIndex', 'archive', 'ar_revid', 'patch-archive_ar_revid.sql' ],
@@ -279,6 +278,11 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'dropTable', 'msg_resource_links' ],
                        [ 'dropTable', 'msg_resource' ],
                        [ 'addTable', 'bot_passwords', 'patch-bot_passwords.sql' ],
+                       [ 'addField', 'watchlist', 'wl_id', 'patch-watchlist-wl_id.sql' ],
+                       [ 'dropIndex', 'categorylinks', 'cl_collation', 'patch-kill-cl_collation_index.sql' ],
+                       [ 'addIndex', 'categorylinks', 'cl_collation_ext',
+                               'patch-add-cl_collation_ext_index.sql' ],
+                       [ 'doCollationUpdate' ],
                ];
        }
 
index 02e59f5..334256b 100644 (file)
@@ -111,6 +111,7 @@ class OracleUpdater extends DatabaseUpdater {
                        // 1.27
                        [ 'dropTable', 'msg_resource_links' ],
                        [ 'dropTable', 'msg_resource' ],
+                       [ 'addField', 'watchlist', 'wl_id', 'patch-watchlist-wl_id.sql' ],
 
                        // KEEP THIS AT THE BOTTOM!!
                        [ 'doRebuildDuplicateFunction' ],
index 234c209..0728415 100644 (file)
@@ -615,7 +615,7 @@ class PostgresInstaller extends DatabaseInstaller {
                        $conn->commit( __METHOD__ );
                }
                // Resume normal operations
-               if ( $status->isOk() ) {
+               if ( $status->isOK() ) {
                        $this->enableLB();
                }
 
index 038c953..a3b50ac 100644 (file)
@@ -67,6 +67,7 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'addSequence', 'filearchive', 'fa_id', 'filearchive_fa_id_seq' ],
                        [ 'addSequence', 'archive', false, 'archive_ar_id_seq' ],
                        [ 'addSequence', 'externallinks', false, 'externallinks_el_id_seq' ],
+                       [ 'addSequence', 'watchlist', false, 'watchlist_wl_id_seq' ],
 
                        # new tables
                        [ 'addTable', 'category', 'patch-category.sql' ],
@@ -428,6 +429,10 @@ class PostgresUpdater extends DatabaseUpdater {
                        // 1.27
                        [ 'dropTable', 'msg_resource_links' ],
                        [ 'dropTable', 'msg_resource' ],
+                       [
+                               'addPgField', 'watchlist', 'wl_id',
+                               "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('watchlist_wl_id_seq')"
+                       ],
                ];
        }
 
index 7db4f1a..86dccd7 100644 (file)
@@ -65,7 +65,6 @@ class SqliteUpdater extends DatabaseUpdater {
                        [ 'addField', 'interwiki', 'iw_api', 'patch-iw_api_and_wikiid.sql' ],
                        [ 'dropIndex', 'iwlinks', 'iwl_prefix', 'patch-kill-iwl_prefix.sql' ],
                        [ 'addField', 'categorylinks', 'cl_collation', 'patch-categorylinks-better-collation.sql' ],
-                       [ 'doCollationUpdate' ],
                        [ 'addTable', 'module_deps', 'patch-module_deps.sql' ],
                        [ 'dropIndex', 'archive', 'ar_page_revid', 'patch-archive_kill_ar_page_revid.sql' ],
                        [ 'addIndex', 'archive', 'ar_revid', 'patch-archive_ar_revid.sql' ],
@@ -148,6 +147,11 @@ class SqliteUpdater extends DatabaseUpdater {
                        [ 'dropTable', 'msg_resource_links' ],
                        [ 'dropTable', 'msg_resource' ],
                        [ 'addTable', 'bot_passwords', 'patch-bot_passwords.sql' ],
+                       [ 'addField', 'watchlist', 'wl_id', 'patch-watchlist-wl_id.sql' ],
+                       [ 'dropIndex', 'categorylinks', 'cl_collation', 'patch-kill-cl_collation_index.sql' ],
+                       [ 'addIndex', 'categorylinks', 'cl_collation_ext',
+                               'patch-add-cl_collation_ext_index.sql' ],
+                       [ 'doCollationUpdate' ],
                ];
        }
 
index 7d09fd7..4c4e6b7 100644 (file)
@@ -1058,7 +1058,7 @@ class WebInstaller extends Installer {
                if ( !$status->isGood() ) {
                        $text = $status->getWikiText();
 
-                       if ( $status->isOk() ) {
+                       if ( $status->isOK() ) {
                                $box = $this->getWarningBox( $text );
                        } else {
                                $box = $this->getErrorBox( $text );
@@ -1149,7 +1149,7 @@ class WebInstaller extends Installer {
         */
        public function downloadLinkHook( $text, $attribs, $parser ) {
                $anchor = Html::rawElement( 'a',
-                       [ 'href' => $this->getURL( [ 'localsettings' => 1 ] ) ],
+                       [ 'href' => $this->getUrl( [ 'localsettings' => 1 ] ) ],
                        wfMessage( 'config-download-localsettings' )->parse()
                );
 
index ffab9bb..11a1833 100644 (file)
@@ -24,12 +24,12 @@ class WebInstallerComplete extends WebInstallerPage {
        public function execute() {
                // Pop up a dialog box, to make it difficult for the user to forget
                // to download the file
-               $lsUrl = $this->getVar( 'wgServer' ) . $this->parent->getURL( [ 'localsettings' => 1 ] );
+               $lsUrl = $this->getVar( 'wgServer' ) . $this->parent->getUrl( [ 'localsettings' => 1 ] );
                if ( isset( $_SERVER['HTTP_USER_AGENT'] ) &&
                        strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE' ) !== false
                ) {
                        // JS appears to be the only method that works consistently with IE7+
-                       $this->addHtml( "\n<script>jQuery( function () { location.href = " .
+                       $this->addHTML( "\n<script>jQuery( function () { location.href = " .
                                Xml::encodeJsVar( $lsUrl ) . "; } );</script>\n" );
                } else {
                        $this->parent->request->response()->header( "Refresh: 0;url=$lsUrl" );
index 9d0d680..63740e3 100644 (file)
@@ -81,9 +81,9 @@ class WebInstallerInstall extends WebInstallerPage {
                if ( $step == 'extension-tables' ) {
                        $this->endLiveBox();
                }
-               $msg = $status->isOk() ? 'config-install-step-done' : 'config-install-step-failed';
+               $msg = $status->isOK() ? 'config-install-step-done' : 'config-install-step-failed';
                $html = wfMessage( 'word-separator' )->escaped() . wfMessage( $msg )->escaped();
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        $html = "<span class=\"error\">$html</span>";
                }
                $this->addHTML( $html . "</li>\n" );
index 5564618..dcd30cf 100644 (file)
@@ -73,7 +73,7 @@ class WebInstallerName extends WebInstallerPage {
                                'label' => '', // @todo Needs a label?
                                'attribs' => [ 'readonly' => 'readonly', 'class' => 'enabledByOther' ]
                        ] ) .
-                       $this->getFieldSetStart( 'config-admin-box' ) .
+                       $this->getFieldsetStart( 'config-admin-box' ) .
                        $this->parent->getTextBox( [
                                'var' => '_AdminName',
                                'label' => 'config-admin-name',
@@ -100,7 +100,7 @@ class WebInstallerName extends WebInstallerPage {
                                'label' => 'config-subscribe',
                                'help' => $this->parent->getHelpBox( 'config-subscribe-help' )
                        ] ) .
-                       $this->getFieldSetEnd() .
+                       $this->getFieldsetEnd() .
                        $this->parent->getInfoBox( wfMessage( 'config-almost-done' )->text() ) .
                        // getRadioSet() builds a set of labeled radio buttons.
                        // For grep: The following messages are used as the item labels:
index 7cc5db2..0c01b64 100644 (file)
@@ -67,7 +67,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        $this->parent->getHelpBox( 'config-license-help' ) .
 
                        # E-mail
-                       $this->getFieldSetStart( 'config-email-settings' ) .
+                       $this->getFieldsetStart( 'config-email-settings' ) .
                        $this->parent->getCheckBox( [
                                'var' => 'wgEnableEmail',
                                'label' => 'config-enable-email',
@@ -101,11 +101,11 @@ class WebInstallerOptions extends WebInstallerPage {
                        ] ) .
                        $this->parent->getHelpBox( 'config-email-auth-help' ) .
                        "</div>" .
-                       $this->getFieldSetEnd()
+                       $this->getFieldsetEnd()
                );
 
                $skins = $this->parent->findExtensions( 'skins' );
-               $skinHtml = $this->getFieldSetStart( 'config-skins' );
+               $skinHtml = $this->getFieldsetStart( 'config-skins' );
 
                $skinNames = array_map( 'strtolower', $skins );
                $chosenSkinName = $this->getVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) );
@@ -136,13 +136,13 @@ class WebInstallerOptions extends WebInstallerPage {
                }
 
                $skinHtml .= $this->parent->getHelpBox( 'config-skins-help' ) .
-                       $this->getFieldSetEnd();
+                       $this->getFieldsetEnd();
                $this->addHTML( $skinHtml );
 
                $extensions = $this->parent->findExtensions();
 
                if ( $extensions ) {
-                       $extHtml = $this->getFieldSetStart( 'config-extensions' );
+                       $extHtml = $this->getFieldsetStart( 'config-extensions' );
 
                        foreach ( $extensions as $ext ) {
                                $extHtml .= $this->parent->getCheckBox( [
@@ -152,7 +152,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        }
 
                        $extHtml .= $this->parent->getHelpBox( 'config-extensions-help' ) .
-                               $this->getFieldSetEnd();
+                               $this->getFieldsetEnd();
                        $this->addHTML( $extHtml );
                }
 
@@ -167,7 +167,7 @@ class WebInstallerOptions extends WebInstallerPage {
                $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none';
                $this->addHTML(
                        # Uploading
-                       $this->getFieldSetStart( 'config-upload-settings' ) .
+                       $this->getFieldsetStart( 'config-upload-settings' ) .
                        $this->parent->getCheckBox( [
                                'var' => 'wgEnableUploads',
                                'label' => 'config-upload-enable',
@@ -195,7 +195,7 @@ class WebInstallerOptions extends WebInstallerPage {
                                'label' => 'config-instantcommons',
                                'help' => $this->parent->getHelpBox( 'config-instantcommons-help' )
                        ] ) .
-                       $this->getFieldSetEnd()
+                       $this->getFieldsetEnd()
                );
 
                $caches = [ 'none' ];
@@ -219,7 +219,7 @@ class WebInstallerOptions extends WebInstallerPage {
                $hidden = ( $cacheval == 'memcached' ) ? '' : 'display: none';
                $this->addHTML(
                        # Advanced settings
-                       $this->getFieldSetStart( 'config-advanced-settings' ) .
+                       $this->getFieldsetStart( 'config-advanced-settings' ) .
                        # Object cache settings
                        // getRadioSet() builds a set of labeled radio buttons.
                        // For grep: The following messages are used as the item labels:
@@ -239,7 +239,7 @@ class WebInstallerOptions extends WebInstallerPage {
                                'help' => $this->parent->getHelpBox( 'config-memcached-help' )
                        ] ) .
                        '</div>' .
-                       $this->getFieldSetEnd()
+                       $this->getFieldsetEnd()
                );
                $this->endForm();
 
index b6bc521..4d16d45 100644 (file)
        "config-help": "مساعدة",
        "config-help-tooltip": "اضغط للتوسيع",
        "config-nofile": "لا يمكن العثور على الملف \"$1\". هل حُذف؟",
-       "mainpagetext": "'''تم تثبيت ميدياويكي بنجاح.'''",
+       "mainpagetext": "<strong>تم تثبيت ميدياويكي بنجاح.</strong>",
        "mainpagedocfooter": "استشر [//meta.wikimedia.org/wiki/Help:Contents دليل المستخدم] لمعلومات حول استخدام برنامج الويكي.\n\n== البداية ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings قائمة إعدادات الضبط]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ أسئلة متكررة حول ميدياويكي]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce القائمة البريدية الخاصة بإصدار ميدياويكي]"
 }
index da2a1c5..8651c15 100644 (file)
@@ -12,7 +12,7 @@
        "config-localsettings-upgrade": "Detectose un ficheru <code>LocalSettings.php</code>.\nP'anovar esta instalación, escriba'l valor de\n<code>$wgUpgradeKey</code> nel cuadru d'abaxo.\nAlcontraralu en <code>LocalSettings.php</code>.",
        "config-localsettings-cli-upgrade": "Deteutose un ficheru <code>LocalSettings.php</code>.\nP'anovar esta instalación, execute <code>update.php</code>",
        "config-localsettings-key": "Clave d'anovamientu:",
-       "config-localsettings-badkey": "La clave que dio ye incorreuta.",
+       "config-localsettings-badkey": "La clave d'anovamientu que disti ye incorreuta.",
        "config-upgrade-key-missing": "Deteutose una instalación esistente de MediaWiki.\nP'anovar esta instalación, ponga la llinia siguiente al final del ficheru <code>LocalSettings.php</code>:\n\n$1",
        "config-localsettings-incomplete": "Paez que'l ficheru <code>LocalSettings.php</code> esistente ta incompletu.\nLa variable $1 nun ta definida.\nCamude'l ficheru <code>LocalSettings.php</code> pa qu'esta variable quede definida y calque \"{{int:Config-continue}}\".",
        "config-localsettings-connection-error": "Alcontróse un error al conectar cola base de datos usando la configuración especificada en <code>LocalSettings.php</code>. Corrixa esta configuración y vuelva a intentalo.\n\n$1",
        "config-no-db": "¡Nun pudo alcontrase un controlador de base de datos afayadizu! Necesites instalar un controlador de base de datos pa PHP.\n{{PLURAL:$2|Tien sofitu el tipu de base de datos siguiente|Tienen sofitu los tipos de base de datos siguientes}}: $1.\n\nSi compilasti PHP tu mesmu, reconfigúralu con un cliente de base de datos activáu, por exemplu, usando <code>./configure --with-mysqli</code>.\nSi instalasti PHP dende un paquete de Debian o Ubuntu, necesites instalar tamién,por exemplu, el paquete <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Avisu:''' tien SQLite $1, que ye inferior a la versión mínima necesaria $2. SQLite nun tará disponible.",
        "config-no-fts3": "'''Avisu:''' SQLite ta compiláu ensin el [//sqlite.org/fts3.html módulu FTS3]; les funciones de gueta nun tarán disponibles nesti sistema.",
-       "config-register-globals-error": "<strong>Error: la opción de PHP <code>[http://php.net/register_globals register_globals]</code> ta activada.\nTien de desactivase pa siguir cola instalación.</strong>\nVisita [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] p'alcontrar ayuda tocante a cómo facelo.",
-       "config-magic-quotes-gpc": "<strong>Fatal: ¡[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] ta activáu!</strong>\nEsta opción causa la imprevisible corrupción de la entrada de datos.\nNun puedes instalar o utilizar MediaWiki nun siendo que esta opción tea desactivada.",
-       "config-magic-quotes-runtime": "<strong>Fatal: ¡[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] ta activáu!</strong>\nEsta opción causa la imprevisible corrupción de la entrada de datos.\nNun puedes instalar o utilizar MediaWiki nun siendo que esta opción tea desactivada.",
-       "config-magic-quotes-sybase": "<strong>Fatal: ¡[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] ta activáu!</strong>\nEsta opción causa la imprevisible corrupción de la entrada de datos.\nNun puedes instalar o utilizar MediaWiki nun siendo que esta opción tea desactivada.",
        "config-mbstring": "<strong>Fatal: ¡[@http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] ta activáu!</strong>\nEsta opción causa errores y pué corromper los datos de mou imprevisible.\nNun puedes instalar o utilizar MediaWiki nun siendo que esta opción tea desactivada.",
-       "config-safe-mode": "<strong>Atención:</strong> el [http://www.php.net/features.safe-mode mou seguru] de PHP ta activáu.\nPuede causar problemes, especialmente si uses la carga de ficheros ya l'encontu pa <code>math</code>.",
        "config-xml-bad": "Falta'l módulu XML de PHP.\nMediaWiki rique funciones d'esti módulu y nun va funcionar con esta configuración.\nSeique precises instalar el paquete RPM llamáu php-xml.",
        "config-pcre-old": "<strong>Fatal:</strong> Ríquese PCRE $1 o posterior.\nEl binariu de PHP ta enllazáu con PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Más información].",
        "config-apc": "[http://www.php.net/apc APC] ta instaláu",
@@ -99,6 +94,6 @@
        "config-download-localsettings": "Descargar <code>LocalSettings.php</code>",
        "config-help": "Ayuda",
        "config-nofile": "Nun pudo atopase'l ficheru \"$1\". ¿Desaniciose?",
-       "mainpagetext": "'''MediaWiki instalóse correchamente.'''",
+       "mainpagetext": "<strong>Instalóse MediaWiki.</strong>",
        "mainpagedocfooter": "Consulta la [//meta.wikimedia.org/wiki/Help:Contents Guía del usuariu] pa saber cómo usar el software wiki.\n\n== Primeros pasos ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Llista de les opciones de configuración]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ EMF de MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de corréu de llanzamientos de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Llocaliza MediaWiki na to llingua]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Depriende como combatir la puxarra na to wiki]"
 }
index 8165da2..80105f2 100644 (file)
@@ -3,7 +3,14 @@
                "authors": [
                        "Haqmar",
                        "Seb35",
-                       "Рустам Нурыев"
+                       "Рустам Нурыев",
+                       "Sagan",
+                       "Азат Хәлилов",
+                       "Айсар",
+                       "Янмурза Баки",
+                       "Гульчатай",
+                       "Вильданова Гюзель",
+                       "З. ӘЙЛЕ"
                ]
        },
        "config-desc": "MediaWiki йөкләүсе",
        "config-localsettings-cli-upgrade": "<code>LocalSettings.php</code> файлы бар. \nБыл күрһәтмәне яңыртыу өсөн <code>update.php</code> эшләтеп ебәрегеҙ.",
        "config-localsettings-key": "Яңыртыу асҡысы:",
        "config-localsettings-badkey": "Дөрөҫ булмаған асҡыс күрһәттегеҙ",
+       "config-upgrade-key-missing": "Ҡуйылған MediaWiki копияһы булыуы асыҡланды. Яңыртыу өсөн файл аҙағында ҡуйығыҙ: <code>LocalSettings.php</code>:\n\n$1",
+       "config-localsettings-incomplete": "Ғәмәлдәге <code>LocalSettings.php</code> файла тулған. $1 билдәләнмәгән. Зинһар өсөн <code>LocalSettings.php</code> кодын үҙгәртегеҙ. Һуңынан ошонда сиртегеҙ «{{int:Config-continue}}».",
+       "config-localsettings-connection-error": "<code>LocalSettings.php</code> көйләүҙәрендә хата китте йәки <code>AdminSettings.php</code> көйләүҙәрендә хата. Зинһар өсөн, көйләүҙәрҙе тәҙәтегеҙ, яңынан эшләп ҡарағыҙ\n$1",
        "config-session-error": "Эш башлағанда сыҡҡан хата: $1",
+       "config-session-expired": "Һеҙҙең ваҡыт үтте. Сессия $1 оҙонлоғона көйләнгән. Уны оҙайтыу өсөн php.ini. эсендә <code>session.gc_maxlifetime</code> кодын үҙгәртегеҙ.\nУрынлаштырыу процессын яңынан башлағыҙ.",
+       "config-no-session": "Был сессия юғалған!\nҮҙегеҙҙең php.ini тикшерегеҙ, \n<code>session.save_path</code> коды тейешле каталогҡа урынлаштырылған икәненә ышынғыҙ.",
        "config-your-language": "Һеҙҙең тел:",
+       "config-your-language-help": "Урынлаштырыу процессы ҡулланған телде һайлағыҙ.",
        "config-wiki-language": "Вики телдәре:",
+       "config-wiki-language-help": "Викила ҡулланылған телде һайлағыҙ.",
        "config-back": "← Кире",
        "config-continue": "Дауам итергә →",
        "config-page-language": "Тел",
        "config-page-welcome": "MediaWiki-ға рәхим итегеҙ!",
        "config-page-dbconnect": "Мәғлүмәт болона тоташыу",
+       "config-page-upgrade": "Ғәмәлдәге урынлаштырғанды яңыртыу.",
        "config-page-dbsettings": "Мәғлүмәт болон көйләү",
        "config-page-name": "Исем",
        "config-page-options": "Көйләүҙәр",
+       "config-page-install": "Урынлаштырыу",
        "config-page-complete": "Тамам!",
+       "config-page-restart": "Урынлаштырыуҙы яңынан башларға",
        "config-page-readme": "Мине уҡы",
        "config-page-releasenotes": "Өлгө тураһында мәғлүмәт",
        "config-page-copying": "Рөхсәтнәмә",
        "config-page-upgradedoc": "Яңыртыу",
+       "config-page-existingwiki": "Ғәмәлдәге вики",
+       "config-help-restart": "Һеҙ үҙегеҙ индергән һәм  һаҡланған әлеге мәғлүмәттәрҙе юйып, урынлаштырыуҙың яңы процессын ебәрергә теләйһегеҙме?",
        "config-restart": "Эйе, яңынан башларға",
+       "config-welcome": "=== Даирәне тикшереү ===",
+       "config-copyright": "=== Авторлыҡ хоҡуҡтары һәм шарттар ===\n\n$1\n\nMediaWiki - ирекле программа тьәминәте. Һеҙ уны ирекле программа тьәминәте фонды баҫып сығарған GNU General Public License лицензия талаптарына ярашлы рәүештә тарата һәм/йәки үҙгәртә алаһығыҙ;икенсе версияһына йәки ниндәйҙә булһа һуңғы версияһына ярашлы рәүештә.\nMediaWiki - файҙалы булыу өмөтө менән таратыла, ләкин <strong> бер ниндәй ҙә гарантияларһыҙ</strong>, хатта күҙ уңында тотолған гарантияларһыҙ <strong> коммерция ҡимәтенән тыш </strong> йәки </strong> ниндәй ҙә булһа маҡсатҡа яраҡһыҙ </strong>. Ҡара. тулыраҡ мәғлүмәт алыу өсөн GNU General Public License лицезияһы. \nҺеҙ <doclink href=Copying> копияһын GNU General Public License</doclink>ошо программа менән бергә алырға тейеш инегеҙ, әгәр алмаһағыҙ, Free Software Foundation, Inc. ошо адрес буйынса яҙығыҙ:51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA йәки  [http://www.gnu.org/copyleft/gpl.html уны онлайнда уҡығыҙ].",
+       "config-sidebar": "* [//www.mediawiki.org Сайт MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents/ru Ҡулланыусылар өсөн белешмә]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents/ru Администраторҙар өсөн белешмә]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/ru FAQ]\n----\n* <doclink href=Readme>Readme-файл</doclink>\n* <doclink href=ReleaseNotes>Сығарылыш тураһында мәғлүмәт</doclink>\n* <doclink href=Copying>Лицензия</doclink>\n* <doclink href=UpgradeDoc>Яңыртыуҙар</doclink>",
+       "config-env-good": "Мөхитте тикшереү уңышлы тамамланды. MediaWiki урынлаштырырға мөмкин.",
+       "config-env-bad": "Мөхит тикшерелде. Һеҙ MediaWiki урынлаштыра алмайһығыҙ.",
+       "config-env-php": "PHP: $1 өлгөһө урынлаштырылды.",
+       "config-env-hhvm": "HHVM $1 урынлаштырылды.",
+       "config-unicode-using-intl": " [http://pecl.php.net/intl ҡушылмаһы файҙаланасаҡ, «intl» для PECL]  Юникод нормаль эшләһен өсөн.",
+       "config-unicode-pure-php-warning": "'''Иғтибар!''': [http://pecl.php.net/intl ҡушылмаһы intl из PECL] Юникод өсөн рөхсәт ителмәгән PHP менән бик әкрен эшләйәсәк.\nҺеҙҙең сайт бик көсөргәнешле эшләһә [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations нормализации Юникодты нормалләштереү] өсөн уҡығыҙ.",
+       "config-unicode-update-warning": "\"Иҫкәртеү\". Ҡуйылған тышлыҡ Юникодты нормаға килтереүҙең иҫке китапхана версияһын ҡуллана[http://site.icu-project.org/ проекта ICU].Әгәр Юникодты тулы мәғәнәһендә ҡулланырға теләһәгеҙ, һеҙ [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations версияны яңыртырға] тейешһегеҙ.",
+       "config-no-db": "Мәғлүмәттәр базаһына тура килгән драйверҙарҙы табып булманы!Һеҙгә  PHP өсөн мәғлүмәттәр базаһының  драйверҙарын ҡуйырға кәрәк.{{PLURAL:$2|сираттағы төр ҡулланыла|сираттағы төрҙәр ҡулланыла}}мәғлүмәттәр базалары:$1.\nӘгәр һеҙ үҙегеҙ PHP -ға компиляция яһаған булһағыҙ,  мәғлүмәттәр базаһына клиентты индереп уны яңынан, мәҫәлән, <code>./configure --with-mysqli</code> ярҙамы менән көйләгеҙ. Әгәр ҙә һеҙ PHP -ны Debian йәки Ubuntu пакеттарынан ҡуйһағыҙ, һеҙгә, мәҫәлән,  <code>php5-mysql</code> пакетын да ҡуйырға кәрәк булыр.",
+       "config-outdated-sqlite": "'''Киҫәтеү''': Һеҙҙә SQLite  $1 ҡуйылған, $2 тейешле өлгөнән түбән . SQLite асылмаясаҡ.",
+       "config-no-fts3": "'''Иғтибар''': SQLite модулһыҙ йыйлған [//sqlite.org/fts3.html FTS3] — был мәғлүмәт базаһы өсөн эҙләү мөмкин булмаясаҡ.",
+       "config-mbstring": "\"Проблема\":  PHP опцияһы тоташтырылған\n[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!'''\nБыл индерелгән мәғлүмәттәрҙең хаталарына һәм көтөлмәгән боҙолоуҙарға килтерә.\nОпцияны һүндермәйенсә MediaWikiны ҡуйыу һәм ҡулланыу мөмкин түгел.",
+       "config-xml-bad": "РНР өсөн XML-модуль юҡ. \nMediaWiki  бындай конфигурацияла эшләмәйәсәк, сөнки был модулдең функционалы талап ителә.\nБәлки, Һеҙгә RPM-пакет php-xml булдырырыға кәрәк булыр.",
+       "config-pcre-old": "'''Фаталь хата:'''  PCRE версияһы йәки яңырағы талап ителә $1.\nБашҡарылыусы файл PHP менән бәйләнгән PCRE  $2версияһы.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Ентекләберәк].",
+       "config-pcre-no-utf8": "'''Фаталь хата'''. PHP өсөн PCRE модуле  PCRE_UTF8 менән яраҡлыштырылмаған.\nMediaWiki дөрөҫ эшләһен өсөн UTF-8 талап ителә.",
+       "config-memory-raised": "Хәтер сикләнгән PHP  (<code>memory_limit</code>)  $1  $2 тиклем арттырылған.",
+       "config-memory-bad": "'''Иғтибар:''' PHP күләме <code>memory_limit</code> $1 тәшкил итә.\nБәлки, был саманан тыш аҙҙыр. \nҠуйылыштың уңышһыҙлыҡҡа осрауы бар!",
+       "config-ctype": "<strong>Фаталь хата:</strong> PHР тотороҡло эшләргә тейеш [http://www.php.net/manual/en/iconv.installation.php киңәйтеү iconv].",
+       "config-iconv": "<strong>Фаталь хата:</strong> PHР тотороҡло эшләргә тейеш [http://www.php.net/manual/en/iconv.installation.php киңәйтеү iconv].",
+       "config-json": "'''Фаталь хата:''' PHP JSON ярҙамынан тыш эшләнгән.\nҺеҙгә йә PHP JSON киңәйтеүен, йәки MediaWiki алдынан [http://pecl.php.net/package/jsonc PECL jsonc] киңәйтеүен ҡуйырға кәрәк.\n* PHP-киңәйтеүсе <code>/etc/php.ini</code> йәки  <code>/etc/php.d/json.ini</code> инергә тейеш булһа ла, Red Hat Enterprise Linux (CentOS) 5 һәм 6, составына инә.\n* 2013 йылдың майынан һуң сығарылған Linux-тың ҡайһы бер  дистрибутивтары  PECL киңәйтеүен <code>php5-json</code> или <code>php-pecl-jsonc</code> кеүек асыр урынға,  PHP киңәйтеүсеһен асмай.",
+       "config-xcache": "[http://xcache.lighttpd.net/ XCache] урынлаштырылды",
+       "config-apc": "[http://www.php.net/apc APC] урынлаштырылды",
+       "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] урынлыштырылды",
+       "config-no-cache-apcu": "'''Иғтибар:'''  [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] табылманы йәки [http://www.iis.net/download/WinCacheForPhp WinCache].\nОбъекттарҙы кэшлау һүндереләсәк..",
+       "config-mod-security": "<strong>Иғтибар</strong>: һеҙҙең веб-серверығыҙҙа [http://modsecurity.org/ mod_security]/mod_security2 ҡабыҙылған. Уның күп кенә стандарт көйләүҙәре MediaWiki йәки бүтән ПО ҡулланыусыларға серверға ирекле контент ебәрегрә мөмкинлек буйынса проблемалар тыуҙырыуы мөмкин.\nКөтөлмәгән хаталарға тап булһағыҙ, ошонда [http://modsecurity.org/documentation/ документации mod_security]йәки үҙегеҙҙең хостинг-провайдерығыҙға мөрәжәғәт итегеҙ.",
+       "config-diff3-bad": "GNU diff3 табылманы.",
+       "config-git": "Git өлгөләрҙе контролләү системаһы табылды: <code>$1</code>.",
+       "config-git-bad": "Git өлгөләре менән идара итеү программаһы табылды?",
+       "config-imagemagick": "ImageMagick: <code>$1</code> табылды.\nФайлдарҙы тейәргә рөхсәт итһәгеҙ, рәсемдәрҙе миниатюр итеп күһәтеү мөминлеге бар.",
+       "config-gd": "Found GD graphics library built-in.\nImage thumbnailing will be enabled if you enable uploads.",
+       "config-no-scaling": "Эске китапхананы GD йәки ImageMagick табып булманы.\nМиниатюр рәсемдәр ҡарау мөмкин булмаясаҡ.",
+       "config-no-uri": "'''Хата:''' Ағымдағы URI билдәләп булмай.\nУрынлаштырыу өҙөлдө.",
+       "config-no-cli-uri": "'''Киҫәтеү''': параметр күрһәтелмәгән <code>--scriptpath</code>, килешеү байынса: <code>$1</code> .",
+       "config-using-server": "«<nowiki>$1</nowiki>» сервер исеме файҙаланыла.",
+       "config-using-uri": " \"<nowiki>$1$2</nowiki>\" сервер исеме файҙаланыла.",
+       "config-uploads-not-safe": "'''Иғтибар:''' (<code>$1</code>) күсереүҙәре өсөе ҡулланылған директория ирекле скриптар яһау өсөн бармай.  \nMediaWiki барлыҡ күсерелгән файлдарҙы тикшерһә лә, файлды күсереүҙән алда [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security бирешеүсәнлекте ябыу] тәҡдим ителә.",
+       "config-no-cli-uploads-check": "\"Иғтибар\" әйтмәйенсә тейәлеү өсөн каталог (<code>$1</code>) CLI  урынлаштырған мәлдә тиҙ боҙололоусанлыҡҡа, ирекле сценарийҙы үтәүгә тикшерелмәне.",
+       "config-brokenlibxml": "Системағыҙҙа  MediaWiki һәм башҡа веб-ҡушымталар мәғлүмәттәрен йәшерен щарралауы ихтимал булған  PHP һәм libxml2 версиялары бар. \nlibxml2  2.7.3  йәки юғарыраҡ версияға ([https://bugs.php.net/bug.php?id=45996 хата тураһында мәғлүмәттәр]) тиклем яңыртығыҙ.\nБәйләнеш өҙөлдө.",
+       "config-suhosin-max-value-length": "Suhosin ҡуйылған һәм  GET <code>length</code> параметрын  $1 байтҡаса кәметә.  MediaWiki-ның  ResourceLoader компоненты был сикләүҙе урап үтә, әммә был етештереүсәнлекте кәметә. Әгәр мөмкин булһа, 1024 асылындағы   <code>suhosin.get.max_value_length</code> йәки унан юғарыраҡ булған  <code>php.ini</code>, шулай уҡ  <code>$wgResourceLoaderMaxQueryLength</code> өсөн шундай уҡ  LocalSettings.php ҡуйырға була.",
+       "config-db-type": "Мәғлүмәт базаһы төрө:",
+       "config-db-host": "Мәғлүмәт базаһы хосты:",
+       "config-db-host-help": "Әгәр ҙә серверҙың база мәғлүмәттәре икенсе серверҙа урынлашһа, бында уның исемен йәки IP-адресын индерегеҙ.\nӘгәр ҙә һеҙ виртуаль хостингты ҡулланһағыҙ, һеҙҙең провайдерығыҙ  хостың дөрөҫ исемен үҙенең документацияһында күрһәтергә тейеш.\nӘгәр ҙә һеҙ системаны Windows аҫтына ҡуяһығыҙ һәм MySQL - ды ҡулланаһығыҙ икән, «localhost» исемле сервер эшләй алмаясаҡ. Был осраҡта 127.0.0.1 локаль  IP-адресығыҙҙы күрһәтергә тырышығыҙ.\nӘгәр ҙә һеҙ  PostgreSQL-ды  ҡулланаһығыҙ икән, был шаҡмаҡты сокет Unix аша инеү өсөн буш ҡалдырығыҙ.",
+       "config-db-host-oracle": "TNS мәғлүмәт базаһы:",
+       "config-db-host-oracle-help": "Ғәмәлдәге [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Local Connect Name] индерегеҙ;  tnsnames.ora файлы был инсталляция өсөн күренергә тейеш. <br /> Клиенттарҙың 10g версияһындағы һәм юғарыраҡ китапханаһын ҡулланғанда шулай уҡ атама биреү ысулын файҙаланыу мөмкинлеге бар   [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].",
+       "config-db-wiki-settings": "Был викиҙың идентификацияһы",
+       "config-db-name": "Мәғлүмәт базаһы исеме:",
+       "config-db-name-help": "Үҙегеҙҙең вики өсөн исем - идентификатор һайлағыҙ.\nИсемдә тултырылмаған урын булмаҫҡа тейеш.\nӘгәр һеҙ виртуаль хостингты ҡулланаһығыҙ икән, провайдер һеҙгә мәғлүмәттәр базаһының конкрет исемен бирер йәки идара итеү панеле ярҙамы менән мәғлүмәттәр базаһын булдырырға мөмкинлек бирер.",
+       "config-db-name-oracle": "Мәғлүмәт базаһы схемаһы",
+       "config-db-account-oracle-warn": "Oracle мәғлүмәттәр базаһы итеп ҡуйыуҙың өс юлы бар:\nӘгәр иҫәп яҙмаһын ҡуйыу процесында булдырырға теләһәгеҙ, зинһар, SYSDBA ҡуйыу өсөн иҫәп алыу ролен һәм веб-күҙәтеү мөмкинлеге булған иҫәп алыуҙың  теләгән вәкәләттәрен  күрһәтегеҙ. Шулай уҡ веб-күҙәтеү мөмкинлеге булған иҫәпте ҡулдан эшләргә һәм уны (әгәр схема объекттарын төҙөүгә кәрәкле рөхсәте бар икән) йәки ике иҫәп яҙмаһын, береһен - объекттар төҙөү хоҡуғы менән, икенсеһен веб-күҙәтеүҙе сикләүсе, күрһәтәһегеҙ. \nТейешле өҫтөнлөктәр менән иҫәп яҙмаһын булдырыу сценарийын ошо ҡоролма программаһының  «maintenance/oracle/» папкаһында табырға мөмкин. Сикләнгән иҫәп яҙмаһын файҫаланыу килешеү буйынса иҫәп яҙмаларының барлыҡ мөмкинлектәрен һүндереүгә килтереү ихтималлығын күҙ уңында тотоғоҙ.",
+       "config-db-install-account": "Көйләү өсөн иҫәп яҙмаһы",
+       "config-db-username": "Мәғлүмәт базаһын ҡулланыусы исеме",
+       "config-db-password": "Мәғлүмәт базаһының серһүҙе",
+       "config-db-install-username": "Ҡуйылыш процесында мәғлүмәттәр базаһына тоташтырыу өсөн файҙаланасаҡ ҡулланыусы исемен индерегеҙ.\nБыл исем MediaWiki ҡулланыусыныҡы түгел, был мәғлүмәттәр базаһы өсөн ҡулланыусы исеме.",
+       "config-db-install-password": "Ҡуйылыш процесында мәғлүмәттәр базаһына тоташтырыу өсөн файҙаланасаҡ ҡулланыусы исемен индерегеҙ.\nБыл исем MediaWiki ҡулланыусыныҡы түгел, ә мәғлүмәттәр базаһы өсөн ҡулланыусы исеме.",
+       "config-db-install-help": "Ҡуйылыш процесын көйләгәндә мәғлүмәттәр базаһына тоташтырыу өсөн файҙаланасаҡ  ҡулланыусы исемен һәм паролен индерегеҙ.",
+       "config-db-account-lock": "Ғәҙәти эш өсөн шул уҡ ҡулланыусы исемен һәм серһүҙен файҙаланырға",
+       "config-db-wiki-account": "Ғәҙәти эш өсөн иҫәп яҙмаһы",
+       "config-db-wiki-help": "Викиҙың ғәҙәттәге эше ваҡытында мәғлүмәт базаһына инеү өсөн файҙаланылған ҡулланыусы исемен һәм серһүҙен индерегеҙ. Әгәр бындай иҫәп яҙмаһы юҡ икән, ә ваҡытлыса яҙма етерлек өҫтөнлөктәргә эйә икән, ғәҙәттәге иҫәп яҙмаһы викиҙа эшләү өсөн кәрәкле минималь өҫтөнлөктәр менән булдырыласаҡ.",
+       "config-db-prefix": "Мәғлүмәт базаһы таблицаларының префиксы",
+       "config-db-prefix-help": "Әгәр һеҙгә бер мәғлүмәт базаһын бер нисә вики йәки MediaWiki һәм башҡа веб-ҡушымталар араһында бүлергә тура килһә, таблицалағы барлыҡ исемдәр өсөн перфикс өҫтәй алаһығыҙ. Ара ҡулланмағыҙ.\nБыл урын ғәҙәттә буш ҡала.",
+       "config-db-charset": "Мәғлүмәт базаһын кодлау",
+       "config-charset-mysql5-binary": "MySQL 4.1/5.0 бинарлы",
+       "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
+       "config-charset-mysql4": "MySQL 4.0 һәм UTF-8 үҙ-ара бәйләнешле",
+       "config-charset-help": "'''Иғтибар.''' Әгәр  '''кире тап килгән UTF-8''' урынына MySQL 4.1+ ҡулланаһығыҙ һәм <code>mysqldump</code> ярҙамында мәғлүмәт базаһының резерв күсермәләрен  файҙаланһағыҙ, ASCII булмаған символдар барыһы ла  могут яңылыш күрһәтелеп, резерв күсермәләре ҡулланыуға яраҡһыҙ буласаҡ!\n\n'''Бинар режимда''' MediaWiki базала юникод тексын  нимә яҙылған, шул килеш һаҡлаясаҡ.\nБыл UTF-8 режимында MySQL  булыуға ҡарағанда һөҙөмтәлерәк, сөнки Юникодтың символдар тупланмаһын тулыһынса ҡулланыу мөмкинлеген бирә. \n'''UTF-8 режимында''' MySQL мәғлүмәттәрегеҙҙең ниндәй символдар тупланмаһына ҡарауын беләсәк һәм уларҙы тейешенсә үҙгәртәсәк  (Ё хәрефе Е хәрефенән һуң киләсәк, ә  бинар режимдағыса Я-нан һуң түгел), әммә [//ru.wikipedia.org/wiki/ Юникодта бирелгән символдар#.D0.91.D0.B0.D0.B7.D0.BE.D0.B2.D0.B0.D1.8F_.D0.BC.D0.BD.D0.BE.D0.B3.D0.BE.D1.8F.D0.B7.D1.8B.D0.BA.D0.BE.D0.B2.D0.B0.D1.8F_.D0.BF.D0.BB.D0.BE.D1.81.D0.BA.D0.BE.D1.81.D1.82.D1.8C BMP] сигенән сығыусы символдарҙы һаҡларға рөхсәт итмәйәсәк.",
+       "config-mysql-old": "PostgreSQL $1 йәки тағы ла һуңыраҡ булған версия кәрәк. Һеҙҙә PostgreSQL $2 ҡуйылған.",
+       "config-db-port": "Мәғлүмәт базаһы порты:",
+       "config-db-schema": "MediaWiki өсөн схема:",
+       "config-db-schema-help": "Был схема ғәҙәттә яҡшы эшләй.\nУны, үҙегеҙгә кәрәк булһа ғына, үҙгәртегеҙ",
+       "config-pg-test-error": "Мәғлүмәт базаһына инеп булманы<strong>$1</strong>: $2",
+       "config-sqlite-dir": "SQLite мәғлүмәттәре директориһы:",
+       "config-sqlite-dir-help": "SQLite бөтә мәғлүмәттәрҙе бер файлда һаҡлай. \nҠуйған ваҡытта веб-сервер һеҙ күрһәткән директорияны уҡый алырға тейеш. \n\nУға Интернет аша инеү '''мөмкин түгел''', шуға ул PHP файлдар һаҡланған файл менән тап килмәҫкә тейеш.\nҠуйыусы бал директорияны <code>.htaccess</code> файлына яҙасаҡ, әгәр ул эшләмәһә, кемдер бөтөн мәғлүмәт базаһына инә аласаҡ. Был базала шулай уҡ ҡулланыусылар тураһында мәғлүмәт тә (электрон почта адрестары, серһүҙ хештары), шулай уҡ юйылған биттәр һәм вики тураһында башҡа йәшерен мәғлүмәттәр һаҡлана. \n\nБыл базаны, мөмкин булһа, ситтәрәк, мәҫәлән, <code>/var/lib/mediawiki/yourwiki</code> һаҡлағыҙ.",
+       "config-oracle-def-ts": "Килешеү буйынса таблица арауығы:",
+       "config-oracle-temp-ts": "Таблицаларҙың ваҡытлы киңлеге:",
+       "config-type-mysql": "MySQL (йәки тура килгән)",
+       "config-type-mssql": "Microsoft SQL Server",
+       "config-support-info": "MediaWiki -ла түбәндәге СУБД бар:\n\n$1\n\nӘгәр мәғлүмәт һаҡлау системаһын исемлектә күрмәһәгеҙ, рөхсәт алыу өсөн өҫтәге һылтанмалағы инструкция буйынса эш итегеҙ.",
+       "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] — MediaWiki-ҙың иҫ яҡшы эшләгән төп мәғлүмәттәр базаһы.  MediaWiki шулай уҡ MySQL-тап килгән [{{int:version-db-mariadb-url}} MariaDB] һәм [{{int:version-db-percona-url}} Percona Server] менән эшләй. ([http://www.php.net/manual/ru/mysql.installation.php MySQL-ярҙамында PHP туплау инструкцияһы])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] —  СУБД-ның популяр открыткаһы, MySQL өсөн альтернатива.\nТөҙәтелмәгән хаталар булыуы мөмкин, эш схемаһында ҡулланыу тәҡдим ителмәй. ([http://www.php.net/manual/ru/pgsql.installation.php  PostgreSQL рөхсәт ителгән РНР йыйыу инструкцияһы]).",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] — яҡшы һәм еңел мәғлүмәт базаһы системаһы. ([http://www.php.net/manual/ru/pdo.installation.php  собрать PHP  SQLite]  PDO менән эшләй торған инструкция)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] — предприятие масштабындаға коммерция базыһы. ([http://www.php.net/manual/ru/oci8.installation.php OCI8 ярҙамындағы РНР нисек йыйырға])",
+       "config-dbsupport-mssql": "* [{{int:version-db-oracle-url}} Oracle] — предприятие масштабындаға Windows өсөн коммерция базыһы. ([http://www.php.net/manual/ru/oci8.installation.php OCI8 ярҙамындағы РНР нисек йыйырға])",
+       "config-header-mysql": "MySQL көйләү",
+       "config-header-postgres": "PostgreSQL көйләү",
+       "config-header-sqlite": "SQLite көйләү",
+       "config-header-oracle": "Оракул көйләү",
+       "config-header-mssql": "Microsoft SQL Серверенең билдәле дәүмәлдәре",
+       "config-invalid-db-type": "Нигеҙ тибтарының дөрөҫ булмаған күрһәткестәре",
+       "config-missing-db-name": "Һеҙ мәғәнәне индерергә тейешһегеҙ «{{int:config-db-name}}».",
+       "config-missing-db-host": "Параметр мәғәнәһен индереү мотлаҡ «{{int:config-db-host}}».",
+       "config-missing-db-server-oracle": "Һеҙ бында мәғәнәне индерергә тейешһегеҙ «{{int:config-db-host-oracle}}».",
+       "config-invalid-db-server-oracle": "«$1» мәғлүмәттәр базаһының дөрөҫ булмаған TNS.\nЙә «TNS Name», йә «Easy Connect» ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm  Oracle атамалары ысулы]) ҡулланығыҙ.",
+       "config-invalid-db-name": "«$1» мәғлүмәттәр базаһының дөрөҫ булмаған префиксы. Тик ASCII  символдарын: (a-z, A-Z) хәрефтәрен, (0-9) һандарын, (_) аҫтына һыҙыу билдәһен һәм (-)дефисты ҡулланығыҙ.",
+       "config-invalid-db-prefix": "«$1» мәғлүмәттәр базаһының дөрөҫ булмаған префиксы. Тик ASCII (a-z, A-Z) хәрефтәрен, (0-9) һандарын, (_) аҫтына һыҙыу билдәһен һәм (-)дефисты ҡулланығыҙ.",
+       "config-connection-error": "$1.\n\nХостығыҙҙы, ҡулланыусы исемен һәм паролде тикшерегеҙ ҙә яңынан инеп ҡарағыҙ.",
+       "config-invalid-schema": "MediaWiki «$1» өсөн схема дөрөҫ түгел.\nБары тик ASCII символдарын (a-z, A-Z), цифрҙарҙы (0-9) һәм аҫҡы һыҙыҡты (_) ғына ҡулланығыҙ.",
+       "config-db-sys-create-oracle": "Яңы иҫәп-хисап яҙмаһын булдырыу өсөн урынлаштырыу программаһы тик SYSDBA ҡулланыу хуплана",
+       "config-db-sys-user-exists-oracle": "Иҫәп яҙмаһы \"$1\". SYSDBA яңы иҫәп-хисап яҙмаһын булдырыу өсөн генә ҡулланыла",
+       "config-postgres-old": "PostgreSQL $1 йәки тағы ла һуңыраҡ булған версия кәрәк. Һеҙҙә PostgreSQL $2 ҡуйылған.",
+       "config-mssql-old": "$1 йә һуңыраҡ версиянан Microsoft SQL Server кәрәк. Һеҙҙә $2 версияһы ҡуйылған.",
+       "config-sqlite-name-help": "Үҙегеҙҙең вики өсөн исем-идентификатор һайлағыҙ.\nДефисы һәм буш урын ҡалдырмағыҙ.\nЬыл юл SQLite файлының исемендә ҡулланыласаҡ.",
+       "config-sqlite-parent-unwritable-group": "<nowiki><code>$1</code></nowiki> мәғлүмәт директорияһын эшләп булманы, веб-серверҙың төп директорияны яҙырға хоҡуғы юҡ <nowiki><code>$2</code></nowiki>.\n\nУрынлаштырыусы ҡатнашыусының веб-серверын билдәләне.\n<nowiki><code>$3</code></nowiki> яҙма мөмкин булған директория эшләгеҙ һәм дауам итегеҙ.\nUnix/Linux системаһында түбәндәгене башҡарығыҙ:\n\n<pre>cd $2\nmkdir $3\nchgrp $4 $3\nchmod g+w $3</pre>",
+       "config-sqlite-parent-unwritable-nogroup": "<nowiki><code>$1</code></nowiki> мәғлүмәт директорияһын эшләп булманы, веб-серверҙың төп директорияны яҙырға хоҡуғы юҡ <nowiki><code>$2</code></nowiki>.\n\nУрынлаштырыусы ҡатнашыусының веб-серверын билдәләй алманы.\n<nowiki><code>$3</code></nowiki> яҙма мөмкин булған директория эшләгеҙ һәм дауам итегеҙ.\nUnix/Linux системаһында түбәндәгене башҡарығыҙ:\n\n<pre>cd $2 mkdir $3 chmod a+w $3</pre>",
+       "config-sqlite-mkdir-error": "«$1» мәғлүмәттәре өсөн директорий яһауҙа хата.\nУрынлашыуын тикшерегеҙ һәм тағы ла эшләп ҡарағыҙ.",
+       "config-sqlite-dir-unwritable": " «$1» каталогына яҙыу булдырыу мөмкин түгел. Веб - сервер был каталогка яҙа алһын өсөн, инеү юлы көйләгесен  үҙгәртегеҙ һәм тағы ла бер мәртәбә ҡабатлап ҡарағыҙ.",
+       "config-sqlite-connection-error": "$1.\n\nМәғлүмәт базаһының исемен һәм мәғлүмәт директорияһын тикшерегеҙ ҙә яңынан эшләп ҡарағыҙ.",
+       "config-sqlite-readonly": "<code>$1</code> файлы яҙыу өсөн ябыҡ.",
+       "config-sqlite-cant-create-db": "<code>$1</code> мәғлүмәт базаһы файлын яһап булмай.",
+       "config-sqlite-fts3-downgrade": "PHP өсөн FTS3 булышлығы юҡ — таблицаларҙы алып ташлайбыҙ",
+       "config-can-upgrade": "Мәғлүмәттәр базаһында MediaWiki таблицалары бар.\nУларҙы MediaWiki $1 итеп яңыртыу өсөн '''«Дауам итергә»''' төймәһенә баҫығыҙ.",
+       "config-upgrade-done": "Яңыртыу тамамланды.\n\nХәҙер [$1 викины ҡуллана башларға] мөмкин.\n\nӘгәр ҙә <code>LocalSettings.php</code> файлын яңынан яһарға теләһәгеҙ, аҫтағы төймәгә баҫығыҙ. Ҡуйғанда проблемалар булмаһа, был '''тәҡдим ителмәй'''.",
+       "config-upgrade-done-no-regenerate": "Яңыртыу тамамланды.\nХәҙер [$1 вики менән эш башлай] алаһығыҙ.",
+       "config-regenerate": "LocalSettings.php яңынан төҙөргә →",
+       "config-show-table-status": "«<code>SHOW TABLE STATUS</code>» һорауы эшләнмәне!",
+       "config-unknown-collation": "'''Иғтибар:''' Мәғлүмәт базаһы сортировканың танылмаған ҡағиҙәләрен ҡуллана.",
+       "config-db-web-account": "Веб-серверҙан мәғлүмәт базаһына инеү өсөн иҫәп яҙмаһы",
+       "config-db-web-help": "Викиҙың ғәҙәттәге эшендә веб - сервер файҙалана торған  мәғлүмәттәр базаһының серверына тоташтырыу өсөн ҡулланыусының исемен һәм серһүҙен һайлағыҙ.",
+       "config-db-web-account-same": "Ҡуйыу өсөн булған иҫәп яҙмаһын ҡулланырға",
+       "config-db-web-create": "Иҫәп яҙмаһы булмаһа - яһарға",
+       "config-db-web-no-create-privs": "Ҡуйылыш өсөн күрһәтелгән иҫәп яҙмағыҙҙың уны барлыҡҡа килтереү өсөн етерлек хоҡуҡтары юҡ. \nКүрһәтелгән иҫәп яҙма бында булырға тейеш инде.",
+       "config-mysql-engine": "Мәғлүмәт базаһы шыуҙырмаһы",
+       "config-mysql-innodb": "InnoDB",
+       "config-mysql-myisam": "MyISAM",
+       "config-mysql-myisam-dep": "\"Иғтибар\" Һеҙ MySQL мәғлүмәтен һаҡлау өсөн MyISAM механизмын һайланығыҙ. Түбәндәге сәбәптәр арҡаһында уны ҡулланыу тәҡдим ителмәй:\n* параллелизмда эшләп булмай;\n* башҡа механизмдар менән сағыштырғанда мәғлүмәттәр юғала;\n* MediaWiki коды  MyISAM үҙенсәләген иҫәпкә алмай.\n\nҺеҙҙең MySQL InnoDB менән яраҡлы эшләһә ошо механизмды һайларға тәҡдим итебеҙ.\n\nҺеҙҙең MySQL InnoDB менән яраҡһыҙ эшләһә  механизмды яңыртырға тәҡдим итебеҙ.",
+       "config-mysql-only-myisam-dep": "<strong>Иҫкәртеү:</strong> MyISAM — был компьютерҙә MySQL өсөн берҙән-бер асыҡ мәғлүмәттәр һаҡлау системаһы, һәм  MediaWiki менән берлектә ҡулланырға рөхсәт ителмәй,сөнки:\n* таблицаларҙы блокировкалау һөҙөмтәһендә параллелизмды көсһөҙ тота;\n* башҡа системаларға ҡарағанда, ватылыуға күберәк дусар ителгән;\n* MediaWiki код базаһы MyISAM -ды ғәҙәттәгесә эшкәртеп бөтә алмай\nҺеҙҙең MySQL  InnoDB -ды тотмай, бәлки, яңыртыу ваҡыты еткәндер.",
+       "config-mysql-engine-help": "Параллель рәүештә яҡшыраҡ эшләгәне өсөн '''InnoDB''' өҫтөнлөрәк.\n\nБер ҡулланыусы йәки төҙәтеүҙәр әҙ булғанда вики өсөн '''MyISAM'''тың тиҙлеге  шәберәк, әммә унда мәғлүмәт базаһы InnoDB-ҡа ҡарағанда йышыраҡ сафтан сыға.",
+       "config-mysql-charset": "Мәғлүмәт базаһын кодлау",
+       "config-mysql-binary": "Икеле",
+       "config-mysql-utf8": "UTF-8",
+       "config-mysql-charset-help": "'''Ике режим'''да MediaWiki  UTF-8 тексын мәғлүмәт базаһының бинарныхҡырында һаҡлай.\nБыл MySQL-дың''UTF-8 режим''ына ҡарағанда һөҙөмтәлерәк һәм Unicode символдарының тулы тупланмаһын ҡулланыу мөмкинлеген бирә. \n\n'''UTF-8 режимы'''нда MySQL мәғлүмәттәрегеҙҙең ниндәй кодировкала ятҡанын беләсәк һәм уларҙы тейешенсә сағылдырасаҡ, үҙгәртәсәк, әммә был символдарҙы юғарыраҡ [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes База күптеллелек киңлегендә] һаәлау мөмкинлеген бирәсәк.",
+       "config-mssql-auth": "Аутентификация төрө :",
+       "config-mssql-install-auth": "Ҡуйыу процесында мәғлүмәт базаһына инеү өсөн файҙаланылған төп нөсхәне тикшереү тибын һайлағыҙ. \n\nӘгәр «{{int:config-mssql-windowsauth}}» һайлаһығыҙ, ҡулланыусының веб-сервер эшләгән иҫәп яҙмаһы файҙаланыласаҡ.",
+       "config-mssql-web-auth": "Викиҙың ғәҙәттәге эше ваҡытында мәғлүмәттәр базаһы серверына инеү өсөн веб-сервер файҙаланған  төп нөсхәне тикшереү тибын һайлағыҙ. \n\nӘгәр «{{int:config-mssql-windowsauth}}» һайлаһығыҙ, ҡулланыусының веб-сервер эшләгән иҫәп яҙмаһы файҙаланыласаҡ.",
+       "config-mssql-sqlauth": "SQL Server ысынлығын тикшереү",
+       "config-mssql-windowsauth": "Windows нөсхәһен тикшереү",
+       "config-site-name": "Вики атамаһы:",
+       "config-site-name-help": "Исеме браузерҙың баш һүҙендә  һәм башҡа урындарҙа күрәнәсәк.",
+       "config-site-name-blank": "Сайт исемен яҙығыҙ",
+       "config-project-namespace": "Проекттың исемдәр арауығы:",
+       "config-ns-generic": "Проект",
+       "config-ns-site-name": "Викилағы кеүек исем: $1",
+       "config-ns-other": "Башҡа (күрһәтегеҙ)",
+       "config-ns-other-default": "MyWiki",
+       "config-project-namespace-help": "Вмкмпедия өлгөһөнә эйәреп, күп викиҙар үҙ ҡағиҙәләре биттәрен төп йөкмәтке битенән айырым,  '''«проект атамалары киңлегендә»''' һаҡлай.\nБыл киңлектәге барлыҡ биттәр атамалары һеҙ бында һорай алған билдәле перфикстан башлана.\nҒәҙәттә, был префикс вики исеменән барлыҡҡа килә, әммә тыныш билдәләре,  «#» йәки «:» символдары була алмай.",
+       "config-ns-invalid": "Күрһәтелгән исемдәр арауығы <nowiki>$1</nowiki> ярамай.\nПроекттың икенсе исемдәр арауығын күрһәтергә.",
+       "config-ns-conflict": "Күрһәтелгән исемдәр арауығы «<nowiki>$1</nowiki>» стандарт MediaWiki исемдәр арауығы менән бәхәстә.\nПроекттың икенсе исемдәр арауығын күрһәтегеҙ.",
+       "config-admin-box": "Администраторҙың иҫәп яҙмаһы",
+       "config-admin-name": "Һеҙҙең ҡуланыусы исеме",
+       "config-admin-password": "Серһүҙ:",
+       "config-admin-password-confirm": "Серһүҙҙе ҡабатлағыҙ",
+       "config-admin-help": "Бында үҙегеҙҙең ҡулланыусы исемегеҙҙе яҙығыҙ, мәҫәлән, «Азат Азатов». \nБыл исем викиға инеү өсөн буласаҡ.",
+       "config-admin-name-blank": "Администраторҙың ҡулланыусы исемен яҙығыҙ",
+       "config-admin-name-invalid": "Ҡулланыусының күрһәтелгән  «<nowiki>$1</nowiki>» исеме рөхсәт ителмәй. Уның икенсе исемен яҙығыҙ.",
+       "config-admin-password-blank": "Администраторҙың иҫәп яҙмаһы өсөн серһүҙҙе яҙығыҙ",
+       "config-admin-password-mismatch": "Һеҙ яҙған серһүҙҙәр тап килмәй.",
+       "config-admin-email": "Электрон почта адресығыҙ:",
+       "config-admin-email-help": "Электрон почтағыҙҙың адресын яҙығыҙ: һеҙҙең башҡа ҡулланыусыларҙан хәбәрҙәр алыу, серһүҙҙе тергеҙеү, шулай уҡ күҙәтеү исемлеге биттәрендәге үҙгәрештәр хаҡында белдереүҙәр алыу мөмкинлеге буласаҡ. Был юлды буш ҡалдырыға ла ярай.",
+       "config-admin-error-user": "«<nowiki>$1</nowiki>» исеме менән администраторҙың иҫәп яҙмаһы төҙөгәндә эске хата.",
+       "config-admin-error-password": "Хакимдың иҫәп яҙмаһы өсөн серһүҙ ҡуйғанда эске хата «<nowiki>$1</nowiki>»: <pre>$2</pre>",
+       "config-admin-error-bademail": "Электрон почта адресы дөрөҫ түгел",
+       "config-subscribe": "[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki яңы версиялары барлыҡҡа килеүен таратыу яңылыҡтарына] яҙылырға.",
+       "config-subscribe-help": "Был хәбәрҙәре аҙ булған таратыу исемлеге хәүефһеҙлек проблемалары тураһында хәбәрҙәр һәм яғы сығарылыштар өсөн анонс булараҡ файҙаланыла. \nҺеҙгә уға яҙылырға һәм яңы версиялар сыҡҡан һайын MediaWiki-ҙы яңыртып торорға кәрәк.",
+       "config-subscribe-noemail": "Һеҙ яңы сығарылыштар тураһында хәбәр ебәреү исемлегенә электрон адресығыҙҙы күрһәтмәй генә яҙылырға тырыштығыҙ.   \nӘгәр хәбәр ебәреү теҙмәһенә яҙылырға теләһәгеҙ,электрон адресығыҙҙы күрһәтегеҙ.",
+       "config-almost-done": "Һеҙ маҡсатҡа яҡын!\nҠалған көйләүҙәрҙе төшөрөп ҡалдырып, вики ҡуя алаһығыҙ.",
+       "config-optional-continue": "Төплөрәк көйләргә",
+       "config-optional-skip": "Етәр, вики ҡуйығыҙ",
+       "config-profile": "Ҡулланыусылар хоҡуҡтары профиле:",
+       "config-profile-wiki": "Асыҡ вики",
+       "config-profile-no-anon": "Иҫәп яҙмаһы булдырырға",
+       "config-profile-fishbowl": "Бары тик авторлашҡан мәхәррирҙәр өсөн",
+       "config-profile-private": "Ябыҡ вики",
+       "config-profile-help": "Ләкин,  MediaWiki  шыуҙырмаһын икенсе ысул менән файҙаланырға мөмкин, һәм асыҡ вики-эштең өҫтөн икәненә барыһын да ышандырып бөтөп булмай.\nҺеҙҙең һайлап алырға мөмкинселек бар.\nСайтта теркәлеү үтмәйенсә лә, модель '''«{{int:config-profile-wiki}}»''' һәр кемгә биттәрҙә үҙгәртеү эшләргә мөмкинселек бирә. Конфигурация '''{{int:config-profile-no-anon}}''' өҫтәлмә хисап тәьмин итә,  ләкин осраҡлы ҡатнашыусыларҙы ябыуы ихтимал.\nСценарий '''«{{int:config-profile-fishbowl}}»''' аныҡланған ҡатнашыусыларға мөхәррирләүҙе рөхсәт итә, ләкин һәр кем алырлыҡ битте ҡарау ҡала, шул иҫәптән үҙгәртеҙәр тарихын ҡарау. '''«{{int:config-profile-private}}»''' режимында биттәрҙе ҡарарға айырым ҡулланыусыларға ғына рөхсәт ителә, ҡайһы бер өлөштәренең мөхәррирләү хоҡуҡтары булыуы мөмкин. \n[//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights Ярашлы ҡулланма] урынлаштырғас,  хоҡуҡтарҙы сикләүсе ҡатмарлыраҡ схемаларҙы көйләргә була.",
+       "config-license": "Автор хоҡуҡтары һәм лицензиялар:",
+       "config-license-none": "Лицензияны аҫта яҙмағыҙ",
+       "config-license-cc-by-sa": "Creative Commons Attribution Share Alike",
+       "config-license-cc-by": "Ижади лицензия, атрибутикалар",
+       "config-license-cc-by-nc-sa": "Creative Commons Attribution Non-Commercial Share Alike",
+       "config-license-cc-0": "Creative Commons Zero (йәмәғәт милке)",
+       "config-license-gfdl": "GNU Free Documentation License 1.3 йәки яңырағы",
+       "config-license-pd": "Йәмәғәт милке",
+       "config-license-cc-choose": "Creative Commons бер лицензияны һайлағыҙ",
+       "config-license-help": "Күпселек дөйөм ҡулланыуҙағы викиҙар үҙ материалдарын [http://freedomdefined.org/Definition/Ru ирекле лицензия] шарттарында файҙаланыуға рөхсәт бирә.\nБыл берҙәмлек тойғоһон булдыррыға ярҙам итә, ҡатнашыу ваҡытын оҙайтыуға дәртләндерә. Әммә шәхси йәки корпоратив викиҙар өсөн бындай ихтыяж юҡ. \n\nӘгәр һеҙ Википедия текстарын файҙаланырға йәки Википедияға үҙ викиғыҙҙан текстар күсереү мөмкинлеге булыуын теләһәгеҙ, \n<strong>{{int:config-license-cc-by-sa}}</strong> һайлағыҙ.\nВикипедия элек  GNU Free Documentation License лицензияһын файҙалана ине.\nGFDL файҙаланыла ала, әммә ул аңлау өсөн ҡатмарлы һәм материалдарҙы ҡабатлап ҡулланыуҙы ауырлаштыра.",
+       "config-email-settings": "Электрон почта көйләүҙәре",
+       "config-enable-email": "e-mail сығыусы почтаны рәхсәт итергә",
+       "config-enable-email-help": "Электрон почта эшләһен өсөн [http://www.php.net/manual/ru/mail.configuration.php PHP көйләүҙәрен] башҡарырға кәрәк.\nӘгәр электорон поста мөмкинлектәре кәрәкмәһә, һүндерергә була.",
+       "config-email-user": "Ҡатнашыусынан ҡатнашыусыға почтаны рөхсәт итергә",
+       "config-email-user-help": "Әгәр профилдә тейешле көйләү булһа, бөтә ҡатнашыусыларға электрон хат ебәрергә рөхсәт итергә.",
+       "config-email-usertalk": "Ҡулланыусыларҙы уларҙың фекерләшеү битендәге хәбәрҙәр хаҡында белдереүҙәрҙе файҙаланыу",
+       "config-email-usertalk-help": "Ҡулланыусылар үҙ көйләүҙәрендә рөхсәт бирһә, уларға фекерләү биттәрендәге үҙгәрештәр хаҡында белдереүҙәр алырға рөхсәт итеү.",
+       "config-email-watchlist": "Күҙәтеү исемлеген үҙгәртеү хаҡында электрон почтаға белдереү ебәрергә",
+       "config-email-watchlist-help": "Ҡулланыусылар үҙ көйләүҙәрендә рөхсәт бирһә, уларға фекерләү биттәрендәге үҙгәрештәр хаҡында белдереүҙәр алырға рөхсәт итеү.",
+       "config-email-auth": "Электрон почта аша аутентификация (ҡулланыусы тәҡдим иткән идентификаторҙы тикшереү) үткәреү",
+       "config-email-auth-help": "Был опция ҡабыҙырған булһа, ҡатнашыусылар үҙ адресын раҫлап e-mail адресындағы һылтанма буйынса күсергә тейеш. Электорон йәшникте алыштырған осраҡта раҫлау талап ителә.Тик почта йәшниге раҫланған ҡатнашыусылар ғына хат ала.\nБыл опцияны почтаны урынһыҙ ҡулланыуҙарҙы булдырмаҫ өсөн ҡулланырға \"тәҡдим\" ителә.",
+       "config-email-sender": "Электрон почта адресығыҙ",
+       "config-email-sender-help": "Баһалама алыу өсөн электрон почта адресын яҙығыҙ. Унда кире ҡағылған баһаламалар ебәреләсәк.Почта серверы домен исемен дөрөҫ яҙыуҙы талап ите.",
+       "config-upload-settings": "Рәсем-һүрәттәрҙе һәм файлдарҙы тултырыу",
+       "config-upload-enable": "Файл тултырырға рөхсәт биреү",
+       "config-upload-help": "Файлды тейәргә рөхсәт итеү серверҙың хәүефһеҙлегенә янай. Өҫтәмә мәғлүмәт алыу өсөн Ҡулланманың [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security хәүефһеҙлек бүлеген] уҡығыҙ.",
+       "config-upload-deleted": "Юйылған файлдарға директория",
+       "config-upload-deleted-help": "Юйылған файлдар архивы һаҡланасаҡ  каталогты һайлағыҙ.\nИң шәп осраҡта, интернет селтәренән был каталогҡа инеү рөхсәте булырға тейеш түгел.",
+       "config-logo": "Логотип URL-ы :",
+       "config-logo-help": "MediaWiki стантарт биҙәү темаһының ситтәге панелендә 135x160 пикселдән торған логотип урынлаштырыла. Шул ҙурлыҡтағы рәсемде тейәгеҙ, һәм  URL адресын яҙығыҙ.\nЛогитип сағыштырмаса ошо юлдарҙа ятһа, <code>$wgStylePath</code> йәки <code>$wgScriptPath</code> кодын файҙалана алаһығыҙ.\nӘгәр логотип кәрәк булмаһа, был урында буш ҡалдырығыҙ.",
+       "config-instantcommons": "Instant Commons-ты тоҡандырырға",
+       "config-instantcommons-help": "[//www.mediawiki.org/wiki/InstantCommons Instant Commons] — Викимилектәге рәсем, тауыш һәм башҡа медиафайлдарҙы файҙаланыу функцияһы  ([//commons.wikimedia.org/ Wikimedia Commons]).\n MediaWiki функцияһы менән эшләү өсөн интернетҡа инеү мөмкинлеге кәрәк.\n\nInstant Commons тураһында өҫтәмә мәғлүмәтте, һәм башҡа көйләүҙәрҙе [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos Ҡулланмала] табырға була.",
+       "config-cc-error": "Creative Commons лицензияһын һайлау механизмы нәтижә бирмәне.\nЛицензия исемен ҡулдан яҙығыҙ.",
+       "config-cc-again": "Ҡабаттан һайлағыҙ",
+       "config-cc-not-chosen": "Creative Commons лицензияһының ҡулланырға теләгәнен һайлағыҙ һәм \"proceed\" төймәһенә баҫыҡыҙ.",
+       "config-advanced-settings": "Өҫтәлмә көйләүҙәр",
+       "config-cache-options": "Объекттарҙы кэшлау параматры",
+       "config-cache-help": "Объекттарҙы кэшлау MediaWiki-ның тиҙлеген арттырыу өсөн ҡулланыла. Ҙур һәм уртаса сайттар өсөн кэшлау ҡәтғи тәҡдим ителә, белекәй сайттар өсөн өҫтөнлөк бирелә.",
+       "config-cache-none": "Кэш ҡулланмайынса (фуккция юғалмай, әммә эре вики-сайттар әкренерәк эшләйәсәк)",
+       "config-cache-accel": "Объекттарҙы PHP кэшлау  (APC, XCache йәки WinCache)",
+       "config-cache-memcached": "Memcached ҡулланырға (өҫтәлмә көйләү талап итә)",
+       "config-memcached-servers": "Memcached серверҙары:",
+       "config-memcached-help": "Memcached ҡулланған IP-адрестар исемлеге.\nҺәр юлға бер генә адрес яҙып һанап сығығыҙ. \nМәҫәлән:\n\n 127.0.0.1:11211\n 192.168.1.25:1234",
+       "config-memcache-needservers": "Һеҙ Memcached кэшлауҙы һайланыҡыҙ, әммә сервер адресын яҙманығыҙ.",
+       "config-memcache-badip": "Һеҙ Memcached өсөн хата IP-адрес яҙҙығыҙ: $1.",
+       "config-memcache-noport": "Memcached: $1 өсөн порт күрһәтелмәгән.\nНиндәй порт икәнән белмәһәгеҙ, килешеү буйынса 11211.",
+       "config-memcache-badport": "Memcached порттары $1 һәм $2 араһында ярырға тейеш.",
+       "config-extensions": "Киңәйтеүҙәр",
+       "config-extensions-help": "Расширения MediaWiki, перечисленные выше, были найдены в каталоге <code>./extensions</code>.\n\nОни могут потребовать дополнительные настройки, но их можно включить прямо сейчас",
+       "config-skins": "Биҙәлеш темалары",
+       "config-skins-help": "Өҫтә һаналған биҙәү темалары һеҙҙең <code>./skins</code> каталогында табылды. Һеҙгә уларҙың берәүһен булһа ла эшләтергә һәм өндәшмәү буйынса ҡулланыласағын һайларға кәрәк.",
+       "config-skins-use-as-default": "Махсус әйтмәгәндә был биҙәлеү темаһын ҡулланырға",
+       "config-skins-missing": "Биҙәү темалары табылманы. Һеҙ яраҡлыһын ҡуйғансы, MediaWiki резерв теманы ҡулланасаҡ.",
+       "config-skins-must-enable-some": "Һеҙ иң кәмендә бер биҙәлеү темаһын эш өҫтөндә ҡалдырырға тейеш",
+       "config-skins-must-enable-default": "\n\nҺүҙһеҙ һайланған биҙәлеш темаһы теркәлергә тейеш.",
+       "config-install-alreadydone": "'''Иҫкәртеү:''' Һеҙ MediaWiki ҡуйҙығыҙ шикелле, әле быны икенсегә эшләйһегеҙ. Алдағы биткә күсегеҙ.",
+       "config-install-begin": "«{{int:config-continue}}» - бында баҫыу MediaWiki ҡуйыуҙы башлай.\nӘгәр һеҙ үҙгәреш индерергә теләһәгеҙ, баҫығыҙ: «{{int:config-back}}».",
+       "config-install-step-done": "Юҡ",
+       "config-install-step-failed": "килеп сыҡманы",
+       "config-install-extensions": "Шул иҫәптән киңәйтеүҙәр",
+       "config-install-database": "Мәғлүмәттәр базаһын  көйләү",
+       "config-install-schema": "Схемаға һалыу",
+       "config-install-pg-schema-not-exist": "PostgreSQL схемалары юҡ",
+       "config-install-pg-schema-failed": "Таблица эшләп булманы. Ҡулланыусы «$1» «$2»-се схема яҙа алыуына ышанырға.",
+       "config-install-pg-commit": "Үҙгәртеүҙәр индереү",
+       "config-install-pg-plpgsql": " PL/pgSQL телен тикшереү",
+       "config-pg-no-plpgsql": "Һеҙгә $1 мәғлүмәт базаһы өсөн PL/pgSQL тел яҡлауын ҡуйырға кәрәк",
+       "config-pg-no-create-privs": "Ҡуйыу өсөн күрһәтелгән иҫәп яҙмаһының иҫәп яҙмаһы булдырыу өсөн етерлек өҫтөнлөгө юҡ.",
+       "config-pg-not-in-role": "Веб-ҡулланыусының күрһәтелгән иҫәп яҙмаһы инде бар. Һеҙ ҡуйыу өсөн һайлаған иҫәп яҙмаһы супер ҡулланыусы яҙмаһы түгел һәм веб-ҡулланыусы роленә инмәй; шуға ла веб-ҡулланыусыныҡы булған объекттар төҙөп булмай\n\nMediaWiki хәҙерге ваҡытта таблицалар хужаһы веб-ҡулланыусы булыуын талап итә. Зинһар, веб-ҡулланыусы иҫәп яҙмаһы өсөн башҡа исем күрһәтегеҙ йәки, «артҡа» төймәһенә баҫып, ҡуйыу өсөн етерлек хоҡуҡтары булған ҡулланыусыны күрһәтегеҙ.",
+       "config-install-user": "Ҡулланыусының база дәүмәлдәрен теркәү",
+       "config-install-user-alreadyexists": "Ҡатнашыусы $1 бар инде",
+       "config-install-user-create-failed": "Ҡатнашыусы «$1» эшләү килеп сыҡманы: $2",
+       "config-install-user-grant-failed": "Ҡатнашыусы «$1»-гә хоҡуҡ биреү хата: $2",
+       "config-install-user-missing": "Күрһәтелгән ҡатнашыусы «$1» юҡ.",
+       "config-install-user-missing-create": "Күрһәтелгән ҡатнашыусы «$1» юҡ.\nӘгәр ҙә яһарға теләгәгеҙ булһа,зинһар, аҫта «Иҫәп яҙыуы булдырырға» билдәһе ҡуйығыҙ.",
+       "config-install-tables": "Таблица төҙөү",
+       "config-install-tables-exist": "'''Иҫкәртеү''': MediaWiki таблицаларының булыуы ихтимал. Икенсегә яһауҙы булдырмау.",
+       "config-install-tables-failed": "'''Хата''': Хата булыу сәбәпле таблица эшләнмәне: $1",
+       "config-install-interwiki": "Килешеү буйынса интервики таблицаларын тултырыу",
+       "config-install-interwiki-list": "Файл табылманы <code>interwiki.list</code>.",
+       "config-install-interwiki-exists": "'''Киҫәтеү''': интервики-таблицала яҙма бар.\nСтандарт исемлек төҙөү төшөп ҡалды.",
+       "config-install-stats": "Инициализация статистикаһы",
+       "config-install-keys": "Серле асҡыстар төҙөү",
+       "config-insecure-keys": "'''Киҫәтеү''' {{PLURAL:$2|1=Ҡатнашыусы булдырған хәүефһеҙлек асҡысы  $1 ышаныслы түгел}}. Асҡысты үҙгәртеү мөмкинлеген {{PLURAL:$2|1=}} ҡарағыҙ.",
+       "config-install-updates": "Кәрәкмәген яңыртыуҙар туҡтатылды",
+       "config-install-updates-failed": "<strong>Хата:</strong> Яңыртыуға асҡыс ҡуйыу түбәндәге хата менән тамамланды: $1",
+       "config-install-sysop": "Администратор иҫәп яҙмаһын булдырыу",
+       "config-install-subscribe-fail": "mediawiki-announce яҙылып булманы: $1",
+       "config-install-subscribe-notpossible": "cURL урынлаштырылмаған һәм опция асылмай<code>allow_url_fopen</code>.",
+       "config-install-mainpage": "Килешеү буйынса эстәлекле баш битте эшләү",
+       "config-install-extension-tables": "Ҡушымталар өсөн таблица эшләү",
+       "config-install-mainpage-failed": "Баш битте ҡуйып булмай:$1",
+       "config-install-done": "<strong>Ҡотлайбыҙ!</strong>\nMediaWiki уңышлы урынлаштырылды.\n\nФайл булдырылды <code>LocalSettings.php</code>.\nБыл файлда һеҙҙеү бөтә көәләүҙәр бар.\n\n\nАвтоматик тейәү башланмаһа йәки үҙегеҙ өҙһәгеҙ түбәндәге һылтанма буйынса тейәргә була:\n\n$3\n\n<strong>Иҫкәртмә</strong>: Файлда тейәмәйенсә сыҡһағыҙ киләсәктә бына эшләй алмайһығыҙ.\n\n\nӨҫтә яҙылғандарҙы эшләгәс<strong>[$2 беҙҙеү викиҙа инегеҙ]</strong>.",
+       "config-download-localsettings": "<code>LocalSettings.php</code> тейәргә",
        "config-help": "белешмә",
+       "config-help-tooltip": "асыр өсөн сиртегеҙ",
+       "config-nofile": "\"$1\" файлын табып булмай, ул юйылған.",
+       "config-extension-link": "Беҙҙең вики-проектта [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions ҡушымта] барлығын беләһегеҙме??\n\n[//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category категориялар буйынса ҡушымта] йәки [//www.mediawiki.org/wiki/Extension_Matrix матрица ҡсн ҡушымтаның] тулы исемлеген ҡарай алаһығыҙ.",
        "mainpagetext": "«MediaWiki» уңышлы рәүештә ҡоролдо.",
        "mainpagedocfooter": "Был вики менән эшләү тураһында мәғлүмәтте [//meta.wikimedia.org/wiki/Help:Contents ошонда] табып була.\n\n== Файҙалы сығанаҡтар ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Көйләүҙәр исемлеге (инг.)];\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki тураһында йыш бирелгән һорауҙар һәм яуаптар (инг.)];\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-ның яңы версиялары тураһында хәбәрҙәр алып тороу].\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]"
 }
index b68e244..1b42cdd 100644 (file)
@@ -68,6 +68,7 @@
        "config-ctype": "'''Фатальная памылка''': PHP мусіць быць скампіляваны з падтрымкай [http://www.php.net/manual/en/ctype.installation.php пашырэньня Ctype].",
        "config-iconv": "<strong>Непапраўная памылка:</strong> PHP мусіць быць скампіляваны з падтрымкай [http://www.php.net/manual/en/iconv.installation.php пашырэньня iconv].",
        "config-json": "<strong>Крытычная памылка:</strong> PHP быў скампіляваны без падтрымкі JSON.\nВы павінныя ўсталяваць або пашырэньне PHP JSON, або пашырэньне [http://pecl.php.net/package/jsonc PECL jsonc] перад усталёўкай MediaWiki.\n* Пашырэньне PHP уваходзіць у Red Hat Enterprise Linux (CentOS) 5 і 6, пры гэтым павінна быць падключана ў <code>/etc/php.ini</code> або <code>/etc/php.d/json.ini</code>.\n* Некаторыя дыстрыбутывы Linux, выдадзеныя пасьля траўня 2013 году, ня маюць пашырэньня PHP, замест яго пакуюць пашырэньне PECL як <code>php5-json</code> або <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Непапраўная памылка:</strong> PHP мусіць быць скампіляваны з падтрымкай [http://www.php.net/manual/en/mbstring.setup.php пашырэньня mbstring].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] усталяваны",
        "config-apc": "[http://www.php.net/apc APC] усталяваны",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] усталяваны",
        "config-install-mainpage": "Стварэньне галоўнай старонкі са зьместам па змоўчваньні",
        "config-install-extension-tables": "Стварэньне табліцаў для ўключаных пашырэньняў",
        "config-install-mainpage-failed": "Немагчыма ўставіць галоўную старонку: $1",
-       "config-install-done": "'''Віншуем!'''\nВы пасьпяхова ўсталявалі MediaWiki.\n\nПраграма ўсталяваньня стварыла файл <code>LocalSettings.php</code>.\nЁн утрымлівае ўсе Вашыя налады.\n\nВам неабходна загрузіць яго і захаваць у карэнную дырэкторыю Вашай вікі (у тую ж самую дырэкторыю, дзе знаходзіцца index.php). Загрузка павінна пачацца аўтаматычна.\n\nКалі загрузка не пачалася, ці Вы яе адмянілі, Вы можаце перазапусьціць яе націснуўшы на спасылку ніжэй:\n\n$3\n\n'''Заўвага''': калі Вы гэтага ня зробіце зараз, то створаны файл ня будзе даступны Вам потым, калі Вы выйдзеце з праграмы ўсталяваньня  без яго загрузкі.\n\nКалі Вы гэта зробіце, Вы можаце '''[$2 ўвайсьці ў Вашую вікі]'''.",
+       "config-install-done": "<strong>Віншуем!</strong>\nВы ўсталявалі MediaWiki.\n\nПраграма ўсталяваньня стварыла файл <code>LocalSettings.php</code>.\nЁн утрымлівае ўсе Вашыя налады.\n\nВам неабходна загрузіць яго і захаваць у карэнную дырэкторыю Вашай вікі (у тую ж самую дырэкторыю, дзе знаходзіцца index.php). Загрузка павінна пачацца аўтаматычна.\n\nКалі загрузка не пачалася, ці Вы яе адмянілі, Вы можаце перазапусьціць яе націснуўшы на спасылку ніжэй:\n\n$3\n\n<strong>Заўвага</strong>: калі Вы гэтага ня зробіце зараз, то створаны файл ня будзе даступны Вам потым, калі Вы выйдзеце з праграмы ўсталяваньня безь яго загрузкі.\n\nКалі Вы гэта зробіце, Вы можаце <strong>[$2 ўвайсьці ў Вашую вікі]</strong>.",
        "config-download-localsettings": "Загрузіць <code>LocalSettings.php</code>",
        "config-help": "дапамога",
        "config-help-tooltip": "націсьніце, каб разгарнуць",
        "config-nofile": "Файл «$1» ня знойдзены. Ці быў ён выдалены?",
        "config-extension-link": "Ці ведаеце вы, што вашая вікі падтрымлівае [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions пашырэньні]?\n\nВы можаце праглядзець [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category пашырэньні паводле катэгорыяў].",
-       "mainpagetext": "'''MediaWiki пасьпяхова ўсталяваная.'''",
+       "mainpagetext": "<strong>MediaWiki была ўсталяваная.</strong>",
        "mainpagedocfooter": "Глядзіце [//meta.wikimedia.org/wiki/Help:Contents дапаможнік карыстальніка] для атрыманьня інфармацыі па карыстаньні вікі-праграмамі.\n\n== З чаго пачаць ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Сьпіс парамэтраў канфігурацыі]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Частыя пытаньні MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Рассылка паведамленьняў пра зьяўленьне новых вэрсіяў MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Пераклад MediaWiki на вашую мову]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Даведайцеся, як змагацца з спамам у вашай вікі]"
 }
index c9e96ed..02e840b 100644 (file)
@@ -73,6 +73,7 @@
        "config-missing-db-host": "আপনাকে অবশ্যই \"{{int:config-db-host}}\"-এর জন্য একটি মান প্রবেশ করাতে হবে।",
        "config-missing-db-server-oracle": "আপনাকে অবশ্যই \"{{int:config-db-host-oracle}}\"-এর জন্য একটি মান প্রবেশ করাতে হবে।",
        "config-connection-error": "$1।\n\n\nদয়া করে প্রস্তাবকারী, ব্যবহারকারী নাম ও পাসওয়ার্ড দেখুন এবং পুনরায় চেষ্টা করুন।",
+       "config-regenerate": "LocalSettings.php পুনরূত্পাদিত করুন →",
        "config-mysql-engine": "সংরক্ষণ ইঞ্জিন:",
        "config-mysql-innodb": "ইনোডিবি",
        "config-mysql-myisam": "মাইআইএসএএম",
index 757e2e2..daaf663 100644 (file)
@@ -46,7 +46,7 @@
        "config-mssql-auth": "Аутентификацин тайп:",
        "config-site-name": "Викин цӀе:",
        "config-site-name-blank": "Язъе сайтан цӀе.",
-       "config-project-namespace": "ЦÓ\80еÑ\80ийн Ð°Ð½Ð° Ð¿Ñ\80оекÑ\82ан:",
+       "config-project-namespace": "Ð\9fÑ\80оекÑ\82ан Ñ\86Ó\80еÑ\80ийн Ð¼ÐµÑ\82Ñ\82иг:",
        "config-ns-generic": "Проект",
        "config-ns-other-default": "MyWiki",
        "config-admin-password": "Пароль:",
index de1f03f..905e326 100644 (file)
@@ -7,7 +7,8 @@
                        "아라",
                        "Matěj Grabovský",
                        "Paxt",
-                       "Matěj Suchánek"
+                       "Matěj Suchánek",
+                       "LordMsz"
                ]
        },
        "config-desc": "Instalační program pro MediaWiki",
        "config-env-php": "Je nainstalováno PHP $1.",
        "config-env-hhvm": "Je nainstalováno HHVM $1.",
        "config-unicode-using-intl": "Pro normalizaci Unicode se používá [http://pecl.php.net/intl PECL rozšíření intl].",
-       "config-unicode-pure-php-warning": "'''Upozornění''': Není dostupné [http://pecl.php.net/intl PECL rozšíření intl] pro normalizaci Unicode, bude se využívat pomalá implementace v čistém PHP.\nPokud provozujete wiki s velkou návštěvností, měli byste si přečíst něco o [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalizaci Unicode].",
-       "config-unicode-update-warning": "'''Upozornění''': Nainstalovaná verze vrstvy pro normalizaci Unicode používá starší verzi knihovny [http://site.icu-project.org/ projektu ICU].\nPokud vám aspoň trochu záleží na používání Unicode, měli byste [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations ji aktualizovat].",
+       "config-unicode-pure-php-warning": "<strong>Upozornění:</strong> Není dostupné [http://pecl.php.net/intl PECL rozšíření intl] pro normalizaci Unicode, bude se využívat pomalá implementace v čistém PHP.\nPokud provozujete wiki s velkou návštěvností, měli byste si přečíst něco o [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalizaci Unicode].",
+       "config-unicode-update-warning": "<strong>Upozornění:</strong> Nainstalovaná verze vrstvy pro normalizaci Unicode používá starší verzi knihovny [http://site.icu-project.org/ projektu ICU].\nPokud vám aspoň trochu záleží na používání Unicode, měli byste [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations ji aktualizovat].",
        "config-no-db": "Nepodařilo se nalézt vhodný databázový ovladač! Musíte nainstalovat databázový ovladač pro PHP.\n{{PLURAL:$2|Je podporován následující typ databáze|Jsou podporovány následující typy databází}}: $1.\n\nPokud jste si PHP přeložili sami, překonfigurujte ho se zapnutým databázovým klientem, například pomocí <code>./configure --with-mysql</code>.\nPokud jste PHP nainstalovali z balíčku Debian či Ubuntu, potřebujete nainstalovat také modul <code>php5-mysql</code>.",
-       "config-outdated-sqlite": "'''Upozornění''': Máte SQLite $1, které je starší než minimálně vyžadovaná verze $2. SQLite nebude dostupné.",
-       "config-no-fts3": "'''Upozornění''': SQLite bylo přeloženo bez [//sqlite.org/fts3.html modulu FTS3], funkce pro vyhledávání zde nebudou dostupné.",
-       "config-mbstring": "'''Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!'''\nToto nastavení způsobuje chyby a může nepředvídatelně poškozovat vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
+       "config-outdated-sqlite": "<strong>Upozornění:</strong> Máte SQLite $1, které je starší než minimálně vyžadovaná verze $2. SQLite nebude dostupné.",
+       "config-no-fts3": "<strong>Upozornění:</strong> SQLite bylo přeloženo bez [//sqlite.org/fts3.html modulu FTS3], funkce pro vyhledávání zde nebudou dostupné.",
+       "config-mbstring": "<strong>Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!</strong>\nToto nastavení způsobuje chyby a může nepředvídatelně poškozovat vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
        "config-xml-bad": "Chybí XML modul pro PHP.\nMediaWiki potřebuje funkce v tomto modulu a v této konfiguraci nebude fungovat.\nMožná si budete muset nainstalovat RPM balíček php-xml.",
-       "config-pcre-old": "'''Kritická chyba:''' Je vyžadováno PCRE verze $1 nebo novější.\nVaše binárka PHP obsahuje PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Více informací.]",
-       "config-pcre-no-utf8": "'''Kritická chyba''': PHP modul PCRE byl zřejmě přeložen bez podpory PCRE_UTF8.\nMediaWiki vyžaduje ke správné funkci podporu UTF-8.",
+       "config-pcre-old": "<strong>Kritická chyba:</strong> Je vyžadováno PCRE verze $1 nebo novější.\nVaše binárka PHP obsahuje PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Více informací.]",
+       "config-pcre-no-utf8": "<strong>Kritická chyba:</strong> PHP modul PCRE byl zřejmě přeložen bez podpory PCRE_UTF8.\nMediaWiki vyžaduje ke správné funkci podporu UTF-8.",
        "config-memory-raised": "<code>memory_limit</code> v PHP byl nastaven na $1, zvýšen na $2.",
-       "config-memory-bad": "'''Upozornění:''' <code>memory_limit</code> je v PHP nastaven na $1.\nTo je pravděpodobně příliš málo.\nInstalace může selhat!",
-       "config-ctype": "'''Kritická chyba''': PHP musí být přeloženo s podporou pro [http://www.php.net/manual/en/ctype.installation.php rozšíření Ctype].",
-       "config-iconv": "'''Kritická chyba''': PHP musí být přeloženo s podporou pro [http://www.php.net/manual/en/iconv.installation.php rozšíření iconv].",
-       "config-json": "'''Kritická chyba:''' PHP bylo přeloženo bez podpory JSON.\nPřed instalací MediaWiki musíte buď nainstalovat rozšíření PHP JSON nebo rozšíření [http://pecl.php.net/package/jsonc PECL jsonc].\n* Rozšíření PHP je součástí Red Hat Enterprise Linux (CentOS) 5 a 6, avšak musí se povolit v <code>/etc/php.ini</code> nebo <code>/etc/php.d/json.ini</code>.\n* V některých linuxových distribucích vydaných po květnu 2013 může toto rozšíření PHP chybět a místo toho mohou používat rozšíření PECL jako <code>php5-json</code> nebo <code>php-pecl-jsonc</code>.",
+       "config-memory-bad": "<strong>Upozornění:</strong> <code>memory_limit</code> je v PHP nastaven na $1.\nTo je pravděpodobně příliš málo.\nInstalace může selhat!",
+       "config-ctype": "<strong>Kritická chyba:</strong> PHP musí být přeloženo s podporou pro [http://www.php.net/manual/en/ctype.installation.php rozšíření Ctype].",
+       "config-iconv": "<strong>Kritická chyba:</strong> PHP musí být přeloženo s podporou pro [http://www.php.net/manual/en/iconv.installation.php rozšíření iconv].",
+       "config-json": "<strong>Kritická chyba:</strong> PHP bylo přeloženo bez podpory JSON.\nPřed instalací MediaWiki musíte buď nainstalovat rozšíření PHP JSON nebo rozšíření [http://pecl.php.net/package/jsonc PECL jsonc].\n* Rozšíření PHP je součástí Red Hat Enterprise Linux (CentOS) 5 a 6, avšak musí se povolit v <code>/etc/php.ini</code> nebo <code>/etc/php.d/json.ini</code>.\n* V některých linuxových distribucích vydaných po květnu 2013 může toto rozšíření PHP chybět a místo toho mohou používat rozšíření PECL jako <code>php5-json</code> nebo <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Kritická chyba:</strong> PHP musí být přeloženo s podporou pro [http://www.php.net/manual/en/mbstring.setup.php rozšíření mbstring].",
        "config-xcache": "Je nainstalována [http://xcache.lighttpd.net/ XCache]",
        "config-apc": "Je nainstalováno [http://www.php.net/apc APC]",
        "config-wincache": "Je nainstalována [http://www.iis.net/download/WinCacheForPhp WinCache]",
        "config-no-cache-apcu": "<strong>Upozornění:</strong> Nebylo nalezeno [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache], ani [http://www.iis.net/download/WinCacheForPhp WinCache].\nKešování objektů bude vypnuto.",
-       "config-mod-security": "'''Upozornění''': váš webový server má zapnuto [http://modsecurity.org/ mod_security]. Při chybné konfiguraci může způsobovat potíže MediaWiki či dalším programům, které umožňují ukládat libovolný obsah.\nPokud narazíte na náhodné chyby, podívejte se do [http://modsecurity.org/documentation/ dokumentace mod_security] nebo kontaktujte technickou podporu vašeho poskytovatele.",
+       "config-mod-security": "<strong>Upozornění:</strong> váš webový server má zapnuto [http://modsecurity.org/ mod_security]/mod_security2. Mnoho běžných konfigurací bude způsobovat potíže MediaWiki a dalším programům, které umožňují ukládat libovolný obsah.\nPokud je to možné, mělo by se to vypnout. Jinak se v případě, že narazíte na náhodné chyby, podívejte do [http://modsecurity.org/documentation/ dokumentace mod_security] nebo kontaktujte technickou podporu vašeho poskytovatele.",
        "config-diff3-bad": "Nebyl nalezen GNU diff3.",
        "config-git": "Nalezen software pro správu verzí Git: <code>$1</code>.",
        "config-git-bad": "Software pro správu verzí Git nebyl nalezen.",
        "config-imagemagick": "Nalezen ImageMagick: <code>$1</code>.\nPokud povolíte načítání souborů, bude zapnuto vytváření náhledů.",
        "config-gd": "Nalezena vestavěná grafická knihovna GD.\nPokud povolíte načítání souborů, bude zapnuto vytváření náhledů.",
        "config-no-scaling": "Nebyla nalezena knihovna GD ani ImageMagick.\nVytváření náhledů bude vypnuto.",
-       "config-no-uri": "'''Chyba:''' Nepodařilo se určit aktuální URI.\nInstalace přerušena.",
-       "config-no-cli-uri": "<strong>Upozornění</strong>: Nebylo uvedeno <code>--scriptpath</code>, používá se implicitní hodnota: <code>$1</code>.",
+       "config-no-uri": "<strong>Chyba:</strong> Nepodařilo se určit aktuální URI.\nInstalace přerušena.",
+       "config-no-cli-uri": "<strong>Upozornění:</strong> Nebylo uvedeno <code>--scriptpath</code>, používá se implicitní hodnota: <code>$1</code>.",
        "config-using-server": "Použito jméno serveru „<nowiki>$1</nowiki>“.",
        "config-using-uri": "Použito URL serveru „<nowiki>$1$2</nowiki>“.",
-       "config-uploads-not-safe": "'''Upozornění:''' Váš výchozí adresář pro načítání souborů <code>$1</code> umožňuje spouštění libovolných skriptů.\nPřestože MediaWiki všechny načítané soubory kontroluje proti bezpečnostním hrozbám, je důrazně doporučeno [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security tuto bezpečnostní díru zacelit] před povolením načítání souborů.",
-       "config-no-cli-uploads-check": "'''Upozornění:''' Váš výchozí adresář pro načítané soubory (<code>$1</code>) se při instalaci z příkazového řádku nekontroluje na bezpečnostní hrozbu provádění libovolných skriptů.",
+       "config-uploads-not-safe": "<strong>Upozornění:</strong> Váš výchozí adresář pro načítání souborů <code>$1</code> umožňuje spouštění libovolných skriptů.\nPřestože MediaWiki všechny načítané soubory kontroluje proti bezpečnostním hrozbám, je důrazně doporučeno [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security tuto bezpečnostní díru zacelit] před povolením načítání souborů.",
+       "config-no-cli-uploads-check": "<strong>Upozornění:</strong> Váš výchozí adresář pro načítané soubory (<code>$1</code>) se při instalaci z příkazového řádku nekontroluje na bezpečnostní hrozbu provádění libovolných skriptů.",
        "config-brokenlibxml": "Váš systém obsahuje kombinaci verzí PHP a libxml2, která je chybná a může v MediaWiki a dalších webových aplikacích způsobovat skryté poškozování dat.\nAktualizujte na libxml2 2.7.3 nebo novější ([https://bugs.php.net/bug.php?id=45996 chyba evidovaná u PHP]).\nInstalace přerušena.",
        "config-suhosin-max-value-length": "Je nainstalován Suhosin, který omezuje délku parametrů GET na $1 bajtů.\nKomponenta ResourceLoader z MediaWiki dokáže s tímto omezením pracovat, ale sníží to výkon.\nPokud to je alespoň trochu možné, měli byste v <code>php.ini</code> nastavit <code>suhosin.get.max_value_length</code> na 1024 nebo vyšší a na stejnou hodnotu nastavit v <code>LocalSettings.php</code> proměnnou <code>$wgResourceLoaderMaxQueryLength</code>.",
        "config-db-type": "Typ databáze:",
        "config-charset-mysql5-binary": "MySQL 4.1/5.0 binární",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-charset-mysql4": "MySQL 4.0 zpětně kompatibilní UTF-8",
-       "config-charset-help": "'''Upozornění:''' Pokud použijete '''zpětně kompatibilní UTF-8''' na MySQL 4.1+ a následně zazálohujete databázi pomocí <code>mysqldump</code>, může to zničit všechny ne-ASCII znaky, což nevratně poškodí vaše zálohy!\n\nV '''binárním režimu''' ukládá MediaWiki text v UTF-8 do databáze v binárních sloupcích.\nTo je výkonnější než UTF-8 režim MySQL a umožňuje využít plný rozsah znaků Unicode.\nV '''režimu UTF-8''' bude MySQL znát znakovou sadu vašich dat a může je příslušně zobrazovat a převádět,\nale neumožní vám uložit znaky mimo [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
-       "config-mysql-old": "Je vyžadováno MySQL $1 nebo novější, vy máte $2.",
+       "config-charset-help": "<strong>Upozornění:</strong> Pokud použijete <strong>zpětně kompatibilní UTF-8<strong> na MySQL 4.1+ a následně zazálohujete databázi pomocí <code>mysqldump</code>, může to zničit všechny ne-ASCII znaky, což nevratně poškodí vaše zálohy!\n\nV <strong>binárním režimu</strong> ukládá MediaWiki text v UTF-8 do databáze v binárních sloupcích.\nTo je výkonnější než UTF-8 režim MySQL a umožňuje využít plný rozsah znaků Unicode.\nV <strong>režimu UTF-8</strong> bude MySQL znát znakovou sadu vašich dat a může je příslušně zobrazovat a převádět,\nale neumožní vám uložit znaky mimo [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
+       "config-mysql-old": "Je vyžadováno MySQL $1 nebo novější. Vy máte $2.",
        "config-db-port": "Databázový port:",
        "config-db-schema": "Schéma pro MediaWiki:",
        "config-db-schema-help": "Toto schéma zpravidla stačí.\nMěňte ho, jen pokud víte, že je to potřeba.",
        "config-upgrade-done-no-regenerate": "Aktualizace byla dokončena.\n\nSvou wiki teď můžete [$1 začít používat].",
        "config-regenerate": "Přegenerovat LocalSettings.php →",
        "config-show-table-status": "Dotaz <code>SHOW TABLE STATUS</code> se nezdařil!",
-       "config-unknown-collation": "'''Upozornění:''' Databáze používá nerozpoznané řazení.",
+       "config-unknown-collation": "<strong>Upozornění:</strong> Databáze používá nerozpoznané řazení.",
        "config-db-web-account": "Databázový účet pro webový přístup",
        "config-db-web-help": "Zvolte uživatelské jméno a heslo, které bude webový server používat pro připojení k databázovému serveru při běžném provozu wiki.",
        "config-db-web-account-same": "Použít stejný účet jako pro instalaci",
        "config-mysql-engine": "Typ úložiště:",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
-       "config-mysql-myisam-dep": "'''Upozornění''': Jako typ úložiště pro MySQL jste zvolili MyISAM, které není pro použití v MediaWiki doporučeno, neboť:\n* stěží podporuje současný přístup kvůli zamykání tabulek,\n* je náchylnější na poškození dat než jiná úložiště,\n* kód MediaWiki nepodporuje MyISAM vždy tak dobře, jak by měl.\n\nPokud vaše instalace MySQL podporuje InnoDB, důrazně doporučujeme použít spíše to.\nPokud vaše instalace MySQL InnoDB nepodporuje, možná je čas na aktualizaci.",
-       "config-mysql-only-myisam-dep": "'''Upozornění:''' Jediným dostupným úložištěm dat pro MySQL je MyISAM, který se k užití s MediaWiki nedoporučuje, neboť:\n* téměř nepodporuje paralelní přístup kvůli zamykání tabulek,\n* oproti jiným formátům je náchylnější k poškození,\n* MediaWiki nepodporuje MyISAM tak dobře, jak by bylo třeba.\n\nVaše instalace MySQL nepodporuje InnoDB, možná je na čase upgradovat.",
+       "config-mysql-myisam-dep": "<strong>Upozornění:</strong> Jako typ úložiště pro MySQL jste zvolili MyISAM, které není pro použití v MediaWiki doporučeno, neboť:\n* stěží podporuje současný přístup kvůli zamykání tabulek,\n* je náchylnější na poškození dat než jiná úložiště,\n* kód MediaWiki nepodporuje MyISAM vždy tak dobře, jak by měl.\n\nPokud vaše instalace MySQL podporuje InnoDB, důrazně doporučujeme použít spíše to.\nPokud vaše instalace MySQL InnoDB nepodporuje, možná je čas na aktualizaci.",
+       "config-mysql-only-myisam-dep": "<strong>Upozornění:</strong> Jediným dostupným úložištěm dat pro MySQL je MyISAM, který se k užití s MediaWiki nedoporučuje, neboť:\n* téměř nepodporuje paralelní přístup kvůli zamykání tabulek,\n* oproti jiným formátům je náchylnější k poškození,\n* MediaWiki nepodporuje MyISAM tak dobře, jak by bylo třeba.\n\nVaše instalace MySQL nepodporuje InnoDB, možná je na čase upgradovat.",
        "config-mysql-engine-help": "'''InnoDB''' je téměř vždy nejlepší volba, neboť má dobrou podporu současného přístupu.\n\n'''MyISAM''' může být rychlejší u instalací pro jednoho uživatele nebo jen pro čtení.\nDatabáze MyISAM bývají poškozeny častěji než databáze InnoDB.",
        "config-mysql-charset": "Znaková sada databáze:",
        "config-mysql-binary": "Binární",
        "config-install-mainpage": "Vytváří se počáteční obsah hlavní strany",
        "config-install-extension-tables": "Vytvářejí se tabulky pro zapnutá rozšíření",
        "config-install-mainpage-failed": "Nepodařilo se vložit hlavní stranu: $1",
-       "config-install-done": "'''Gratulujeme!'''\nÚspěšně jste nainstalovali MediaWiki.\n\nInstalátor vytvořil soubor <code>LocalSettings.php</code>.\nTen obsahuje veškerou vaši konfiguraci.\n\nBudete si ho muset stáhnout a uložit do základního adresáře vaší instalace wiki (do stejného adresáře jako soubor index.php). Stažení souboru se mělo spustit automaticky.\n\nPokud se vám stažení nenabídlo nebo jste ho zrušili, můžete ho spustit znovu kliknutím na následující odkaz:\n\n$3\n\n'''Poznámka''': Pokud to neuděláte hned, tento vygenerovaný konfigurační soubor nebude později dostupný, pokud instalaci opustíte, aniž byste si ho stáhli.\n\nAž to dokončíte, můžete '''[$2 vstoupit do své wiki]'''.",
+       "config-install-done": "<strong>Gratulujeme!</strong>\nNainstalovali jste MediaWiki.\n\nInstalátor vytvořil soubor <code>LocalSettings.php</code>.\nTen obsahuje veškerou vaši konfiguraci.\n\nBudete si ho muset stáhnout a uložit do základního adresáře vaší instalace wiki (do stejného adresáře jako soubor index.php). Stažení souboru se mělo spustit automaticky.\n\nPokud se vám stažení nenabídlo nebo jste ho zrušili, můžete ho spustit znovu kliknutím na následující odkaz:\n\n$3\n\n<strong>Poznámka</strong>: Pokud to neuděláte hned, tento vygenerovaný konfigurační soubor nebude později dostupný, pokud instalaci opustíte, aniž byste si ho stáhli.\n\nAž to dokončíte, můžete <strong>[$2 vstoupit do své wiki]</strong>.",
        "config-download-localsettings": "Stáhnout <code>LocalSettings.php</code>",
        "config-help": "nápověda",
        "config-help-tooltip": "rozbalíte kliknutím",
        "config-nofile": "Soubor „$1“ nelze nalézt. Byl smazán?",
        "config-extension-link": "Věděli jste, že vaše wiki podporuje [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions rozšíření]?\n\nMůžete si prohlédnout [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category seznam rozšíření po kategoriích].",
-       "mainpagetext": "'''MediaWiki byla úspěšně nainstalována.'''",
+       "mainpagetext": "<strong>MediaWiki byla úspěšně nainstalována.</strong>",
        "mainpagedocfooter": "[//meta.wikimedia.org/wiki/Help:Contents Uživatelská příručka] vám napoví, jak používat MediaWiki.\n\n== Začínáme ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Nastavení konfigurace]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Často kladené otázky o MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce E-mailová konference oznámení MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Překlad MediaWiki do vašeho jazyka]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Naučte se bojovat se spamem na vaší wiki]"
 }
index 2516a16..5a1e1c4 100644 (file)
@@ -76,6 +76,7 @@
        "config-ctype": "'''Fataler Fehler:''' PHP muss mit Unterstützung für das [http://www.php.net/manual/de/ctype.installation.php Modul ctype] kompiliert werden.",
        "config-iconv": "<strong>Fatal:</strong> PHP muss mit Support für die [http://www.php.net/manual/en/iconv.installation.php iconv-Erweiterung] kompiliert werden.",
        "config-json": "<strong>Fataler Fehler:</strong> PHP wurde ohne Unterstützung für JSON kompiliert.\nVor der Installation von MediaWiki muss entweder die PHP-JSON- oder die [http://pecl.php.net/package/jsonc PECL-jsonc]-Erweiterung installieren werden.\n* Die PHP-Erweiterung ist in Red Hat Enterprise Linux (CentOS) 5 und 6 enthalten, muss jedoch in <code>/etc/php.ini</code> oder <code>/etc/php.d/json.ini</code> aktiviert werden.\n* Einige Linux-Distributionen, die nach Mai 2013 veröffentlicht wurden, nutzen nicht mehr die PHP-Erweiterung, sondern stattdessen die PECL-Erweiterung als <code>php5-json</code> oder <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Fatal:</strong> PHP muss mit Unterstützung für die [http://www.php.net/manual/de/mbstring.setup.php mbstring-Erweiterung] kompiliert werden.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] ist installiert",
        "config-apc": "[http://www.php.net/apc APC] ist installiert",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] ist installiert",
index 6fa5930..b97cc96 100644 (file)
@@ -60,6 +60,7 @@
        "config-ctype": "<strong>Fatal:</strong> PHP must be compiled with support for the [http://www.php.net/manual/en/ctype.installation.php Ctype extension].",
        "config-iconv": "<strong>Fatal:</strong> PHP must be compiled with support for the [http://www.php.net/manual/en/iconv.installation.php iconv extension].",
        "config-json": "<strong>Fatal:</strong> PHP was compiled without JSON support.\nYou must install either the PHP JSON extension or the [http://pecl.php.net/package/jsonc PECL jsonc] extension before installing MediaWiki.\n* The PHP extension is included in Red Hat Enterprise Linux (CentOS) 5 and 6, though must be enabled in <code>/etc/php.ini</code> or <code>/etc/php.d/json.ini</code>.\n* Some Linux distributions released after May 2013 omit the PHP extension, instead packaging the PECL extension as <code>php5-json</code> or <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Fatal:</strong> PHP must be compiled with support for the [http://www.php.net/manual/en/mbstring.setup.php mbstring extension].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] is installed",
        "config-apc": "[http://www.php.net/apc APC] is installed",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] is installed",
index 0653a72..d70571d 100644 (file)
@@ -6,7 +6,8 @@
                        "KuboF",
                        "Fitoschido",
                        "Ochilov",
-                       "Tlustulimu"
+                       "Tlustulimu",
+                       "Robin van der Vliet"
                ]
        },
        "config-desc": "Instalilo de MediaWiki",
        "config-db-name": "Nomo de datumbazo:",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-type-mysql": "MySQL (aŭ kongrua)",
+       "config-header-mysql": "MySQL-agordoj",
+       "config-header-postgres": "PostgreSQL-agordoj",
+       "config-header-sqlite": "SQLite-agordoj",
+       "config-header-oracle": "Oracle-agordoj",
+       "config-header-mssql": "Microsoft SQL Server-agordoj",
+       "config-mysql-binary": "Duuma",
        "config-mysql-utf8": "UTF-8",
        "config-site-name": "Nomo de vikio:",
        "config-ns-generic": "Projekto",
index 5b36510..9ea112b 100644 (file)
@@ -26,7 +26,9 @@
                        "Macofe",
                        "AVIADOR",
                        "FuzzyDice",
-                       "Legoktm"
+                       "Legoktm",
+                       "Matiia",
+                       "AlvaroMolina"
                ]
        },
        "config-desc": "El instalador de MediaWiki",
@@ -87,6 +89,7 @@
        "config-ctype": "'''Fatal''': Se necesita compilar PHP con compatibilidad para la [http://www.php.net/manual/en/ctype.installation.php extensión Ctype].",
        "config-iconv": "<strong>Fatal:</strong> PHP debe ser compilado con soporte para la [http://www.php.net/manual/en/iconv.installation.php extensión iconv].",
        "config-json": "'''Fatal:''' PHP fue compilado sin soporte para JSON.\nDebes instalar la extensión JSON o la extensión [http://pecl.php.net/package/jsonc PECL jsonc] antes de instalar MediaWiki.\n* La extensión PHP se incluye en Red Hat Enterprise Linux (CentOS) 5 y 6, aunque debe habilitarse en <code>/etc/php.ini</code> o <code>/etc/php.d/json.ini</code>.\n* Algunas distribuciones Linux liberadas después de mayo del 2013 omiten la extensión PHP, y en su lugar disponen de la extensión PECL en el paquete <code>php5-json</code> o <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "'''Fatal''': Se necesita compilar PHP con compatibilidad para la [http://www.php.net/manual/en/ctype.installation.php extensión Ctype].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] está instalado",
        "config-apc": "[http://www.php.net/apc APC] está instalado",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] está instalado",
        "config-mssql-install-auth": "Selecciona el tipo de autenticación que se utilizará para conectarse a la base de datos durante el proceso de instalación.\nSi seleccionas \"{{int:config-mssql-windowsauth}}\", se usarán las credenciales del usuario con el que se ejecuta el servidor web.",
        "config-mssql-web-auth": "Selecciona el tipo de autenticación que utilizará el servidor web para conectarse al servidor de base de datos, durante el funcionamiento normal de la wiki.\nSi seleccionas \"{{int:config-mssql-windowsauth}}\", se usarán las credenciales del usuario con el cual se ejecuta el servidor web.",
        "config-mssql-sqlauth": "Autenticación de SQL Server",
-       "config-mssql-windowsauth": "Autentificación de Windows",
+       "config-mssql-windowsauth": "Autenticación de Windows",
        "config-site-name": "Nombre del wiki:",
        "config-site-name-help": "Esto aparecerá en la barra de título del navegador y en varios otros lugares.",
        "config-site-name-blank": "Escribe un nombre de sitio.",
        "config-profile-no-anon": "Creación de cuenta requerida",
        "config-profile-fishbowl": "Sólo editores autorizados",
        "config-profile-private": "Wiki privado",
-       "config-profile-help": "Los wikis funcionan mejor cuando dejas que los edite tanta gente como sea posible.\nEn MediaWiki, es fácil revisar los cambios recientes y revertir los daños realizados por usuarios malintencionados o novatos.\nSin embargo, muchos han encontrado que MediaWiki es útil para una amplia variedad de funciones, y a veces no es fácil convencer a todos de los beneficios de la forma wiki.\nPor lo tanto tienes la elección.\n\nEl modelo '''{{int:config-profile-wiki}}''' permite que cualquiera pueda editar, sin siquiera iniciar sesión.\nUn wiki con '''{{int:config-profile-no-anon}}''' ofrece rendición de cuentas adicional, pero puede disuadir a colaboradores.\n\nEl modelo '''{{int:config-profile-fishbowl}}''' permite editar a los usuarios autorizados, pero el público puede ver las páginas, incluyendo el historial.\nUn '''{{int:config-profile-private}}''' sólo permite ver páginas a los usuarios autorizados, el mismo grupo al que le está permitido editar.\n\nConfiguraciones más complejas de derechos de usuario están disponibles después de la instalación, consulte [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights esta entrada en el manual].",
+       "config-profile-help": "Los wikis funcionan mejor cuando dejas que los edite tanta gente como sea posible.\nEn MediaWiki, es fácil revisar los cambios recientes y revertir los daños realizados por usuarios malintencionados o novatos.\nSin embargo, muchos han encontrado que MediaWiki es útil para una amplia variedad de funciones, y a veces no es fácil convencer a todos de los beneficios de la forma wiki.\nPor lo tanto tienes la elección.\n\nEl modelo <strong>{{int:config-profile-wiki}}</strong> permite que cualquiera pueda editar, sin siquiera iniciar sesión.\nUn wiki con <strong>{{int:config-profile-no-anon}}</strong> ofrece rendición de cuentas adicional, pero puede disuadir a colaboradores casuales.\n\nEl modelo <strong>{{int:config-profile-fishbowl}}</strong> permite editar a los usuarios autorizados, pero el público puede ver las páginas, incluyendo el historial.\nUn <strong>{{int:config-profile-private}}</strong> sólo permite ver páginas a los usuarios autorizados, el mismo grupo al que le está permitido editar.\n\nConfiguraciones más complejas de permisos de usuario están disponibles después de la instalación. Consulta [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights la entrada correspondiente del manual].",
        "config-license": "Derechos de autor y licencia:",
        "config-license-none": "Pie sin licencia",
        "config-license-cc-by-sa": "Creative Commons Atribución-CompartirIgual",
        "config-install-mainpage": "Creando página principal con contenido predeterminado",
        "config-install-extension-tables": "Creando las tablas para las extensiones habilitadas",
        "config-install-mainpage-failed": "No se pudo insertar la página principal: $1",
-       "config-install-done": "<strong>¡Felicidades!</strong>\nHas instalado MediaWiki correctamente.\n\nEl instalador ha generado un  archivo <code>LocalSettings.php</code>.\nEste contiene toda su configuración.\n\nDeberás descargarlo y ponerlo en la base de la instalación de wiki (el mismo directorio que index.php). La descarga debería haber comenzado automáticamente.\n\nSi no comenzó la descarga, o si se ha cancelado, puedes reiniciar la descarga haciendo clic en el siguiente enlace:\n\n$3\n\n<strong>Nota</strong>: Si no haces esto ahora, este archivo de configuración generado no estará disponible más tarde si sales de la instalación sin descargarlo.\n\nCuando lo hayas hecho, podrás <strong>[$2  entrar en tu wiki]</strong>.",
+       "config-install-done": "<strong>¡Felicidades!</strong>\nHas instalado MediaWiki.\n\nEl instalador ha generado un archivo <code>LocalSettings.php</code>.\nEste contiene toda su configuración.\n\nDeberás descargarlo y ponerlo en la base de la instalación de wiki (el mismo directorio que index.php). La descarga debería haber comenzado automáticamente.\n\nSi no comenzó la descarga, o si se ha cancelado, puedes reiniciar la descarga haciendo clic en el siguiente enlace:\n\n$3\n\n<strong>Nota</strong>: si no haces esto ahora, este archivo de configuración generado no estará disponible más tarde si sales de la instalación sin descargarlo.\n\nCuando lo hayas hecho, podrás <strong>[$2  entrar en tu wiki]</strong>.",
        "config-download-localsettings": "Descargar <code>LocalSettings.php</code>",
        "config-help": "ayuda",
        "config-help-tooltip": "haz clic para ampliar",
        "config-nofile": "El archivo \"$1\" no se pudo encontrar. ¿Se ha eliminado?",
        "config-extension-link": "¿Sabías que tu wiki admite [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensiones]?\n\nPuedes navegar por las [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category categorías] o visitar el [//www.mediawiki.org/wiki/Extension_Matrix centro de extensiones] para ver una lista completa.",
-       "mainpagetext": "<strong>MediaWiki se ha instalado con éxito.</strong>",
+       "mainpagetext": "<strong>MediaWiki se ha instalado.</strong>",
        "mainpagedocfooter": "Consulta la [//meta.wikimedia.org/wiki/Help:Contents/es guía del usuario] para obtener información sobre el uso del software wiki.\n\n== Primeros pasos ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de ajustes de configuración]\n* [//www.mediawiki.org/wiki/Manual:FAQ/es Preguntas frecuentes sobre MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de publicación de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Traducir MediaWiki en tu idioma]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Aprende cómo combatir el spam en tu wiki]"
 }
index b5ed996..d7e36ce 100644 (file)
@@ -11,7 +11,8 @@
                        "Danialbehzadi",
                        "Leyth",
                        "Huji",
-                       "Macofe"
+                       "Macofe",
+                       "درفش کاویانی"
                ]
        },
        "config-desc": "نصب کنندهٔ ویکی‌مدیا",
@@ -75,7 +76,6 @@
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] نصب شده‌است.",
        "config-apc": "[http://www.php.net/apc APC] نصب شده‌است.",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] نصب شده‌است.",
-       "config-no-cache": "'''هشدار:''' [http://www.php.net/apc APC],[http://xcache.lighttpd.net/ XCache] یا [http://www.iis.net/download/WinCacheForPhp WinCache] را نتوانست پیدا کند.\nذخیره شی فعال نیست.",
        "config-no-cache-apcu": "<strong>هشدار:</strong> پیوند [http://www.php.net/apcu APCu]، [http://xcache.lighttpd.net/ XCache] یا [http://www.iis.net/download/WinCacheForPhp WinCache] یافت نشد. ذخیره شی فعال نیست.",
        "config-mod-security": "'''هشدار:''' وب سرور شما [http://modsecurity.org/ mod_security] فعال است.اگر اشتباه پیکربندی شده‌‌ باشد،می تواند باعث ایجاد مشکلاتی برای مدیاویکی یا دیگر نرم‌افزاری شود که به کاربران اجازه می‌دهد پیام دلخواه ارسال کنند.\nبه [http://modsecurity.org/documentation/ mod_security documentation] مراجعه کنید یا اگر با خطاهای اتفاقی مواجه شدید با پشتیبانی میزبان خود در تماس باشید.",
        "config-diff3-bad": "جی‌ان‌یو دیف۳ پیدا نشد.",
        "config-help-tooltip": "برای گسترش کلیک کنید",
        "config-nofile": "پروندهٔ «$1» یافت نشد. آیا حذف شده‌است؟",
        "config-extension-link": "آیا می‌دانستید که ویکی شما [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensions] را پشتیبانی می‌کند؟\nشما می‌توانید [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensions by category]",
-       "mainpagetext": "'''Ù\86رÙ\85â\80\8cاÙ\81زار ویکی با موفقیت نصب شد.'''",
+       "mainpagetext": "'''Ù\85دÛ\8cاویکی با موفقیت نصب شد.'''",
        "mainpagedocfooter": "از [//meta.wikimedia.org/wiki/Help:Contents راهنمای کاربران]\nبرای استفاده از نرم‌افزار ویکی کمک بگیرید.\n\n== آغاز به کار ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings تنظیم پیکربندی]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki پرسش‌های متداول]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce فهرست ارسال نسخه‌های مدیاویکی]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise مدیاویکی برای زبان شما]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam آموزش مقابله به هرزنگاری در ویکی شما]"
 }
index 223955d..f99ca2f 100644 (file)
@@ -17,7 +17,9 @@
                        "SMAUG",
                        "SuperPete",
                        "McSalama",
-                       "Jaakkoh"
+                       "Jaakkoh",
+                       "Mikahama",
+                       "Olimar"
                ]
        },
        "config-desc": "MediaWiki-asennin",
        "config-type-sqlite": "SQLite",
        "config-type-oracle": "Oracle",
        "config-type-mssql": "Microsoft SQL Server",
+       "config-support-info": "MediaWiki tukee seuraavia tietokantajärjestelmiä:\n\n$1\n\nJos et näe tietokantajärjestelmää, jota yrität käyttää, listattuna alhaalla, seuraa yläpuolella olevia ohjeita tuen aktivoimiseksi.",
+       "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] on MediaWikin ensisijainen kohde ja se on myös parhaiten tuettu. MediaWiki voi myös käyttää [{{int:version-db-mariadb-url}} MariaDB]- sekä [{{int:version-db-percona-url}} Percona Server]-järjestelmiä, jotka ovat MySQL-yhteensopivia. ([http://www.php.net/manual/en/mysqli.installation.php Miten käännetään PHP MySQL-tuella])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] on suosittu avoimen lähdekoodin tietokantajärjestelmä vaihtoehtona MySQL:lle. Tuessa saattaa olla pieniä puutteita, eikä sitä suositella käytettäväksi tuotantoympäristössä. ([http://www.php.net/manual/en/pgsql.installation.php Kuinka käännetään PHP PostgreSQL-tuella])",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] on kevyt tietokantajärjestelmä, jota tuetaan hyvin. ([http://www.php.net/manual/en/pdo.installation.php Miten käännetään PHP SQLite-tuella], käyttää PDO:ta)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] on kaupallinen yritystietokanta. ([http://www.php.net/manual/en/oci8.installation.php Kuinka käännetään PHP OCI8-tuella])",
+       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] on kaupallinen yritystietokanta Windowsille. ([http://www.php.net/manual/en/sqlsrv.installation.php Miten käännetään PHP SQLSRV-tuella])",
        "config-header-mysql": "MySQL-asetukset",
        "config-header-postgres": "PostgreSQL-asetukset",
        "config-header-sqlite": "SQLite-asetukset",
        "config-missing-db-name": "\"{{int:config-db-name}}\" on pakollinen.",
        "config-missing-db-host": "\"{{int:config-db-host}}\" on pakollinen.",
        "config-missing-db-server-oracle": "\"{{int:config-db-host-oracle}}\" on pakollinen.",
+       "config-invalid-db-server-oracle": "Virheellinen tietokanta TNS \"$1\".\nKäytä joko \"TNS Name\"- tai \"Easy Connect\" -tekstiä\n([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Oracle metodien nimeäminen]).",
        "config-invalid-db-name": "”$1” ei kelpaa tietokannan nimeksi.\nKäytä ainoastaan kirjaimia (a-z, A-Z), numeroita (0-9), alaviivoja (_) ja tavuviivoja (-).",
        "config-invalid-db-prefix": "”$1” ei kelpaa tietokannan etuliitteeksi.\nKäytä ainoastaan kirjaimia (a-z, A-Z), numeroita (0-9), alaviivoja (_) ja tavuviivoja (-).",
        "config-connection-error": "$1.\n\nTarkista isäntä, käyttäjänimi, salasana ja yritä uudestaan.",
+       "config-invalid-schema": "Virheellinen skeema MediaWikille \"$1\".\nKäytä pelkkiä ASCII-kirjaimia (a-z, A-Z), numeroita (0-9) ja alaviivoja (_).",
+       "config-db-sys-create-oracle": "Asennusohjelma tukee ainoastaan SYSDBA-tunnuksen käyttämistä uuden tunnuksen luonnissa.",
        "config-postgres-old": "MediaWiki tarvitsee PostgreSQL:n version $1 tai uudemman. Nykyinen versio on $2.",
        "config-mssql-old": "Vaaditaan Microsoft SQL Server $1 tai uudempi. Sinulla on käytössä $2.",
        "config-sqlite-name-help": "Valitse nimi, joka yksilöi tämän wikin.\nÄlä käytä välilyöntejä tai viivoja.\nNimeä käytetään SQLite-tietokannan tiedostonimessä.",
        "config-help-tooltip": "Klikkaa laajentaaksesi",
        "config-nofile": "Tiedostoa \"$1\" ei löytynyt. Onko se poistettu?",
        "config-extension-link": "Tiesitkö että wiki tukee [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions laajennuksia]?\n\nLaajennuksia voi hakea myös [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category luokittain].",
-       "mainpagetext": "'''MediaWiki on onnistuneesti asennettu.'''",
+       "mainpagetext": "<strong>MediaWiki on onnistuneesti asennettu.</strong>",
        "mainpagedocfooter": "Lisätietoja käytöstä on sivulla [//meta.wikimedia.org/wiki/Help:Contents User's Guide].\n\n=== Lisäohjeita ===\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Asetusten teko-ohjeita]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWikin FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Sähköpostilista, jolla tiedotetaan MediaWikin uusista versioista]\n\n=== Asetukset ===\n\nTarkista, että alla olevat taivutusmuodot ovat oikein. Jos eivät, tee tarvittavat muutokset tiedostoon LocalSettings.php seuraavasti:\n $wgGrammarForms['fi']['genitive']['{{SITENAME}}'] = '...';\n $wgGrammarForms['fi']['partitive']['{{SITENAME}}'] = '...';\n $wgGrammarForms['fi']['elative']['{{SITENAME}}'] = '...';\n $wgGrammarForms['fi']['inessive']['{{SITENAME}}'] = '...';\n $wgGrammarForms['fi']['illative']['{{SITENAME}}'] = '...';\nTaivutusmuodot: {{GRAMMAR:genitive|{{SITENAME}}}} (yön) – {{GRAMMAR:partitive|{{SITENAME}}}} (yötä) – {{GRAMMAR:elative|{{SITENAME}}}} (yöstä) – {{GRAMMAR:inessive|{{SITENAME}}}} (yössä) – {{GRAMMAR:illative|{{SITENAME}}}} (yöhön)."
 }
index 5455cb7..70ceed1 100644 (file)
                        "Wladek92",
                        "Scoopfinder",
                        "Seb35",
-                       "Linedwell"
+                       "Linedwell",
+                       "Orlodrim",
+                       "Cl3m3n7",
+                       "C13m3n7",
+                       "The RedBurn"
                ]
        },
        "config-desc": "Le programme d’installation de MediaWiki",
@@ -83,6 +87,7 @@
        "config-ctype": "'''Fatal ''': PHP doit être compilé avec le support pour l'[http://www.php.net/manual/en/ctype.installation.php extension Ctype].",
        "config-iconv": "<strong>Erreur critique :</strong> PHP doit être compilé avec le support de l’[http://www.php.net/manual/en/iconv.installation.php extension iconv].",
        "config-json": "'''Erreur fatale :''' PHP a été compilé sans le support de JSON.\nVous devez soit installez l’extension JSON de PHP ou l’extension [http://pecl.php.net/package/jsonc PECL jsonc] avant d’installer MediaWiki.\n* L’extension PHP est comprise dans Red Hat Enterprise Linux (CentOS) 5 et 6, mais doit être activée dans <code>/etc/php.ini</code> ou <code>/etc/php.d/json.ini</code>.\n* Certaines distributions Linux après mai 2013 ne comprennent pas l’extension PHP, mais ont mis à la place l’extension PECL sous la forme <code>php5-json</code> ou <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Fatal :</strong> PHP doit être compilé avec la prise en charge de [http://www.php.net/manual/en/mbstring.setup.php l’extension mbstring].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] est installé",
        "config-apc": "[http://www.php.net/apc APC] est installé",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] est installé",
        "config-skins-must-enable-default": "L’habillage choisi par défaut doit être activé.",
        "config-install-alreadydone": "'''Attention''': Vous semblez avoir déjà installé MediaWiki et tentez de l'installer à nouveau.\nS'il vous plaît, allez à la page suivante.",
        "config-install-begin": "En appuyant sur {{int:config-continue}}, vous commencerez l'installation de MediaWiki.\nSi vous voulez encore apporter des modifications, appuyez sur \"{{int:config-back}}\".",
-       "config-install-step-done": "fait",
+       "config-install-step-done": "terminé",
        "config-install-step-failed": "échec",
        "config-install-extensions": "Inclusion des extensions",
        "config-install-database": "Création de la base de données",
        "config-install-mainpage": "Création de la page principale avec un contenu par défaut",
        "config-install-extension-tables": "Création de tables pour les extensions activées",
        "config-install-mainpage-failed": "Impossible d’insérer la page principale : $1",
-       "config-install-done": "'''Félicitations!'''\nVous avez réussi à installer MediaWiki.\n\nLe programme d'installation a généré un fichier <code>LocalSettings.php</code>. Il contient tous les paramètres de votre configuration.\n\nVous devrez le télécharger et le mettre à la racine de votre installation wiki (dans le même répertoire que index.php). Le téléchargement démarre automatiquement.\n\nSi le téléchargement n'a pas été offert, ou que vous l'avez annulé, vous pouvez démarrer à nouveau le téléchargement en cliquant ce lien :\n\n$3\n\n'''Note''': Si vous ne le faites pas maintenant, ce fichier de configuration généré ne sera pas disponible plus tard si vous quittez l'installation sans le télécharger.\n\nLorsque c'est fait, vous pouvez '''[$2 accéder à votre wiki]'''.",
+       "config-install-done": "<strong>Félicitations!</strong>\nVous avez installé MediaWiki.\n\nLe programme d'installation a généré un fichier <code>LocalSettings.php</code>. Il contient tous les paramètres de votre configuration.\n\nVous devrez le télécharger et le mettre à la racine de votre installation wiki (dans le même répertoire que index.php). Le téléchargement devrait démarrer automatiquement.\n\nSi le téléchargement n'a pas été proposé, ou que vous l'avez annulé, vous pouvez redémarrer le téléchargement en cliquant ce lien :\n\n$3\n\n<strong>Note :</strong> Si vous ne le faites pas maintenant, ce fichier de configuration généré ne sera pas disponible plus tard si vous quittez l'installation sans le télécharger.\n\nLorsque c'est fait, vous pouvez <strong>[$2 accéder à votre wiki]</strong> .",
        "config-download-localsettings": "Télécharger <code>LocalSettings.php</code>",
        "config-help": "aide",
        "config-help-tooltip": "cliquer pour agrandir",
        "config-nofile": "Le fichier « $1 » est introuvable. A-t-il été supprimé ?",
        "config-extension-link": "Saviez-vous que votre wiki supporte [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions des extensions] ?\n\nVous pouvez consulter les [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensions par catégorie].",
-       "mainpagetext": "<strong>MediaWiki a été installé avec succès.</strong>",
+       "mainpagetext": "<strong>MediaWiki a été installé.</strong>",
        "mainpagedocfooter": "Consultez le [//meta.wikimedia.org/wiki/Help:Contents/fr Guide de l’utilisateur] pour plus d’informations sur l’utilisation de ce logiciel de wiki.\n\n== Pour démarrer ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Liste des paramètres de configuration]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/fr Questions courantes sur MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Liste de discussion sur les distributions de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Adaptez MediaWiki dans votre langue]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Apprendre comment lutter contre le pourriel dans votre wiki]"
 }
index 7b9abdb..33f219b 100644 (file)
@@ -66,6 +66,7 @@
        "config-ctype": "<strong>Erro fatal:</strong> O PHP debe compilarse co soporte para a [http://www.php.net/manual/en/ctype.installation.php extensión Ctype].",
        "config-iconv": "<strong>Erro fatal:</strong> O PHP debe compilarse co soporte para a [http://www.php.net/manual/en/iconv.installation.php extensión iconv].",
        "config-json": "<strong>Erro fatal:</strong> O PHP compilouse sen o soporte de JSON.\nDebe instalar ben a extensión JSON do PHP ou a extensión [http://pecl.php.net/package/jsonc PECL jsonc] antes de instalar MediaWiki.\n* A extensión do PHP está incluída en Red Hat Enterprise Linux (CentOS) 5 e 6, mais debe activarse <code>/etc/php.ini</code> ou <code>/etc/php.d/json.ini</code>.\n* Algunhas distribucións do Linux lanzadas despois de maio de 2013 omiten a extensión do PHP, pero inclúen a extensión PECL como <code>php5-json</code> ou <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Erro fatal:</strong> O PHP debe compilarse co soporte para a [http://www.php.net/manual/en/mbstring.setup.php extensión mbstring].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] está instalado",
        "config-apc": "[http://www.php.net/apc APC] está instalado",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] está instalado",
index 0ff33c1..5e15c8d 100644 (file)
        "config-no-db": "Non poteva trovar un driver appropriate pro le base de datos! Es necessari installar un driver de base de datos pro PHP.\nLe sequente {{PLURAL:$2|typo|typos}} de base de datos es supportate: $1.\n\nSi tu compilava PHP tu mesme, reconfigura lo con un cliente de base de datos activate, per exemplo, usante <code>./configure --with-mysqli</code>.\nSi tu installava PHP ex un pacchetto Debian o Ubuntu, tu debe etiam installar, per exemplo, le modulo <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Attention''': tu ha SQLite $1, que es inferior al version minimal requirite, $2. SQLite essera indisponibile.",
        "config-no-fts3": "'''Attention''': SQLite es compilate sin [//sqlite.org/fts3.html modulo FTS3]; functionalitate de recerca non essera disponibile in iste back-end.",
-       "config-register-globals-error": "<strong>Error: Le option <code>[http://php.net/register_globals register_globals]</code> de PHP es active.\nIllo debe esser disactivate pro continuar le installation.</strong>\nVide [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] pro obtener adjuta sur como facer lo.",
-       "config-magic-quotes-gpc": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] es active!</strong>\nIste option corrumpe le datos entrate de maniera imprevisibile.\nTu non pote installar o usar MediaWiki si iste option non es disactivate.",
-       "config-magic-quotes-runtime": "'''Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] es active!'''\nIste option corrumpe le entrata de datos imprevisibilemente.\nTu non pote installar o usar MediaWiki si iste option non es disactivate.",
-       "config-magic-quotes-sybase": "'''Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] es active!'''\nIste option corrumpe le entrata de datos imprevisibilemente.\nTu non pote installar o usar MediaWiki si iste option non es disactivate.",
        "config-mbstring": "'''Fatal: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] es active!'''\nIste option causa errores e pote corrumper datos imprevisibilemente.\nTu non pote installar o usar MediaWiki si iste option non es disactivate.",
-       "config-safe-mode": "'''Aviso:''' Le [http://www.php.net/features.safe-mode modo secur] de PHP es active.\nIsto pote causar problemas, particularmente si es usate le incargamento de files e le supporto de <code>math</code>.",
        "config-xml-bad": "Le modulo XML de PHP es mancante.\nMediaWiki require functiones de iste modulo e non functionara in iste configuration.\nEs possibile que tu debe installar le pacchetto RPM php-xml.",
        "config-pcre-old": "<strong>Fatal:</strong> PCRE $1 o plus tarde es necessari.\nTu binario de PHP binary es ligate con PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Plus information].",
        "config-pcre-no-utf8": "'''Fatal''': Le modulo PCRE de PHP pare haber essite compilate sin supporto de PCRE_UTF8.\nMediaWiki require supporto de UTF-8 pro functionar correctemente.",
@@ -72,7 +67,6 @@
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] es installate",
        "config-apc": "[http://www.php.net/apc APC] es installate",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] es installate",
-       "config-no-cache": "'''Aviso:''' Non poteva trovar [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] o [http://www.iis.net/download/WinCacheForPhp WinCache].\nLe cache de objectos non es activate.",
        "config-mod-security": "'''Attention''': [http://modsecurity.org/ mod_security] es active in tu servitor web. Si mal configurate, isto pote causar problemas pro MediaWiki o altere software que permitte al usatores de publicar contento arbitrari.\nConsulta le [http://modsecurity.org/documentation/ documentation de mod_security] o contacta le servicio de adjuta de tu host si tu incontra estranie errores.",
        "config-diff3-bad": "GNU diff3 non trovate.",
        "config-git": "Systema de controlo de version Git trovate: <code>$1</code>",
        "config-help-tooltip": "clicca pro displicar",
        "config-nofile": "Le file \"$1\" non poteva esser trovate. Ha illo essite delite?",
        "config-extension-link": "Sapeva tu que tu wiki supporta [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensiones]?\n\nTu pote explorar le [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensiones per category] o le [//www.mediawiki.org/wiki/Extension_Matrix matrice de extensiones] pro vider le lista complete de extensiones.",
-       "mainpagetext": "'''MediaWiki ha essite installate con successo.'''",
+       "mainpagetext": "<strong>MediaWiki ha essite installate.</strong>",
        "mainpagedocfooter": "Consulta le [//meta.wikimedia.org/wiki/Help:Contents Guida del usator] pro informationes super le uso del software wiki.\n\n== Pro initiar ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de configurationes]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ FAQ a proposito de MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de diffusion pro annuncios de nove versiones de MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Traducer MediaWiki in tu lingua]"
 }
diff --git a/includes/installer/i18n/inh.json b/includes/installer/i18n/inh.json
new file mode 100644 (file)
index 0000000..abc7fbf
--- /dev/null
@@ -0,0 +1,8 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Умар"
+               ]
+       },
+       "config-help": "гӀо"
+}
index f524b32..e0a7975 100644 (file)
@@ -5,14 +5,20 @@
                        "Sveinn í Felli"
                ]
        },
+       "config-desc": "Uppsetningarforrit fyrir MediaWiki",
+       "config-title": "MediaWiki $1 uppsetning",
        "config-information": "Upplýsingar",
+       "config-localsettings-key": "Uppfærslulykill:",
        "config-your-language": "Tungumálið þitt:",
        "config-your-language-help": "Veldu tungumál að nota við uppsetninguna.",
+       "config-wiki-language": "Tungumál á wiki:",
        "config-back": "← Til baka",
        "config-continue": "Halda áfram →",
        "config-page-language": "Tungumál",
        "config-page-welcome": "Velkomin í MediaWiki!",
        "config-page-dbconnect": "Tengjast gagnagrunni",
+       "config-page-upgrade": "Uppfæra núverandi kerfi",
+       "config-page-dbsettings": "Gagnagrunnsstillingar",
        "config-page-name": "Heiti",
        "config-page-options": "Valkostir",
        "config-page-install": "Setja upp",
        "config-page-releasenotes": "Athugasemdir með útgáfu",
        "config-page-copying": "Afritun",
        "config-page-upgradedoc": "Uppfærsla",
+       "config-page-existingwiki": "Fyrirliggjandi wiki",
+       "config-restart": "Já, endurræsa",
        "config-env-php": "PHP $1 er uppsett.",
        "config-env-hhvm": "HHVM $1 er uppsett.",
+       "config-diff3-bad": "GNU diff3 fannst ekki.",
+       "config-db-type": "Tegund gagnagrunns:",
+       "config-db-host": "Netþjónn gagnagrunns:",
+       "config-db-name": "Heiti gagnagrunns:",
+       "config-db-name-oracle": "Gagnagrunnsskema:",
+       "config-db-username": "Notandanafn á gagnagrunni:",
+       "config-db-password": "Lykilorð gagnagrunns:",
+       "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
+       "config-type-mysql": "MySQL (eða samhæft)",
+       "config-type-postgres": "PostgreSQL",
+       "config-type-sqlite": "SQLite",
+       "config-type-oracle": "Oracle",
+       "config-type-mssql": "Microsoft SQL Server",
+       "config-regenerate": "Endurgera LocalSettings.php →",
+       "config-show-table-status": "<code>SHOW TABLE STATUS</code> beiðni mistókst!",
+       "config-db-web-account": "Gagnagrunnsreikningur fyrir vefaðgang",
+       "config-mysql-engine": "Gagnagrunnshýsing:",
+       "config-mysql-innodb": "InnoDB",
+       "config-mysql-myisam": "MyISAM",
+       "config-mysql-charset": "Stafatafla gagnagrunns:",
+       "config-mysql-binary": "Tvíundakerfis",
        "config-mysql-utf8": "UTF-8",
+       "config-mssql-auth": "Tegund auðkenningar:",
+       "config-mssql-sqlauth": "SQL Server auðkenning",
+       "config-mssql-windowsauth": "Windows auðkenning",
        "config-ns-generic": "Verkefni",
        "config-admin-name": "Notandanafnið þitt:",
        "config-admin-password": "Lykilorð:",
        "config-admin-password-confirm": "Lykilorðið aftur:",
        "config-admin-email": "Tölvupóstfang:",
-       "config-license-pd": "Almenningseign",
+       "config-profile": "Snið notandaréttinda:",
+       "config-profile-wiki": "Opið wiki",
+       "config-profile-no-anon": "Stofnun aðgangs krafist",
+       "config-profile-fishbowl": "Aðeins auðkenndir ritstjórar",
+       "config-profile-private": "Einkawiki",
+       "config-license": "Höfundaréttur og notkunarleyfi:",
+       "config-license-none": "Ekki síðufótur með notkunarleyfi",
+       "config-license-cc-by-sa": "Creative Commons: Höfundar getið - Deilist áfram",
+       "config-license-cc-by": "Creative Commons: Höfundar getið",
+       "config-license-cc-by-nc-sa": "Creative Commons: Höfundar getið - Ekki í ágóðaskyni - Deilist áfram",
+       "config-license-cc-0": "Creative Commons Zero leyfi (almenningseign)",
+       "config-license-gfdl": "Frjálsa GNU-handbókarleyfið, útgáfa 1.3 eða nýrri",
+       "config-license-pd": "Almenningseign (Public Domain)",
+       "config-license-cc-choose": "Veldu sérsniðið Creative Commons notkunarleyfi",
+       "config-extensions": "Viðbætur",
+       "config-skins": "Skinn",
        "config-install-step-done": "lokið",
        "config-install-step-failed": "mistókst",
+       "config-install-pg-commit": "Virkja breytingar",
+       "config-install-tables": "Töflur búnar til",
+       "config-download-localsettings": "Ná í <code>LocalSettings.php</code>",
+       "config-help": "hjálp",
+       "config-help-tooltip": "Smella til að þenja út",
        "mainpagetext": "'''Uppsetning á MediaWiki heppnaðist.'''",
        "mainpagedocfooter": "Ráðfærðu þig við [//meta.wikimedia.org/wiki/Help:Contents Notandahandbókina] fyrir frekari upplýsingar um notkun wiki-hugbúnaðarins.\n\n== Fyrir byrjendur ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Listi yfir uppsetningarstillingar]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki Algengar spurningar MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Póstlisti MediaWiki-útgáfa]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Læra hvernig á að berjast við amapóst á þínum wiki]"
 }
index d157e53..42159bc 100644 (file)
        "config-pcre-no-utf8": "'''Errore''': Il modulo PCRE di PHP sembra essere stato compilato senza il supporto PCRE_UTF8, ma MediaWiki lo richiede per funzionare correttamente.",
        "config-memory-raised": "Il valore <code>memory_limit</code> di PHP è $1, aumentato a $2.",
        "config-memory-bad": "''Attenzione:''' Il valore di <code>memory_limit</code> di PHP è $1.\nProbabilmente è troppo basso.\nL'installazione potrebbe non riuscire!",
-       "config-ctype": "'''Errore''': PHP deve essere compilato con il supporto per l'[http://www.php.net/manual/it/ctype.installation.php estensione Ctype].",
+       "config-ctype": "<strong>Fatale:</strong> PHP deve essere compilato con il supporto per l'[http://www.php.net/manual/it/ctype.installation.php estensione Ctype].",
        "config-iconv": "<strong>Fatale:</strong> PHP deve essere compilato con il supporto per l'[http://www.php.net/manual/en/iconv.installation.php estensione iconv].",
        "config-json": "'''Errore:''' PHP è stato compilato senza il supporto per JSON. E' necessario installare l'estensione PHP per JSON o l'estensione [http://pecl.php.net/package/jsonc PECL jsonc] prima di installare MediaWiki.\n* L'estensione PHP è inclusa in Red Hat Enterprise Linux (CentOS) 5 e 6, ma deve essere abilitata in <code>/etc/php.ini</code> o <code>/etc/php.d/json.ini</code>.\n* Alcune distribuzioni di Linux pubblicate dopo il maggio 2013 omettono l'estensione PHP, e al posto utilizzano l'estensione PECL come <code>php5-json</code> o <code>php-pecl-jsonc</code>",
+       "config-mbstring-absent": "<strong>Fatale:</strong> PHP deve essere compilato con il supporto per l'[http://www.php.net/manual/en/mbstring.setup.php estensione mbstring].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] è installato",
        "config-apc": "[http://www.php.net/apc APC] è installato",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] è installato",
        "config-help-tooltip": "fai clic per espandere",
        "config-nofile": "Il file \"$1\" non può essere trovato. È stato eliminato?",
        "config-extension-link": "Sapevi che il tuo wiki supporta le  [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions estensioni]?\n\nPuoi navigare tra le [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category estensioni per categoria].",
-       "mainpagetext": "'''Installazione di MediaWiki completata correttamente.'''",
+       "mainpagetext": "<strong>MediaWiki è stato installato.</strong>",
        "mainpagedocfooter": "Consulta la [//meta.wikimedia.org/wiki/Special:MyLanguage/Help:Contents Guida utente] per maggiori informazioni sull'uso di questo software wiki.\n\n== Per iniziare ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Impostazioni di configurazione]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Domande frequenti su MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailing list annunci MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localizza MediaWiki nella tua lingua]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Imparare a combattere lo spam sul tuo wiki]"
 }
index b3fc4ed..5a79940 100644 (file)
@@ -79,6 +79,7 @@
        "config-ctype": "<strong>致命的エラー:</strong> PHP は [http://www.php.net/manual/en/ctype.installation.php Ctype 拡張モジュール]のサポート付きでコンパイルされている必要があります。",
        "config-iconv": "<strong>致命的なエラー:</strong> PHPは[http://www.php.net/manual/en/iconv.installation.php iconv 拡張機能]のサポートを有効にしてコンパイルされている必要があります。",
        "config-json": "<strong>致命的エラー:</strong> PHP は JSON サポートなしでコンパイルされています。\nPHP に JSON 拡張モジュールまたは [http://pecl.php.net/package/jsonc PECL jsonc] 拡張モジュールをインストールしてから、MediaWiki をインストールしてください。\n* Red Hat Enterprise Linux (CentOS) 5 および 6には PHP の拡張機能が含まれているため、<code>/etc/php.ini</code> または <code>/etc/php.d/json.ini</code> から有効にしてください。\n* 2013年5月以降にリリースされた一部の Linux ディストリビューションでは、PHP 拡張モジュールの代わりに、<code>php5-json</code> または <code>php-pecl-jsonc</code> として PECL が同梱されています。",
+       "config-mbstring-absent": "<strong>致命的エラー:</strong> PHP は [http://www.php.net/manual/en/mbstring.setup.php mbstring 拡張モジュール]のサポートを有効にしてコンパイルされている必要があります。",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] がインストール済み",
        "config-apc": "[http://www.php.net/apc APC] がインストール済み",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] がインストール済み",
        "config-help-tooltip": "クリックで展開",
        "config-nofile": "ファイル「$1」が見つかりませんでした。削除された可能性があります。",
        "config-extension-link": "あなたのウィキは[//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions 拡張機能]をサポートしていることをご存知ですか?\n\n[//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category カテゴリ別で拡張機能を見る]か[//www.mediawiki.org/wiki/Extension_Matrix 拡張機能のマトリックス]で拡張機能すべてのリストをご覧になれます。",
-       "mainpagetext": "<strong>MediaWiki ã\81®ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83«ã\81«æ\88\90å\8a\9fã\81\97ã\81¾ã\81\97ã\81\9f。</strong>",
+       "mainpagetext": "<strong>MediaWiki ã\81¯ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83«æ¸\88ã\81¿ã\81§ã\81\99。</strong>",
        "mainpagedocfooter": "ウィキソフトウェアの使い方に関する情報は[//meta.wikimedia.org/wiki/Help:Contents 利用者案内]を参照してください。\n\n== はじめましょう ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings/ja 設定の一覧]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/ja MediaWiki よくある質問と回答]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki リリース情報メーリングリスト]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation/ja MediaWiki のあなたの言語へのローカライズ]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]"
 }
diff --git a/includes/installer/i18n/jbo.json b/includes/installer/i18n/jbo.json
new file mode 100644 (file)
index 0000000..e52919f
--- /dev/null
@@ -0,0 +1,12 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Xbony2"
+               ]
+       },
+       "config-information": "lo datni",
+       "config-page-name": "lo cmene",
+       "config-page-options": "lo cuxna",
+       "config-page-install": "lo instale",
+       "config-page-copying": "nu lo fukpi"
+}
index 13750e8..2163c6f 100644 (file)
@@ -41,6 +41,7 @@
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-db-port": "მონაცემთა ბაზის პორტი:",
        "config-db-schema": "მედიავიკის სქემა:",
+       "config-type-mssql": "Microsoft SQL Server",
        "config-header-mysql": "MySQL-ის პარამეტრები",
        "config-header-postgres": "PostgreSQL-ის პარამეტრები",
        "config-header-sqlite": "SQLite-ის პარამეტრები",
index d911898..09a9264 100644 (file)
        "config-admin-error-password": "\"<nowiki>$1</nowiki>\" 관리자의 비밀번호를 설정하는 중 내부 오류가 발생했습니다: <pre>$2</pre>",
        "config-admin-error-bademail": "이메일 주소를 잘못 입력하였습니다.",
        "config-subscribe": "[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce 릴리스 발표 메일링 리스트]를 구독합니다.",
-       "config-subscribe-help": "중요한 보안 알림을 포함한 릴리스 알림에 사용되는 저용량 메일링 리스트입니다.\n이 리스트를 구독하고 새 버전이 나올 때 미디어위키 설치를 업데이트해야 합니다.",
+       "config-subscribe-help": "중요한 보안 발표를 포함한 배포판 발표에 사용되는 저용량 메일링 리스트입니다.\n이 리스트를 구독하고 새 버전이 나올 때 미디어위키 설치를 업데이트해야 합니다.",
        "config-subscribe-noemail": "이메일 주소를 입력하지 않고 릴리스 발표 메일링 리스트에 가입하려 합니다.\n메일링 리스트에 가입하고자 할 경우 이메일 주소를 입력하세요.",
        "config-almost-done": "거의 다 완료했습니다!\n이제 남은 설정을 생략하고 지금 바로 위키를 설치할 수 있습니다.",
        "config-optional-continue": "더 많은 질문을 물어보세요.",
index e7bed0e..9a30139 100644 (file)
@@ -43,6 +43,7 @@
        "config-page-existingwiki": "Esamas viki",
        "config-help-restart": "Ar norite ištrinti visus išsaugotus duomenis, kuriuos jūs įvedėte ir iš naujo paleisti diegimo procesą?",
        "config-restart": "Taip, paleiskite jį iš naujo",
+       "config-welcome": "== Aplinkos patikrinimas ==\nDabar bus atlikti pagrindiniai patikrinimai, po kurių paaiškės, ar ši aplinka yra tinkama MediaWiki įrangai.\nNepamirškite įtraukti šią informaciją, jeigu norite gauti pagalbos, kaip užbaigti įdiegimą.",
        "config-sidebar": "* [//www.mediawiki.org MediaWiki namų tinklalapis]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Vartotojo gidas]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Administratoriaus gidas]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ DUK]\n----\n* <doclink href=Readme>Skaityk mane</doclink>\n* <doclink href=ReleaseNotes>Leidimo pastabos</doclink>\n* <doclink href=Copying>Kopijavimas</doclink>\n* <doclink href=UpgradeDoc>Atnaujinimas</doclink>",
        "config-env-good": "Aplinka buvo patikrinta.\nJūs galite įdiegti MediaWiki.",
        "config-env-bad": "Aplinka buvo patikrinta.\nJūs negalite įdiegti MediaWiki.",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] yra įdiegtas",
        "config-apc": "[http://www.php.net/apc APC] yra įdiegtas",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] yra įdiegtas",
+       "config-no-cache-apcu": "<strong>Įspėjimas:</strong> Nepavyko rasti [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] or [http://www.iis.net/download/WinCacheForPhp WinCache].\nObjekto spartinimas neįjungtas.",
        "config-diff3-bad": "GNU diff3 nerastas.",
-       "config-using-server": "Naudojant serverio pavadinimas „<nowiki>$1</nowiki>“.",
+       "config-git": "Rasta Git versijų kontrolės sistema: <code>$1</code>.",
+       "config-imagemagick": "Rastas „ImageMagick“: <code>$1</code>.\nPaveikslėlių miniatiūrizavimas bus įjungtas, jeigu įgalinsite vaizdų įkėlimą.",
+       "config-using-server": "Naudojamas serverio pavadinimas „<nowiki>$1</nowiki>“.",
        "config-using-uri": "Naudojamas serverio URL „<nowiki>$1$2</nowiki>“.",
        "config-db-type": "Duomenų bazės tipas:",
        "config-db-host": "Duomenų bazės serveris:",
index 69bbc83..b3aaef1 100644 (file)
@@ -27,6 +27,7 @@
        "config-restart": "Jā, restartēt",
        "config-env-php": "PHP $1 ir uzstādīts.",
        "config-diff3-bad": "GNU diff3 nav atrasts.",
+       "config-db-name": "Datubāzes nosaukums:",
        "config-db-username": "Datubāzes lietotājvārds:",
        "config-db-password": "Datubāzes parole:",
        "config-db-charset": "Datubāzes rakstzīmju kopa",
        "config-header-mssql": "Microsoft SQL servera iestatījumi",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
+       "config-mysql-utf8": "UTF-8",
+       "config-ns-generic": "Projekts",
+       "config-ns-site-name": "Tāds pats kā viki nosaukums: $1",
+       "config-ns-other": "Cits (jānorāda)",
+       "config-ns-other-default": "MansViki",
+       "config-admin-box": "Administratora konts",
        "config-admin-name": "Tavs lietotājvārds:",
        "config-admin-password": "Parole:",
        "config-admin-password-confirm": "Parole vēlreiz:",
        "config-admin-name-blank": "Ievadiet administratora lietotājvārdu.",
        "config-admin-email": "E-pasta adrese:",
+       "config-logo": "Logo URL:",
        "config-cc-again": "Izvēlies vēlreiz...",
+       "config-extensions": "Paplašinājumi",
        "config-install-step-done": "Gatavs",
        "config-help": "palīdzība",
        "config-help-tooltip": "uzspiediet, lai izvērstu",
-       "mainpagetext": "'''MediaWiki veiksmīgi ieinstalēts'''",
+       "mainpagetext": "<strong>MediaWiki veiksmīgi instalēts.</strong>",
        "mainpagedocfooter": "Izlasi [//meta.wikimedia.org/wiki/Help:Contents Lietotāja pamācību], lai iegūtu vairāk informācijas par Wiki programmatūras lietošanu.\n\n== Pirmie soļi ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Konfigurācijas iespēju saraksts]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki J&A]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Parakstīties uz paziņojumiem par jaunām MediaWiki versijām]"
 }
index 3916233..e576e2f 100644 (file)
        "config-localsettings-badkey": "Diso ilay lakile fanavaozana natsofokao.",
        "config-session-error": "Hadisoana teo am-panombohana ny fidirana : $1",
        "config-your-language": "Ny fiteninao :",
+       "config-your-language-help": "Hifidy ny teny ilaina amin'ny piraosesy fametrahana.",
        "config-wiki-language": "Fiteny ho ampiasain'ny wiki :",
+       "config-wiki-language-help": "Hifidy ny teny hanoratana ny votoatin'ny wiki.",
        "config-back": "← Miverina",
        "config-continue": "Manohy →",
        "config-page-language": "Fiteny",
        "config-page-welcome": "Tonga soa eto amin'i MediaWiki !",
        "config-page-dbconnect": "Hiditra eo amin'i banky angona",
+       "config-page-upgrade": "Hanavao ny fametrahana efa misy",
        "config-page-dbsettings": "Parametatry ny banky angona",
        "config-page-name": "Anarana",
        "config-page-options": "Safidy",
@@ -33,6 +36,8 @@
        "config-help-restart": "Tianao hofafana avokoa ve ny data voaangona natsofokao ary hamerina ny fizotran'ny fametrahana ?",
        "config-restart": "Eny, avereno atao",
        "config-welcome": "=== Fanamarinana mikasika ny tontolo ===\nNy fanamarihana tsotsotra dia atao hijerena raha mety ho ana rindrankajy Mediawiki ny tontolo.\nTadidio ny mametraka ireto torohay ireo raha mitady fanohanana mikasika ny fomba famaranana ny fametrahana ianao.",
+       "config-copyright": "== Zom-pamorona ary fepetra ==\n\n$1\n\n\nIo fandaharana dia rindrambaiko maimaim-poana; dia afaka zarazarain ary ovaina araka ny fepetra ao amin'ny GNU General Public License navoakan'ny Free Software Foundation; na versiona 2 ao amin'ny lisansa, na (araka ny safidinao) versiona tatỳ aoriana.\n\nIo fandaharaa io dia zaraina amin'ny fanantenana fa ho ilaina, anefa kosa dia <strong>tsy misy fiantohana</strong>; tsy misy fiantohana mikasika ny <strong>fivarotana azy</strong> na <strong>famendrehana ho azo ampiasaina amin'ny tranga iray manokana</strong>.\nJereo ny GNU General Public License hahazoana zavatra amin'ny antsipiriany.\n\nIanao dia tokony nandray <doclink href=Copying> kôpian'nyGNU General Public License </doclink> miaraka amin'ny fandaharana ity; raha tsy izany, manorata any amin'ny Free Software Foundation, Inc., 51 Franklin Street, Fahadimy Floor, Boston, MA 02110-1301, USA, na [http://www.gnu.org/copyleft/gpl.html vakio ao amin'ny Internet izany].",
+       "config-sidebar": "* [//www.mediawiki.org MediaWiki fandraisana]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Torolalan'ny mampiasa]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Torolalan'ny mpandrindra]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Fanontaniana mipetraka matetika]\n----\n* <doclink href=Readme>Vakio aho</doclink>\n* <doclink href=ReleaseNotes>Naoty famoahana</doclink>\n* <doclink href=Copying>Fandikàna</doclink>\n* <doclink href=UpgradeDoc>Fampihatsaràna</doclink>",
        "config-env-good": "Voamarina ny tontolo.\nAfaka apetrakao i MediaWiki.",
        "config-env-bad": "Voamarina ny tontolo.\nTsy afaka mametraka an'i MediaWiki ianao.",
        "config-env-php": "Misy ato PHP $1.",
        "config-unicode-pure-php-warning": "<strong>Fampitandremana: </strong>  Ny [http://pecl.php.net/intl itatra PECL intl] dia tsy misy mba hahazakana ny fampifenerana Unicode, ka mitontona amin'ny implementasiona PHP ranoray noho ny tsifisiany.\nRaha hametraka tranonkala be mpamangy ianao dia tokony mamaky ny [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations ''Unicode normalization''] (amin'ny teny anglisy)",
        "config-db-username": "Anaram-pikamban'ny banky angona :",
        "config-db-password": "Tenimiafin'ny banky angona :",
+       "config-db-prefix": "Tovom-banky angona:",
        "config-charset-mysql5-binary": "roafototra MySQL 4.1/5.0",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-charset-mysql4": "MySQL 4.0 miverinjaka UTF-8",
        "config-db-port": "Seranam-banky angona:",
        "config-header-mysql": "Parametatr'i MySQL",
+       "config-header-postgres": "Parametatra PostgreSQL",
        "config-header-sqlite": "Parametatr'i SQLite",
        "config-header-oracle": "Parametatr'i Oracle",
+       "config-header-mssql": "Parametatry ny lohamilina Microsoft SQL Server",
+       "config-invalid-db-type": "Karazana banky angona tsy ekena.",
        "config-mysql-innodb": "innoDB",
        "config-mysql-myisam": "MyISAM",
        "config-ns-generic": "Tetikasa",
index 3377afb..7deead3 100644 (file)
        "config-no-db": "Не можев да најдам соодветен двигател за базата на податоци! Ќе треба да воспоставите двигател за PHP-база.\n{{PLURAL:$2|Поддржан се следниов вид|Поддржани се следниве видови}} бази: $1.\n\nДоколку самите го срочивте овој PHP, овозможете го базниот клиент во поставките — на пр. со <code>./configure --with-mysqli</code>.\nАко овој PHP го воспоставите од пакет на Debian или Ubuntu, тогаш ќе треба исто така да го воспоставите, на пр., пакетот <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Предупредување''': имате SQLite $1. Најстарата допуштена верзија е $2. Затоа, SQLite ќе биде недостапен.",
        "config-no-fts3": "'''Предупредување''': SQLite iе составен без модулот [//sqlite.org/fts3.html FTS3] - за оваа база нема да има можност за пребарување.",
-       "config-register-globals-error": "<strong>Грешка: Вклучена е можноста <code>[http://php.net/register_globals register_globals]</code> за PHP.\nМора да се исклучи за да продолжите со воспоставката.</strong>\nКако да го направите тоа можете да прочитате на [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
-       "config-magic-quotes-gpc": "<strong>Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] е ективно!</strong>\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
-       "config-magic-quotes-runtime": "'''Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] е активно!'''\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
-       "config-magic-quotes-sybase": "'''Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] е активно!'''\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
        "config-mbstring": "'''Кобно: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] е активно!'''\nОваа можност предизвикува грешки и може непредвидиво да го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
-       "config-safe-mode": "'''Предупредување:''' [http://www.php.net/features.safe-mode безбедниот режим] на PHP е активен.\nОва може да предизвика проблеми, особено ако користите подигања и поддршка за <code>math</code>.",
        "config-xml-bad": "XML-модулот за PHP недостасува.\nМедијаВики има потреба од функции во овој модул и нема да работи со овие поставки.\nМоже да треба да го воспоставите RPM-пакетот „php-xml“.",
        "config-pcre-old": "'''Кобно:''' Се бара PCRE $1 или понова верзија.\nВашиот PHP-бинарен е сврзан со PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Повеќе информации].",
-       "config-pcre-no-utf8": "'''Фатално''': PCRE-модулот на PHP е составен без поддршка за PCRE_UTF8.\nМедијаВики бара поддршка за UTF-8 за да може да работи правилно.",
+       "config-pcre-no-utf8": "<strong>Кобно</strong>: PCRE-модулот на PHP е срочен без поддршка за PCRE_UTF8.\nМедијаВики бара поддршка за UTF-8 за да може да работи правилно.",
        "config-memory-raised": "<code>memory_limit</code> за PHP изнесува $1, зголемен на $2.",
        "config-memory-bad": "'''Предупредување:''' <code>memory_limit</code> за PHP изнесува $1.\nОва е веројатно премалку.\nВоспоставката може да не успее!",
-       "config-ctype": "'''Фатална грешка''': PHP мора да се состави со поддршка за [http://www.php.net/manual/en/ctype.installation.php додатокот Ctype].",
+       "config-ctype": "<strong>Кобно:</strong> PHP мора да се срочи со поддршка за додатокот [http://www.php.net/manual/en/ctype.installation.php Ctype].",
        "config-iconv": "<strong>Кобно:</strong> PHP мора да се срочува со поддршка за [http://www.php.net/manual/en/iconv.installation.php додатокот iconv].",
        "config-json": "'''Кобно:''' PHP беше срочен без поддршка од JSON.\nЌе мора да го воспоставите додатокот за JSON во PHP, или додатокот [http://pecl.php.net/package/jsonc PECL jsonc] пред да го воспоставите МедијаВики.\n* Додатокот за PHP е вклучен во верзиите 5 и 6 на Linux (од Red Hat Enterprise) (CentOS), но мора да се активира во <code>/etc/php.ini</code> или <code>/etc/php.d/json.ini</code>.\n* Некои варијанти на Linux излезени по мај 2013 г. не го содржат додатокот за PHP, туку го пакуваат додатокот PECL како <code>php5-json</code> или <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Кобно:</strong> PHP мора да се срочува со поддршка за додатокот [http://www.php.net/manual/en/mbstring.setup.php mbstring].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] е воспоставен",
        "config-apc": "[http://www.php.net/apc APC] е воспоставен",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] е воспоставен",
-       "config-no-cache": "<strong>Предупредување:</strong> Не можев да го најдам [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] или [http://www.iis.net/download/WinCacheForPhp WinCache].\nМеѓускладирањето на објекти не е овозможено.",
        "config-no-cache-apcu": "<strong>Предупредување:</strong> Не можев да го најдам [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] или [http://www.iis.net/download/WinCacheForPhp WinCache].\nМеѓускладирањето на објекти не е овозможено",
        "config-mod-security": "'''Предупредување''': на вашиот опслужувач има овозможено [http://modsecurity.org/ mod_security]. Ако не е поставено како што треба, ова може да предизвика проблеми кај МедијаВики и други програми што им овозможуваат на корисниците да објавуваат произволни содржини.\nПогледнете ја [http://modsecurity.org/documentation/ mod_security документацијата] или обратете се кај домаќинот ако наидете на случајни грешки.",
        "config-diff3-bad": "GNU diff3 не е пронајден.",
        "config-install-mainpage": "Создавам главна страница со стандардна содржина",
        "config-install-extension-tables": "Изработка на табели за овозможени додатоци",
        "config-install-mainpage-failed": "Не можев да вметнам главна страница: $1",
-       "config-install-done": "'''Честитаме!'''\nУспешно го воспоставивте МедијаВики.\n\nВоспоставувачот создаде податотека <code>LocalSettings.php</code>.\nТаму се содржат сите ваши нагодувања.\n\nЌе треба да ја преземете и да ја ставите во основата на воспоставката (истата папка во која се наоѓа index.php). Преземањето треба да е започнато автоматски.\n\nАко не ви е понудено преземање, или пак ако сте го откажале, можете да го почнете одново стискајќи на следнава врска:\n\n$3\n\n'''Напомена''': Ако ова не го направите сега, податотеката со поставки повеќе нема да биде на достапна.\n\nОткога ќе завршите со тоа, можете да '''[$2 влезете на вашето вики]'''.",
+       "config-install-done": "<strong>Честитаме!</strong>\nУспешно го воспоставивте МедијаВики.\n\nВоспоставувачот создаде податотека <code>LocalSettings.php</code>.\nТаму се содржат сите ваши нагодувања.\n\nЌе треба да ја преземете и да ја ставите во основата на воспоставката (истата папка во која се наоѓа index.php). Преземањето треба да е започнато автоматски.\n\nАко не ви е понудено преземање, или пак ако сте го откажале, можете да го почнете одново стискајќи на следнава врска:\n\n$3\n\n<strong>Напомена</strong>: Ако ова не го направите сега, податотеката со поставки повеќе нема да биде на достапна.\n\nОткога ќе завршите со тоа, можете да <strong>[$2 влезете на вашето вики]</strong>.",
        "config-download-localsettings": "Преземи го <code>LocalSettings.php</code>",
        "config-help": "помош",
        "config-help-tooltip": "стиснете да расклопите",
        "config-nofile": "Податотеката „$1“ не е пронајдена. Да не е избришана?",
        "config-extension-link": "Дали сте знаеле дека вашето вики поддржува [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions додатоци]?\n\nМожете да ги прелистате [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category по категории]",
-       "mainpagetext": "'''МедијаВики е успешно воспоставен.'''",
+       "mainpagetext": "<strong>МедијаВики е успешно воспоставен.</strong>",
        "mainpagedocfooter": "Погледнете го [//meta.wikimedia.org/wiki/Help:Contents Упатството за корисници] за подетални иформации како се користи вики-програмот.\n\n==Од каде да почнете==\n* [//meta.wikimedia.org/wiki/Manual:Configuration_settings Список на нагодувања]\n* [//meta.wikimedia.org/wiki/Manual:FAQ ЧПП (често поставувани прашања) за МедијаВики].\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Поштенски список на МедијаВики за нови верзии]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Локализирајте го МедијаВики на вашиот јазик]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Дознајте како да се борите против спам на вашето вики]"
 }
index 6251c03..1d5d779 100644 (file)
@@ -20,7 +20,8 @@
                        "Pio387",
                        "Darellur",
                        "The Polish",
-                       "Macofe"
+                       "Macofe",
+                       "Sethakill"
                ]
        },
        "config-desc": "Instalator MediaWiki",
@@ -30,9 +31,9 @@
        "config-localsettings-cli-upgrade": "Wykryto obecność pliku <code>LocalSettings.php</code>.\nAktualizację należy wykonać poprzez uruchomienie <code>update.php</code>",
        "config-localsettings-key": "Klucz aktualizacji:",
        "config-localsettings-badkey": "Podany klucz aktualizacji jest nieprawidłowy.",
-       "config-upgrade-key-missing": "Wykryto zainstalowane wcześniej MediaWiki.\nJeśli chcesz je zaktualizować dodaj na koniec pliku <code>LocalSettings.php</code> poniższą linię tekstu.\n\n$1",
+       "config-upgrade-key-missing": "Wykryto zainstalowane wcześniej MediaWiki.\nJeśli chcesz je zaktualizować, dodaj na koniec pliku <code>LocalSettings.php</code> poniższą linię tekstu:\n\n$1",
        "config-localsettings-incomplete": "Istniejący plik <code>LocalSettings.php</code> wygląda na niekompletny.\nBrak wartości zmiennej $1.\nZmień plik <code>LocalSettings.php</code>, tak by zawierał deklarację wartości tej zmiennej, a następnie kliknij „{{int:Config-continue}}”.",
-       "config-localsettings-connection-error": "Wystąpił błąd podczas łączenia z bazą danych używając ustawień podanych w <code>LocalSettings.php</code>\nNapraw te ustawienia i spróbuj ponownie.\n\n$1",
+       "config-localsettings-connection-error": "Wystąpił błąd podczas łączenia z bazą danych używając ustawień podanych w <code>LocalSettings.php</code>.\nNapraw te ustawienia i spróbuj ponownie.\n\n$1",
        "config-session-error": "Błąd uruchomienia sesji – $1",
        "config-session-expired": "Wygląda na to, że Twoja sesja wygasła.\nCzas życia sesji został skonfigurowany na $1.\nMożesz go wydłużyć zmieniając <code>session.gc_maxlifetime</code> w pliku php.ini.\nUruchom ponownie proces instalacji.",
        "config-no-session": "Dane sesji zostały utracone.\nSprawdź plik php.ini i upewnij się, że <code>session.save_path</code> wskazuje na odpowiedni katalog.",
@@ -84,6 +85,7 @@
        "config-xcache": "[Http://trac.lighttpd.net/xcache/ XCache] jest zainstalowany",
        "config-apc": "[Http://www.php.net/apc APC] jest zainstalowany",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] jest zainstalowany",
+       "config-no-cache-apcu": "<strong>Ostrzeżenie:</strong> Nie można znaleźć [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] lub [http://www.iis.net/download/WinCacheForPhp WinCache].\nPamięć podręczna obiektów nie zostanie włączona.",
        "config-mod-security": "''' Ostrzeżenie ''': Serwer sieci web ma włączone [http://modsecurity.org/ mod_security]. Jeśli jest niepoprawnie skonfigurowane, może być przyczyną problemów MediaWiki lub innego oprogramowania, które pozwala użytkownikom na wysyłanie dowolnej zawartości.\nSprawdź w [http://modsecurity.org/documentation/ dokumentacji mod_security] lub skontaktuj się z obsługa hosta, jeśli wystąpią losowe błędy.",
        "config-diff3-bad": "Nie znaleziono GNU diff3.",
        "config-git": "Znaleziono oprogramowanie kontroli wersji Git: <code>$1</code>.",
        "config-ns-site-name": "Taka sama jak nazwa wiki: $1",
        "config-ns-other": "Inna (należy określić)",
        "config-ns-other-default": "MojaWiki",
-       "config-project-namespace-help": "Według przykładu Wikipedii wiele wiki przechowuje swoje strony zasad oddzielnie od stron z zawartością, w \"'''przestrzeni nazw projektu'''\".\nWszystkie tytuły stron w tej przestrzeni nazw zaczynają się od pewnego przedrostka, który można tutaj określić.\nTradycyjnie ten przedrostek wywodzi się od nazwy wiki, ale nie może zawierać pewnych znaków przestankowych takich jak \"#\" lub \":\".",
+       "config-project-namespace-help": "Według przykładu Wikipedii wiele wiki przechowuje swoje strony zasad oddzielnie od stron z zawartością, w '''przestrzeni nazw projektu'''.\nWszystkie tytuły stron w tej przestrzeni nazw zaczynają się od pewnego przedrostka, który można tutaj określić.\nZazwyczaj ten przedrostek wywodzi się od nazwy wiki, ale nie może zawierać pewnych znaków przestankowych takich jak \"#\" lub \":\".",
        "config-ns-invalid": "Podana przestrzeń nazw „<nowiki>$1</nowiki>” jest nieprawidłowa.\nPodaj inną przestrzeń nazw projektu.",
        "config-ns-conflict": "Określona przestrzeń nazw \"<nowiki>$1</nowiki>\" powoduje konflikt z domyślną przestrzenią nazw MediaWiki.\nWskaż inną przestrzeń nazw projektu.",
        "config-admin-box": "Konto administratora",
        "config-install-mainpage": "Tworzenie strony głównej z domyślną zawartością",
        "config-install-extension-tables": "Tworzenie tabel dla aktywnych rozszerzeń",
        "config-install-mainpage-failed": "Nie udało się wstawić strony głównej: $1",
-       "config-install-done": "'''Gratulacje!'''\nUdało Ci się zainstalować MediaWiki.\n\nInstalator wygenerował plik konfiguracyjny <code>LocalSettings.php</code>.\n\nMusisz go pobrać i umieścić w katalogu głównym Twojej instalacji wiki (tym samym katalogu co index.php). Pobieranie powinno zacząć się automatycznie.\n\nJeżeli pobieranie nie zostało zaproponowane lub jeśli użytkownik je anulował, można ponownie uruchomić pobranie klikając poniższe łącze:\n\n$3\n\n'''Uwaga''': Jeśli nie zrobisz tego teraz, wygenerowany plik konfiguracyjny nie będzie już dostępny po zakończeniu instalacji.\n\nPo załadowaniu pliku konfiguracyjnego możesz '''[$2 wejść na wiki]'''.",
+       "config-install-done": "<strong>'''Gratulacje!</strong>\nUdało Ci się zainstalować MediaWiki.\n\nInstalator wygenerował plik konfiguracyjny <code>LocalSettings.php</code>.\n\nMusisz go pobrać i umieścić w katalogu głównym Twojej instalacji wiki (tym samym katalogu co index.php). Pobieranie powinno zacząć się automatycznie.\n\nJeżeli pobieranie nie zostało zaproponowane lub jeśli użytkownik je anulował, można ponownie uruchomić pobranie klikając poniższe łącze:\n\n$3\n\n<strong>Uwaga</strong>: Jeśli nie zrobisz tego teraz, wygenerowany plik konfiguracyjny nie będzie już dostępny po zakończeniu instalacji.\n\nPo załadowaniu pliku konfiguracyjnego możesz <strong>[$2 wejść na wiki]</strong>.",
        "config-download-localsettings": "Pobierz <code>LocalSettings.php</code>",
        "config-help": "pomoc",
        "config-help-tooltip": "kliknij, aby rozwinąć",
index 4a6526c..35835d2 100644 (file)
@@ -90,6 +90,6 @@
        "config-install-tables": "لښتيالونه جوړول",
        "config-download-localsettings": "ښکته کول <code>LocalSettings.php</code>",
        "config-help": "لارښود",
-       "mainpagetext": "'''MediaWiki په برياليتوب سره نصب شو.'''",
+       "mainpagetext": "<strong>MediaWiki نصب شو.</strong>",
        "mainpagedocfooter": "د ويکي ساوترې د کارولو د  مالوماتو په اړه [//meta.wikimedia.org/wiki/Help:Contents د کارن لارښود] سره سلا وکړۍ.\n\n== پيلول ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings د امستنو د سازونې لړليک]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ د ميډياويکي ډېرځليزې پوښتنې]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce د مېډياويکي د برېښليکونو لړليک]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources خپلې ژبې لپاره MediaWiki ځايتابول]"
 }
index e41c1f7..677908b 100644 (file)
@@ -18,7 +18,8 @@
                        "TheEduGobi",
                        "Dianakc",
                        "Walesson",
-                       "Almondega"
+                       "Almondega",
+                       "Luk3"
                ]
        },
        "config-desc": "O instalador do MediaWiki",
@@ -27,7 +28,7 @@
        "config-localsettings-upgrade": "Foi detectada a existência do arquivo <code>LocalSettings.php</code>.\nPara atualizar esta instalação, insira na caixa abaixo o valor de <code>$wgUpgradeKey</code>.\nEssa informação pode ser encontrada no arquivo <code>LocalSettings.php</code>",
        "config-localsettings-cli-upgrade": "Foi detectada a existência do arquivo <code><code>LocalSettings.php</code></code>.\nAtualize esta instalação executando o arquivo <code>update.php</code>",
        "config-localsettings-key": "Chave de atualização:",
-       "config-localsettings-badkey": "A chave fornecida está incorreta.",
+       "config-localsettings-badkey": "A chave de atualização que você forneceu está incorreta.",
        "config-upgrade-key-missing": "Foi detectada uma instalação existente do MediaWiki.\nPara atualizar esta instalação, insira a seguinte linha ao final do seu <code>LocalSettings.php</code>:\n\n$1",
        "config-localsettings-incomplete": "O arquivo <code>LocalSettings.php</code> parece incompleto.\nA variável $1 não está definida.\nPor favor, altere seu <code>LocalSettings.php</code> e defina esta variável e clique em \"{{int:Config-continue}}\".",
        "config-localsettings-connection-error": "Ocorreu um erro ao conectar ao banco de dados através das configurações presentes no arquivo <code>LocalSettings.php</code>. Por favor, corrija essas configurações e tente novamente.\n\n$1",
        "config-no-db": "Não foi possível encontrar um driver apropriado para a banco de dados! Você precisa instalar um driver de banco de dados para PHP. {{PLURAL:$2|É aceite o seguinte tipo|São aceites os seguintes tipos}} de banco de dados: $1.\n\nSe compilou o PHP você mesmo, reconfigure-o com um cliente de banco de dados ativado, por exemplo, usando <code>./configure --with-mysqli</code>.\nSe instalou o PHP a partir de um pacote Debian ou Ubuntu, então também precisa instalar, por exemplo, o pacote <code>php5-mysql</code>.",
        "config-outdated-sqlite": "<strong>Aviso:</strong> você tem o SQLite versão $1, que é menor do que a versão mínima necessária $2. O SQLite não estará disponível.",
        "config-no-fts3": "<strong>Aviso</strong> O SQLite foi compilado sem o [//sqlite.org/fts3.html módulo FTS3], as funcionalidades de pesquisa não estarão disponíveis nesta instalação.",
-       "config-register-globals-error": "<strong>Erro: a opção <code>[http://php.net/register_globals register_globals]</code> do PHP está ativada.\nA mesma deve ser desativada para continuar a instalação.</strong>\nVeja [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] para obter ajuda com isto.",
-       "config-magic-quotes-gpc": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] está ativa!</strong>\nEsta opção corrompe a entrada de dados imprevisivelmente.\nVocê não pode instalar ou usar a MediaWiki a menos que esta opção seja desativada.",
-       "config-magic-quotes-runtime": "<strong>Erro fatal: A opção [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] está ativada!</strong>\nEsta opção causa corrupção dos dados de entrada de forma imprevisível.\nVocê não pode instalar ou utilizar o MediaWiki a menos que esta opção seja desativada.",
-       "config-magic-quotes-sybase": "<strong>Erro fatal: A opção [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] está ativada!</strong>\nEsta opção corrompe os dados de entrada de forma imprevisível.\nVocê não pode instalar ou utilizar o MediaWiki a menos que esta opção seja desativada.",
        "config-mbstring": "<strong>Erro fatal: A opção [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] está ativada!</strong>\nEsta opção causa erros e pode corromper os dados de forma imprevisível.\nVocê não pode instalar ou utilizar o MediaWiki a menos que esta opção seja desativada.",
-       "config-safe-mode": "<strong>Aviso:</strong> O [http://www.php.net/features.safe-mode safe mode] do PHP está ativado.\nEste modo pode causar problemas, especialmente no upload de arquivos e no suporte a <code>math</code>.",
        "config-xml-bad": "Falta o módulo XML do PHP.\nO MediaWiki necessita de funções deste módulo e não funcionará com esta configuração.\nPode precisar de instalar o pacote RPM chamado php-xml.",
        "config-pcre-old": "<strong>Erro fatal:</strong> É necessário o PCRE $1 ou versão posterior.\nO binário do seu PHP foi vinculado com o PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Mais informações].",
        "config-pcre-no-utf8": "<strong>Erro fatal:</strong> O módulo PCRE do PHP parece ser compilado sem suporte a PCRE_UTF8.\nO MediaWiki requer suporte a UTF-8 para funcionar corretamente.",
@@ -87,7 +83,7 @@
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] está instalado",
        "config-apc": "[http://www.php.net/apc APC] está instalado",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] está instalado",
-       "config-no-cache": "<strong>Aviso:</strong> Não foi possível encontrar o [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] ou [http://www.iis.net/download/WinCacheForPhp WinCache].\nO cache de objetos não está habilitado.",
+       "config-no-cache-apcu": "<strong>Aviso:</strong> Não se pode encontrar [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] ou [http://www.iis.net/download/WinCacheForPhp WinCache].\nO caching de objetos não foi ativado.",
        "config-mod-security": "<strong>Aviso:</strong> Seu servidor web tem [http://modsecurity.org/ mod_security] habilitado. Se configurado incorretamente, pode causar problemas para o MediaWiki ou outro software que permite aos usuários postar conteúdo arbitrário.\nConsulte a [http://modsecurity.org/documentation/ documentação do mod_security] ou entre em contato com o suporte do seu host se você encontrar erros aleatórios.",
        "config-diff3-bad": "O GNU diff3 não foi encontrado.",
        "config-git": "Foi encontrado o software de controle de versão Git: <code>$1</code>.",
index 896b94b..9b45830 100644 (file)
        "config-install-mainpage": "A criar a página principal com o conteúdo padrão.",
        "config-install-extension-tables": "A criar as tabelas das extensões ativadas",
        "config-install-mainpage-failed": "Não foi possível inserir a página principal: $1",
-       "config-install-done": "'''Parabéns!'''\nTerminou a instalação do MediaWiki.\n\nO instalador gerou um ficheiro <code>LocalSettings.php</code>.\nEste ficheiro contém todas as configurações.\n\nPrecisa de fazer o download do ficheiro e colocá-lo no diretório de raiz da sua instalação (o mesmo diretório onde está o ficheiro index.php). Este download deverá ter sido iniciado automaticamente.\n\nSe o download não foi iniciado, ou se o cancelou, pode recomeçá-lo clicando o link abaixo:\n\n$3\n\n'''Nota''': Se não fizer isto agora, o ficheiro que foi gerado deixará de estar disponível quando sair do processo de instalação.\n\nDepois de terminar o passo anterior, pode '''[$2 entrar na wiki]'''.",
+       "config-install-done": "<strong>Parabéns!</strong>\nTerminou a instalação do MediaWiki.\n\nO instalador gerou um ficheiro <code>LocalSettings.php</code>.\nEste ficheiro contém todas as configurações.\n\nPrecisa de fazer a descarga do ficheiro e colocá-lo no diretório de raiz da sua instalação (o mesmo diretório onde está o ficheiro index.php). Esta descarga deverá ter sido iniciada automaticamente.\n\nSe a descarga não foi iniciada, ou se o cancelou, pode recomeçá-la ao clicar na ligação abaixo:\n\n$3\n\n<strong>Nota</strong>: Se não fizer isto agora, o ficheiro que foi gerado deixará de estar disponível quando sair do processo de instalação.\n\nDepois de terminar o passo anterior, pode <strong>[$2 entrar na wiki]</strong>.",
        "config-download-localsettings": "Descarga do <code>LocalSettings.php</code>",
        "config-help": "ajuda",
        "config-help-tooltip": "clique para expandir",
        "config-nofile": "Não foi possível encontrar o ficheiro \"$1\". Terá sido apagado?",
        "config-extension-link": "Sabia que a sua wiki suporta [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensões]?\n\nPode procurar [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category extensões por categoria].",
-       "mainpagetext": "'''MediaWiki instalado com sucesso.'''",
-       "mainpagedocfooter": "Consulte o [//meta.wikimedia.org/wiki/Help:Contents Guia de Utilizadores] para informações sobre o uso do software wiki.\n\n== Onde começar ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de opções de configuração]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Perguntas e respostas frequentes sobre o MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Subscreva a lista de divulgação de novas versões do MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Regionalize MediaWiki para seu idioma]"
+       "mainpagetext": "<strong>MediaWiki instalado.</strong>",
+       "mainpagedocfooter": "Consulte o [//meta.wikimedia.org/wiki/Help:Contents Guia de Utilizadores] para informações sobre o uso do software wiki.\n\n== Onde começar ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de opções de configuração]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Perguntas e respostas frequentes sobre o MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Subscreva a lista de divulgação de novas versões do MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Regionalize MediaWiki para seu idioma]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Aprenda a combater o spam na sua wiki]"
 }
index e734801..7010be0 100644 (file)
@@ -78,6 +78,7 @@
        "config-ctype": "Message if support for [http://www.php.net/manual/en/ctype.installation.php Ctype] is missing from PHP.\n{{Related|Config-fatal}}",
        "config-iconv": "Message if support for [http://www.php.net/manual/en/iconv.installation.php iconv] is missing from PHP.\n{{Related|Config-fatal}}",
        "config-json": "Message if support for [[wikipedia:JSON|JSON]] is missing from PHP.\n* \"[[wikipedia:Red Hat Enterprise Linux|Red Hat Enterprise Linux]]\" (RHEL) and \"[[wikipedia:CentOS|CentOS]]\" refer to two almost-identical Linux distributions. \"5 and 6\" refers to version 5 or 6 of either distribution. Because RHEL 7 likely will not include the PHP extension, do not translate as \"5 or newer\".\n* \"The [http://www.php.net/json PHP extension]\" is the JSON extension included with PHP 5.2 and newer.\n* \"The [http://pecl.php.net/package/jsonc PECL extension]\" is based on the PHP extension, though excludes code some distributions have found unacceptable (see [[phab:T49431]]).\n{{Related|Config-fatal}}",
+       "config-mbstring-absent": "Message if support for [http://www.php.net/manual/en/mbstring.installation.php mbstring] is missing from PHP.\n{{Related|Config-fatal}}",
        "config-xcache": "Message indicates if this program is available",
        "config-apc": "Message indicates if this program is available",
        "config-wincache": "Message indicates if this program is available",
index f589678..21f0cb0 100644 (file)
        "config-no-db": "Не удалось найти подходящие драйвера баз данных! Вам необходимо установить драйвера базы данных для PHP.\n{{PLURAL:$2|Поддерживается следующий тип|Поддерживаются следующие типы}} баз данных: $1.\n\nЕсли вы скомпилировали PHP сами, перенастройте его с включением клиента баз данных, например, с помощью <code>./configure --with-mysqli</code>.\nЕсли вы установили PHP из пакетов Debian или Ubuntu, то вам также необходимо установить, например, пакет <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Предупреждение''': у Вас установлен SQLite  $1, версия которого ниже требуемой $2 . SQLite будет недоступен.",
        "config-no-fts3": "'''Внимание''': SQLite собран без модуля [//sqlite.org/fts3.html FTS3] — поиск не будет работать для этой базы данных.",
-       "config-register-globals-error": "<strong>Ошибка: Параметр PHP <code>[http://php.net/register_globals register_globals]</code> включен.\nОн должен быть отключен для того, чтобы можно было продолжить установку.</strong>\nПолучить справку о том, как это сделать, можно по адресу [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
-       "config-magic-quotes-gpc": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
-       "config-magic-quotes-runtime": "'''Проблема: включена опция PHP [http://www.php.net/manual/ru/function.magic-quotes-runtime.php magic_quotes_runtime]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
-       "config-magic-quotes-sybase": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
        "config-mbstring": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!'''\nЭто приводит к ошибкам и непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
-       "config-safe-mode": "'''Предупреждение:''' PHP работает в [http://www.php.net/features.safe-mode «безопасном режиме»].\nЭто может привести к проблемам, особенно с загрузкой файлов и вставкой математических формул.",
        "config-xml-bad": "Для РНР отсутствует XML-модуль.\nMediaWiki не будет работать в этой конфигурации, так как требуется функционал этого модуля.\nВозможно, вам понадобится установить RPM-пакет php-xml.",
        "config-pcre-old": "'''Фатальная ошибка:''' требуется PCRE версии $1 или более поздняя.\nВаш исполняемый файл PHP связан с PCRE версии $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Подробнее].",
        "config-pcre-no-utf8": "'''Фатальная ошибка'''. Модуль PCRE для PHP, похоже, собран без поддержки PCRE_UTF8.\nMediaWiki требует поддержки UTF-8 для корректной работы.",
        "config-ctype": "'''Фатальная ошибка:''' PHP должен быть скомпилирован с поддержкой [http://www.php.net/manual/ru/ctype.installation.php расширения Ctype].",
        "config-iconv": "<strong>Фатальная ошибка:</strong> PHP должен быть скомпилирован с поддержкой [http://www.php.net/manual/en/iconv.installation.php расширения iconv].",
        "config-json": "'''Фатальная ошибка:''' PHP был скомпилирован без поддержка JSON.\nВам необходимо установить либо расширение PHP JSON, либо расширение [http://pecl.php.net/package/jsonc PECL jsonc] перед установкой MediaWiki.\n* PHP-расширение входит в состав Red Hat Enterprise Linux (CentOS) 5 и 6, хотя должна быть включено в <code>/etc/php.ini</code> или <code>/etc/php.d/json.ini</code>.\n* Некоторые дистрибутивы Linux, выпущенные после мая 2013 года, не включают расширение PHP, вместо того, чтобы упаковывать расширение PECL как <code>php5-json</code> или <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Фатальная ошибка:</strong> PHP должен быть скомпилирован с поддержкой [http://www.php.net/manual/en/mbstring.setup.php расширения mbstring].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] установлен",
        "config-apc": "[http://www.php.net/apc APC] установлен",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] установлен",
-       "config-no-cache": "'''Внимание:''' Не найдены [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] или [http://www.iis.net/download/WinCacheForPhp WinCache].\nКэширование объектов будет отключено.",
        "config-no-cache-apcu": "'''Внимание:''' Не найдены [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] или [http://www.iis.net/download/WinCacheForPhp WinCache].\nКэширование объектов будет отключено.",
        "config-mod-security": "<strong>Внимание</strong>: На вашем веб-сервере включен [http://modsecurity.org/ mod_security]/mod_security2. Многие его стандартные настройки могут вызывать проблемы для MediaWiki или другого ПО, позволяющего пользователям отправлять на сервер произвольный контент.\nОбратитесь к [http://modsecurity.org/documentation/ документации mod_security] или в службу поддержки вашего хостинг-провайдера, если вы сталкиваетесь со случайными ошибками.",
        "config-diff3-bad": "GNU diff3 не найден.",
        "config-install-mainpage": "Создание главной страницы с содержимым по умолчанию",
        "config-install-extension-tables": "Создание таблиц для включённых расширений",
        "config-install-mainpage-failed": "Не удаётся вставить главную страницу: $1",
-       "config-install-done": "'''Поздравляем!'''\nВы успешно установили MediaWiki.\n\nВо время установки был создан файл <code>LocalSettings.php</code>.\nОн содержит всю конфигурации вики.\n\nВам необходимо скачать его и положить в корневую директорию вашей вики (ту же директорию, где находится файл index.php). Его загрузка должна начаться автоматически.\n\nЕсли автоматическая загрузка не началась или вы её отменили, вы можете скачать по ссылке ниже:\n\n$3\n\n'''Примечание''': Если вы не сделаете этого сейчас, то сгенерированный файл конфигурации не будет доступен вам в дальнейшем, если вы выйдете из установки, не скачивая его.\n\nПо окончании действий, описанных выше, вы сможете '''[$2 войти в вашу вики]'''.",
+       "config-install-done": "<strong>Поздравляем!</strong>\nВы установили MediaWiki.\n\nВо время установки был создан файл <code>LocalSettings.php</code>.\nОн содержит все ваши настройки.\n\nВам необходимо скачать его и положить в корневую директорию вашей вики (ту же директорию, где находится файл index.php). Его загрузка должна начаться автоматически.\n\nЕсли автоматическая загрузка не началась или вы её отменили, вы можете скачать по ссылке ниже:\n\n$3\n\n<strong>Примечание</strong>: Если вы не сделаете этого сейчас, то сгенерированный файл конфигурации не будет доступен вам в дальнейшем, если вы выйдете из установки, не скачивая его.\n\nПо окончании действий, описанных выше, вы сможете <strong>[$2 войти в вашу вики]</strong>.",
        "config-download-localsettings": "Загрузить <code>LocalSettings.php</code>",
        "config-help": "справка",
        "config-help-tooltip": "нажмите, чтобы развернуть",
        "config-nofile": "Файл \"$1\" не удается найти. Он был удален?",
        "config-extension-link": "Знаете ли вы, что ваш вики-проект поддерживает [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions расширения]?\n\nВы можете просмотреть [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category расширения по категориям] или [//www.mediawiki.org/wiki/Extension_Matrix матрицу расширений], чтобы увидеть их полный список.",
-       "mainpagetext": "'''Вики-движок «MediaWiki» успешно установлен.'''",
+       "mainpagetext": "<strong>MediaWiki успешно установлена.</strong>",
        "mainpagedocfooter": "Информацию по работе с этой вики можно найти в [//meta.wikimedia.org/wiki/Help:Contents/ru справочном руководстве].\n\n== Некоторые полезные ресурсы ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Список возможных настроек];\n* [//www.mediawiki.org/wiki/Manual:FAQ/ru Часто задаваемые вопросы и ответы по MediaWiki];\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Рассылка уведомлений о выходе новых версий MediaWiki].\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Перевод MediaWiki на свой язык]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Узнайте, как бороться со спамом в вашей вики]"
 }
index 5ba505e..fc6997d 100644 (file)
@@ -84,6 +84,6 @@
        "config-install-step-failed": "није успело",
        "config-help": "помоћ",
        "config-help-tooltip": "кликните да проширите",
-       "mainpagetext": "'''Медијавики је успешно инсталиран.'''",
+       "mainpagetext": "<strong>Медијавики је успешно инсталиран.</strong>",
        "mainpagedocfooter": "Погледајте [//meta.wikimedia.org/wiki/Help:Contents кориснички водич] за коришћење програма.\n\n== Увод ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Помоћ у вези са подешавањима]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Често постављена питања]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Дописна листа о издањима Медијавикија]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Научите како да се борете против спама на Вашој вики]"
 }
index b1a97e9..3e1faf9 100644 (file)
@@ -35,6 +35,6 @@
        "config-site-name": "Ime vikija:",
        "config-license-cc-0": "Creative Commons Zero (javno vlasništvo)",
        "config-skins": "Teme",
-       "mainpagetext": "'''MedijaViki je uspešno instaliran.'''",
+       "mainpagetext": "<strong>Medijaviki je uspešno instaliran.</strong>",
        "mainpagedocfooter": "Molimo vidite [//meta.wikimedia.org/wiki/Help:Contents korisnički vodič] za informacije o upotrebi viki softvera.\n\n== Za početak ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Pomoć u vezi sa podešavanjima]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Najčešće postavljena pitanja]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mejling lista o izdanjima MedijaVikija]"
 }
index aba3d34..785c90b 100644 (file)
@@ -69,6 +69,6 @@
        "config-install-step-done": "әзер",
        "config-install-step-failed": "булмады",
        "config-help": "ярдәм",
-       "mainpagetext": "<strong>«MediaWiki» уңышлы куелды.</strong>",
+       "mainpagetext": "<strong>«MediaWiki» куелды.</strong>",
        "mainpagedocfooter": "Бу вики турында мәгълүматны [//meta.wikimedia.org/wiki/Help:Contents биредә] табып була.\n\n== Кайбер файдалы ресурслар ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Көйләнмәләр исемлеге (инг.)];\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki турында еш бирелгән сораулар һәм җаваплар (инг.)];\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki'ның яңа версияләре турында хәбәрләр яздырып алу];\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language].\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]"
 }
index 0793918..991e7c3 100644 (file)
@@ -73,6 +73,7 @@
        "config-ctype": "'''Помилка''': PHP має бути зібраним з підтримкою [http://www.php.net/manual/en/ctype.installation.php розширення Ctype].",
        "config-iconv": "'''Фатальна помилка''': PHP має бути зібраним з підтримкою [http://www.php.net/manual/en/iconv.installation.php розширення iconv].",
        "config-json": "'''Fatal:''' PHP був скомпільований без підтримки JSON.\nВам потрібно встановити або розширення PHP JSON або розширення[http://pecl.php.net/package/jsonc PECL jsonc] перед встановлення Медіавікі.\n* Розширення PHP включено у Red Hat Enterprise Linux (CentOS) 5 та 6, хоча має бути доступним у  <code>/etc/php.ini</code> або <code>/etc/php.d/json.ini</code>.\n* Деякі дистрибутиви Лінукса, випущені після травня 2013, пропустили розширення PHP, натомість упакували розширення  PECL як <code>php5-json</code> або <code>php-pecl-jsonc</code>.",
+       "config-mbstring-absent": "<strong>Фатальна помилка:</strong> PHP має бути скомпільовано з підтримкою [http://www.php.net/manual/en/mbstring.setup.php розширення mbstring].",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] встановлено",
        "config-apc": "[http://www.php.net/apc APC] встановлено",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] встановлено",
        "config-admin-password-confirm": "Пароль ще раз:",
        "config-admin-help": "Введіть бажане ім'я користувача тут, наприклад \"Павло НЛО\".\nЦе ім'я ви будете використовувати про вході у вікі.",
        "config-admin-name-blank": "Введіть ім'я користувача адміністратора.",
-       "config-admin-name-invalid": "Вказане ім'я користувача \"<nowiki>$1</nowiki>\" не припустиме.\nВкажіть інше ім'я користувача.",
+       "config-admin-name-invalid": "Вказане ім'я користувача «<nowiki>$1</nowiki>» не припустиме.\nВкажіть інше ім'я користувача.",
        "config-admin-password-blank": "Введіть пароль до облікового запису адміністратора.",
        "config-admin-password-mismatch": "Два введені вами паролі не збігаються.",
        "config-admin-email": "Адреса електронної пошти:",
index 57c4790..2644f3f 100644 (file)
@@ -15,7 +15,7 @@
        "config-localsettings-upgrade": "Một tập tin <code>LocalSettings.php</code> đã được phát hiện.\nĐể nâng cấp bản cài đặt này, xin nhập giá trị của <code>$wgUpgradeKey</code> trong hộp thoại bên dưới đây.\nBạn sẽ tìm thấy nó trong <code>LocalSettings.php</code>.",
        "config-localsettings-cli-upgrade": "Một tập tin <code>LocalSettings.php</code> đã được phát hiện.\nĐể nâng cấp bản cài đặt này, hãy chạy <code>update.php</code> thay thế.",
        "config-localsettings-key": "Chìa khóa nâng cấp:",
-       "config-localsettings-badkey": "Bạn đã cung cấp một chìa khóa sai.",
+       "config-localsettings-badkey": "Bạn đã cung cấp một chìa khóa nâng cấp sai.",
        "config-upgrade-key-missing": "Một bản cài đặt MediaWiki sẵn đã được phát hiện.\nĐể nâng cấp bản cài đặt này, hãy thêm dòng sau vào cuối <code>LocalSettings.php</code>:\n\n$1",
        "config-localsettings-incomplete": "Tập tin <code>LocalSettings.php</code> đã tồn tại hình như không hoàn chỉnh.\nBiến $1 chưa được đặt.\nXin hãy thay đổi <code>LocalSettings.php</code> để đặt biến này, rồi bấm “{{int:Config-continue}}”.",
        "config-localsettings-connection-error": "Đã xuất hiện lỗi khi kết nối với cơ sở dữ liệu dùng cấu hình trong <code>LocalSettings.php</code>. Xin hãy sửa lại cấu hình và thử lại.\n\n$1",
        "config-no-db": "Không tìm thấy một trình điều khiển cơ sở dữ liệu phù hợp! Bạn cần phải cài một trình điều khiển cơ sở dữ liệu cho PHP.\n{{PLURAL:$2|Loại|Các loại}} cơ sở dữ liệu sau đây được hỗ trợ: $1.\n\nNếu bạn đã biên dịch PHP lấy, cấu hình lại nó mà kích hoạt một trình khách cơ sở dữ liệu, ví dụ bằng lệnh <code>./configure --with-mysqli</code>.\nNếu bạn đã cài PHP từ một gói Debian hoặc Ubuntu, thì bạn cũng cần phải cài ví dụ gói <code>php5-mysql</code>.",
        "config-outdated-sqlite": "<strong>Chú ý:</strong> Bạn có SQLite $1, phiên bản này thấp hơn phiên bản yêu câu tối thiểu $2. SQLite sẽ không có tác dụng.",
        "config-no-fts3": "<strong>Chú ý:</strong> SQLite được biên dịch mà không có [//sqlite.org/fts3.html mô đun FTS3], nên các chức năng tìm kiếm sẽ bị vô hiệu trên hệ thống phía sau này.",
-       "config-register-globals-error": "<strong>Lỗi: Tùy chọn <code>[http://php.net/register_globals register_globals]</code> của PHP đã được kích hoạt.\nNó phải bị vô hiệu để tiếp tục quá trình cài đặt.</strong>\nXem [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] để biết cách thực hiện.",
-       "config-magic-quotes-gpc": "<strong>Lỗi chí tử: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] đang hoạt động!</strong>\nTùy chọn này sẽ làm hỏng dữ liệu nhập một cách không thể đoán trước.\nBạn không thể cài đặt hoặc sử dụng MediaWiki trừ phi tùy chọn này bị vô hiệu.",
-       "config-magic-quotes-runtime": "<strong>Lỗi chí tử: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] đang hoạt động!</strong>\nTùy chọn này sẽ làm hỏng dữ liệu nhập một cách không thể đoán trước.\nBạn không thể cài đặt hoặc sử dụng MediaWiki trừ phi tùy chọn này bị vô hiệu.",
-       "config-magic-quotes-sybase": "<strong>Lỗi chí tử: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] đang hoạt động!</strong>\nTùy chọn này sẽ làm hỏng dữ liệu nhập một cách không thể đoán trước.\nBạn không thể cài đặt hoặc sử dụng MediaWiki trừ phi tùy chọn này bị vô hiệu.",
        "config-mbstring": "<strong>Lỗi chí tử: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] được kích hoạt!</strong>\nTùy chọn này gây lỗi và có thể làm hỏng dữ liệu một cách không thể đoán trước.\nBạn không thể cài đặt hoặc sử dụng MediaWiki trừ phi tùy chọn này bị vô hiệu.",
-       "config-safe-mode": "<strong>Cảnh báo:</strong> [http://www.php.net/features.safe-mode Chế độ an toàn] của PHP đang được kích hoạt.\nNó có thể gây vấn đề, nhất là nếu dùng các chức năng tải lên tập tin và <code>math</code>.",
        "config-xml-bad": "Mô đun XML của PHP đang bị thiếu.\nMediaWiki yêu cầu các hàm trong mô đun này và sẽ không hoạt động trong cấu hình này.\nBạn có thể cần cài đặt gói RPM php-xml.",
        "config-pcre-old": "<strong>Lỗi chí tử:</strong> PCRE $1 trở lên được yêu cầu phải có.\nBản nhị phân PHP của bạn dang được liên kết với PCRE $2.\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE Thông tin bổ sung].",
        "config-pcre-no-utf8": "<strong>Lỗi chí tử:</strong> Mô đun PCRE của PHP dường như được biên dịch mà không có hỗ trợ PCRE_UTF8.\nMediaWiki yêu cầu phải có hỗ trợ UTF-8 để hoạt động chính xác.",
@@ -75,7 +70,7 @@
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] đã được cài đặt",
        "config-apc": "[http://www.php.net/apc APC] đã được cài đặt",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] đã được cài đặt",
-       "config-no-cache": "<strong>Cảnh báo:</strong> Không tìm thấy [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] hoặc [http://www.iis.net/download/WinCacheForPhp WinCache].\nVùng nhớ đệm đối tượng không được kích hoạt.",
+       "config-no-cache-apcu": "<strong>Cảnh báo:</strong> Không tìm thấy [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache], hoặc [http://www.iis.net/download/WinCacheForPhp WinCache].\nVùng nhớ đệm đối tượng không được kích hoạt.",
        "config-mod-security": "<strong>Cảnh báo:</strong> [http://modsecurity.org/ mod_security]/mod_security2 đã được kích hoạt trên máy chủ Web của bạn. Nhiều cấu hình phổ biến của phần mềm này sẽ gây vấn đề cho MediaWiki và những phần mềm khác cho phép người dùng đăng các nội dung tùy tiện.\nNếu có thể, bạn nên vô hiệu nó. Còn không, tra cứu [http://modsecurity.org/documentation/ tài liệu mod_security] hoặc liên hệ với nhà cung cấp hỗ trợ cho máy chủ nếu bạn gặp những lỗi ngẫu nhiên nào đó.",
        "config-diff3-bad": "Không tìm thấy GNU diff3.",
        "config-git": "Đã tìm thấy phần mềm điều khiển phiên bản Git: <code>$1</code>.",
        "config-ns-site-name": "Cùng với tên wiki: $1",
        "config-ns-other": "Khác (định rõ)",
        "config-ns-other-default": "WikiTôi",
-       "config-project-namespace-help": "Ví dụ sau đây của Wikipedia, nhiều wiki tách các trang sách họ với các trang nội dung, trong một \"''' không gian tên dự án'''\".\nTất cả các tiêu đề trang trong không gian tên này bắt đầu với một tiền tố nhất định, bạn có thể xác định ở đây.\nThông thường, tiền tố này được bắt nguồn từ tên của wiki, nhưng nó không thể chứa các ký tự đặc biệt như \"#\" hoặc \":\".",
+       "config-project-namespace-help": "Nhiều wiki bắt chước Wikipedia bằng cách tách các trang quy định ra khỏi các trang nội dung trong một '''không gian tên dự án'''.\nTất cả các tên trang trong không gian tên này bắt đầu với một tiền tố cụ thể, bạn có thể xác định ở đây.\nThông thường, tiền tố này bắt nguồn từ tên của wiki, nhưng nó không thể chứa các ký tự đặc biệt như “#” hoặc “:”.",
        "config-ns-invalid": "Không gian tên cụ thể \"<nowiki>$1</nowiki>\" không hợp lệ.\nXác định một không gian tên dự án khác.",
        "config-ns-conflict": "Không gian tên cụ thể \"<nowiki>$1</nowiki>\" xung đột với một không gian tên MediaWiki mặc định.\nXác định một không gian tên dự án khác.",
        "config-admin-box": "Tài khoản bảo quản viên",
        "config-install-mainpage": "Đang tạo trang đầu với nội dung mặc định",
        "config-install-extension-tables": "Đang tạo bảng cho các phần mở rộng được kích hoạt",
        "config-install-mainpage-failed": "Không thể chèn trang đầu: $1",
-       "config-install-done": "<strong>Xin chúc mừng!</strong>\nBạn đã cài đặt thành công MediaWiki.\n\nBộ cài đặt đã tạo ra một tập tin <code>LocalSettings.php</code>.\nTập tin này chứa tất cả các cấu hình của bạn.\n\nBạn sẽ cần phải tải nó về và đặt nó trong thư mục cài đặt wiki của bạn (cùng thư mục với index.php). Việc tải về có lẽ sẽ được khởi động tự động.\n\nNếu bản tải về không được cung cấp, hoặc nếu bạn hủy bỏ nó, bạn có thể khởi động lại tải về bằng cách nhấn vào liên kết dưới đây:\n\n$3\n\n<strong>Lưu ý:</strong> Nếu bạn không làm điều này ngay bây giờ, điều này sẽ tạo ra tập tin cấu hình sẽ không có giá trị cho bạn sau này nếu bạn thoát khỏi trình cài đặt mà không tải nó về.\n\nKhi đã việc tải về đã hoàn thành, bạn có thể <strong>[$2 truy cập trang wiki của bạn]</strong>.",
+       "config-install-done": "<strong>Xin chúc mừng!</strong>\nBạn đã cài đặt MediaWiki.\n\nBộ cài đặt đã tạo ra một tập tin <code>LocalSettings.php</code>.\nTập tin này chứa tất cả các cấu hình của bạn.\n\nBạn sẽ cần phải tải nó về và đặt nó trong thư mục cài đặt wiki của bạn (cùng thư mục với index.php). Việc tải về có lẽ sẽ được khởi động tự động.\n\nNếu bản tải về không được cung cấp, hoặc nếu bạn hủy bỏ nó, bạn có thể khởi động lại tải về bằng cách nhấn vào liên kết dưới đây:\n\n$3\n\n<strong>Lưu ý:</strong> Nếu bạn không làm điều này ngay bây giờ, điều này sẽ tạo ra tập tin cấu hình sẽ không có giá trị cho bạn sau này nếu bạn thoát khỏi trình cài đặt mà không tải nó về.\n\nKhi đã việc tải về đã hoàn thành, bạn có thể <strong>[$2 truy cập trang wiki của bạn]</strong>.",
        "config-download-localsettings": "Tải về <code>LocalSettings.php</code>",
        "config-help": "Trợ giúp",
        "config-help-tooltip": "nhấn chuột để mở rộng",
        "config-nofile": "Không tìm thấy tập tin “$1”. Nó có phải bị xóa không?",
        "config-extension-link": "Bạn có biết rằng wiki của bạn có hỗ trợ [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions mở rộng]?\n\nBạn có thể truy cập [//www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category phần mở rộng theo thể loại] hoặc [//www.mediawiki.org/wiki/Extension_Matrix Ma trận Mở rộng] để xem danh sách đầy đủ các phần mở rộng.",
-       "mainpagetext": "'''MediaWiki đã được cài đặt thành công.'''",
+       "mainpagetext": "'''MediaWiki đã được cài đặt.'''",
        "mainpagedocfooter": "Xin đọc [//meta.wikimedia.org/wiki/Help:Contents Hướng dẫn sử dụng] để biết thêm thông tin về cách sử dụng phần mềm wiki.\n\n== Để bắt đầu ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Danh sách các thiết lập cấu hình]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Các câu hỏi thường gặp MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Danh sách gửi thư về việc phát hành MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Tìm hiểu cách chống spam tại wiki của bạn]"
 }
index 4906b04..60133f7 100644 (file)
@@ -69,6 +69,6 @@
        "config-download-localsettings": "אראפלאדן <code>LocalSettings.php</code>",
        "config-help": "הילף",
        "config-nofile": "מ'האט נישט געקענט טרעפן די טעקע \"$1\". צי האט מען זי אויסגעמעקט?",
-       "mainpagetext": "'''מעדיעוויקי אינסטאלירט מיט דערפאלג.'''",
+       "mainpagetext": "<strong> מעדיעוויקי אינסטאלירט.</strong>",
        "mainpagedocfooter": "גיט זיך אן עצה מיט [//meta.wikimedia.org/wiki/Help:Contents באניצער'ס וועגווײַזער] פֿאר אינפֿארמאציע וויאזוי זיך באנוצן מיט וויקי ווייכוואַרג.\n\n== נוצליכע וועבלינקען פֿאַר אנהייבערס ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings רשימה פון קאנפֿיגוראציעס]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ אפֿט געפֿרעגטע שאלות]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce מעדיעוויקי באפֿרײַאונג פאסטליסטע]* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources איבערזעצן מעדיעוויקי אין אײַער שפראך]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam לערנט וויאזוי צו באקעמפן בפעם אויף אייער וויקי]"
 }
index 8c6988b..5943c05 100644 (file)
@@ -83,6 +83,7 @@
        "config-ctype": "<strong>致命错误:</strong>PHP必须有[http://www.php.net/manual/en/ctype.installation.php Ctype 扩展]来支持编译。",
        "config-iconv": "<strong>致命错误:</strong>PHP必须编译支持[http://www.php.net/manual/en/iconv.installation.php iconv拓展]。",
        "config-json": "<strong>致命错误:</strong>PHP编译没有附带JSON支持。\n在安装MediaWiki前,你必须安装PHP JSON扩展或者[http://pecl.php.net/package/jsonc PECL jsonc]扩展。\n* PHP扩展已包含在Red Hat Enterprise Linux (CentOS) 5和6中,但必须在<code>/etc/php.ini</code>或<code>/etc/php.d/json.ini</code>中启用。\n* 部分在2013年5月后发行的Linux发行版省略了PHP扩展,而将PECL扩展打包成了<code>php5-json</code>或<code>php-pecl-jsonc</code>。",
+       "config-mbstring-absent": "<strong>致命错误:</strong>PHP必须有[http://www.php.net/manual/en/mbstring.setup.php mbstring扩展]来支持编译。",
        "config-xcache": "[http://xcache.lighttpd.net/ XCache]已安装",
        "config-apc": "[http://www.php.net/apc APC]已安装",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache]已安装",
index 1f319d3..4f57b1f 100644 (file)
        "config-no-db": "找不到合適的資料庫驅動程式!您需要安裝 PHP 資料庫驅動程式。\n目前支援以下{{PLURAL:$2|類型|類型}}的資料庫: $1 。\n\n如果您是自行編譯 PHP,您必須重新設定並開啟資料庫客戶端,例:使用 <code>./configure --with-mysqli</code> 指令參數。\n如果您是使用 Debian 或 Ubuntu 的套件安裝 PHP ,您則需要額外安裝,例:<code>php5-mysql</code> 套件。",
        "config-outdated-sqlite": "<strong>警告:</strong>您已安裝 SQLite $1,但是它的版本低於最低需求版本 $2。 因此您無法使用 SQLite。",
        "config-no-fts3": "<strong>警告:</strong> SQLite 編譯時未包含 [//sqlite.org/fts3.html FTS3 模組],後台搜尋功能將無法使用。",
-       "config-register-globals-error": "<strong>錯誤:PHP 的 <code>[http://php.net/register_globals register_globals]</code> 選項已開啟。\n要繼續安裝程序必須關閉該選項。</strong>\n請參考 [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] 以取得操作說明。",
-       "config-magic-quotes-gpc": "<strong>嚴重:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] 已開啟!</strong>\n此選項會在無法預期的情況下損壞資料。\n除非您將該選項關閉,否鄍您無法安裝或使用 MediaWiki。",
-       "config-magic-quotes-runtime": "<strong>嚴重:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] 選項被開啟!</strong>\n此選項會導致資料在無法預測的情況下損壞。\n您必須將開選項關閉方可繼續安裝 MediaWiki。",
-       "config-magic-quotes-sybase": "<strong>嚴重:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] 選項被開啟!</strong>\n此選項會導致資料在無法預測的情況下損壞。\n您必須將開選項關閉方可繼續安裝 MediaWiki。",
        "config-mbstring": "<strong>嚴重:[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] 選項被開啟!</strong>\n此選項會導致資料在無法預測的情況下損壞。\n您必須將開選項關閉方可繼續安裝 MediaWiki。",
-       "config-safe-mode": "<strong>警告:</strong>PHP 的 [http://www.php.net/features.safe-mode 安全模式] 選項被開啟。它可能會導致檔案上傳與數學函數 <code>math</code> 的問題。",
        "config-xml-bad": "PHP 缺少的 XML 模組。\nMediaWiki 需要使用此模組中所提供的函數,且在目前的設定下將無法繼續作業。\n您可能需要安裝 php-xml RPM 套件。",
        "config-pcre-old": "<strong>嚴重:</strong> 需要使用 PCRE $1 或更新的版本。\n您的 PHP 執行檔使用的是 PCRE $2。\n[https://www.mediawiki.org/wiki/Manual:Errors_and_symptoms/PCRE 詳細資訊]。",
        "config-pcre-no-utf8": "<strong>嚴重:</strong> PHP 的 PCRE 模組在編譯時未包含 PCRE_UTF8 支援。\nMediaWiki 需要支援 UTF-8 才可正常運作。",
@@ -83,7 +78,6 @@
        "config-xcache": "[http://xcache.lighttpd.net/ XCache] 已安裝",
        "config-apc": "[http://www.php.net/apc APC] 已安裝",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] 已安裝",
-       "config-no-cache": "<strong>警告:</strong> 找不到 [http://www.php.net/apc APC]、[http://xcache.lighttpd.net/ XCache] 或 [http://www.iis.net/download/WinCacheForPhp WinCache]。\n無法開啟物件快取功能。",
        "config-mod-security": "<strong>警告:</strong>您的網頁伺服器已開啟 [http://modsecurity.org/ mod_security] 模組,如果設定不恰當會導致使用者可在 MediaWiki 或其他應用程式發佈任意的內容。\n若您遇到任何問題,請參考 [http://modsecurity.org/documentation/ mod_security 文件] 或聯繫您的伺服器技術支援人員。",
        "config-diff3-bad": "找不到 GNU diff3。",
        "config-git": "找到 Git 版本控制軟體:<code>$1</code>。",
        "config-ns-generic": "專案",
        "config-ns-site-name": "同 Wiki 名稱:$1",
        "config-ns-other": "其他 (請註明)",
-       "config-ns-other-default": "我的 Wiki",
+       "config-ns-other-default": "我的 wiki",
        "config-project-namespace-help": "許多 Wiki 以維基百科(Wikipedia)做為範例將政策頁面從內容頁面抽離,放置在 \"'''專案命名空間'''\" 中。\n所有在此命名空間裡的頁面都會有特定的字首,您可以在此處設定。\n通常這些字首是由該 Wiki 的名稱所衍伸出來,但無法使用標點符號,如 \"#\" 或 \":\"。",
        "config-ns-invalid": "您指定的命名空間 \"<nowiki>$1</nowiki>\" 無效,\n請指定另一個專案命名空間。",
        "config-ns-conflict": "您指定的命名空間 \"<nowiki>$1</nowiki>\" 與 MediaWiki 預設的命名空間衝突。\n請指定另一個專案命名空間。",
        "config-profile-wiki": "開放式 Wiki",
        "config-profile-no-anon": "需要註冊帳號",
        "config-profile-fishbowl": "僅授權的編輯者",
-       "config-profile-private": "封閉式 Wiki",
+       "config-profile-private": "私人 wiki",
        "config-profile-help": "Wiki 最佳的運作方式是盡可能讓大家都可以編輯文件。\n在 MediaWiki,可以很輕易的審查最近做的所有變更動作,並且可以還原由新手或惡意使用者造成的損害。\n\n不論如何,很多人發現 MediaWiki 可以廣泛的運用在各種地方,但並不是很容易可以說服每個人都遵守對 Wiki 有益的方式。\n所以您必須做出以下選擇。\n\n使用 <strong>{{int:config-profile-wiki}}</strong> 模式,允許所有人編輯文章,包含未匿名使用者。\n使用 <strong>{{int:config-profile-no-anon}}</strong> 模式,允許所有人編輯文章,不包含未登入的使用者。此模式較能管理所有使用者的言論,但會扼殺臨時使用者的貢獻機會。\n\n使用 <strong>{{int:config-profile-fishbowl}}</strong> 模式,僅經核准的使用者可以編輯,所有人可以檢視頁面,包含修訂的記錄。\n使用 <strong>{{int:config-profile-private}}</strong> 模式,僅經核准的使用者可以編輯、檢視頁面。\n\n有關更多複雜的使用者權限設定可在安裝程序結束後設定,請參考 [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights 相關文件說明]。",
        "config-license": "版權聲明與授權條款:",
        "config-license-none": "無授權條款頁腳",
index 48d38d9..9ccf6f8 100644 (file)
@@ -315,14 +315,6 @@ abstract class Job implements IJobSpecification {
         * @return string
         */
        public function toString() {
-               $truncFunc = function ( $value ) {
-                       $value = (string)$value;
-                       if ( mb_strlen( $value ) > 1024 ) {
-                               $value = "string(" . mb_strlen( $value ) . ")";
-                       }
-                       return $value;
-               };
-
                $paramString = '';
                if ( $this->params ) {
                        foreach ( $this->params as $key => $value ) {
@@ -332,14 +324,14 @@ abstract class Job implements IJobSpecification {
                                if ( is_array( $value ) ) {
                                        $filteredValue = [];
                                        foreach ( $value as $k => $v ) {
-                                               if ( is_scalar( $v ) ) {
-                                                       $filteredValue[$k] = $truncFunc( $v );
+                                               $json = FormatJson::encode( $v );
+                                               if ( $json === false || mb_strlen( $json ) > 512 ) {
+                                                       $filteredValue[$k] = gettype( $v ) . '(...)';
                                                } else {
-                                                       $filteredValue = null;
-                                                       break;
+                                                       $filteredValue[$k] = $v;
                                                }
                                        }
-                                       if ( $filteredValue && count( $filteredValue ) < 10 ) {
+                                       if ( count( $filteredValue ) <= 10 ) {
                                                $value = FormatJson::encode( $filteredValue );
                                        } else {
                                                $value = "array(" . count( $value ) . ")";
@@ -348,7 +340,12 @@ abstract class Job implements IJobSpecification {
                                        $value = "object(" . get_class( $value ) . ")";
                                }
 
-                               $paramString .= "$key={$truncFunc( $value )}";
+                               $flatValue = (string)$value;
+                               if ( mb_strlen( $value ) > 1024 ) {
+                                       $flatValue = "string(" . mb_strlen( $value ) . ")";
+                               }
+
+                               $paramString .= "$key={$flatValue}";
                        }
                }
 
index ef3d61d..0a0a7a2 100644 (file)
@@ -506,7 +506,7 @@ class JobRunner implements LoggerAwareInterface {
 
                $ms = intval( 1000 * $dbwSerial->pendingWriteQueryDuration() );
                $msg = $job->toString() . " COMMIT ENQUEUED [{$ms}ms of writes]";
-               $this->logger->warning( $msg );
+               $this->logger->info( $msg );
                $this->debugCallback( $msg );
 
                // Wait for an exclusive lock to commit
index 616c6d6..d636dc6 100644 (file)
@@ -216,7 +216,7 @@ class JobSpecification implements IJobSpecification {
                        'opts'   => $this->opts,
                        'title'  => [
                                'ns'  => $this->title->getNamespace(),
-                               'key' => $this->title->getDbKey()
+                               'key' => $this->title->getDBkey()
                        ]
                ];
        }
index 7fb020b..7f50055 100644 (file)
@@ -116,7 +116,7 @@ class BacklinkJobUtils {
                        foreach ( array_chunk( $titles, $cSize ) as $titleBatch ) {
                                $pages = [];
                                foreach ( $titleBatch as $tl ) {
-                                       $pages[$tl->getArticleId()] = [ $tl->getNamespace(), $tl->getDBKey() ];
+                                       $pages[$tl->getArticleID()] = [ $tl->getNamespace(), $tl->getDBkey() ];
                                }
                                $jobs[] = new $class(
                                        $title, // maintain parent job title
@@ -137,6 +137,10 @@ class BacklinkJobUtils {
                                                'batchSize' => $realBSize,
                                                'subranges' => array_slice( $ranges, 1 )
                                        ],
+                                       // Track how many times the base job divided for debugging
+                                       'division'      => isset( $params['division'] )
+                                               ? ( $params['division'] + 1 )
+                                               : 1
                                ] + $extraParams
                        );
                }
diff --git a/includes/libs/BufferingStatsdDataFactory.php b/includes/libs/BufferingStatsdDataFactory.php
deleted file mode 100644 (file)
index 9c18b10..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-/**
- * Copyright 2015
- *
- * 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
- */
-
-use Liuggio\StatsdClient\Entity\StatsdData;
-use Liuggio\StatsdClient\Entity\StatsdDataInterface;
-use Liuggio\StatsdClient\Factory\StatsdDataFactory;
-
-/**
- * A factory for application metric data.
- *
- * This class prepends a context-specific prefix to each metric key and keeps
- * a reference to each constructed metric in an internal array buffer.
- *
- * @since 1.25
- */
-class BufferingStatsdDataFactory extends StatsdDataFactory {
-       protected $buffer = [];
-
-       public function __construct( $prefix ) {
-               parent::__construct();
-               $this->prefix = $prefix;
-       }
-
-       /**
-        * Normalize a metric key for StatsD
-        *
-        * Replace occurences of '::' with dots and any other non-alphanumeric
-        * characters with underscores. Combine runs of dots or underscores.
-        * Then trim leading or trailing dots or underscores.
-        *
-        * @param string $key
-        * @since 1.26
-        */
-       private static function normalizeMetricKey( $key ) {
-               $key = preg_replace( '/[:.]+/', '.', $key );
-               $key = preg_replace( '/[^a-z0-9.]+/i', '_', $key );
-               $key = trim( $key, '_.' );
-               return str_replace( [ '._', '_.' ], '.', $key );
-       }
-
-       public function produceStatsdData(
-               $key, $value = 1, $metric = StatsdDataInterface::STATSD_METRIC_COUNT
-       ) {
-               $entity = $this->produceStatsdDataEntity();
-               if ( $key !== null ) {
-                       $key = self::normalizeMetricKey( "{$this->prefix}.{$key}" );
-                       $entity->setKey( $key );
-               }
-               if ( $value !== null ) {
-                       $entity->setValue( $value );
-               }
-               if ( $metric !== null ) {
-                       $entity->setMetric( $metric );
-               }
-               // Don't bother buffering a counter update with a delta of zero.
-               if ( !( $metric === StatsdDataInterface::STATSD_METRIC_COUNT && !$value ) ) {
-                       $this->buffer[] = $entity;
-               }
-               return $entity;
-       }
-
-       /**
-        * @return StatsdData[]
-        */
-       public function getBuffer() {
-               return $this->buffer;
-       }
-}
index cc236e2..a67b919 100644 (file)
@@ -206,86 +206,3 @@ class Cookie {
                return $this->isSessionKey || $this->expires > time();
        }
 }
-
-class CookieJar {
-       private $cookie = [];
-
-       /**
-        * Set a cookie in the cookie jar. Make sure only one cookie per-name exists.
-        * @see Cookie::set()
-        * @param string $name
-        * @param string $value
-        * @param array $attr
-        */
-       public function setCookie( $name, $value, $attr ) {
-               /* cookies: case insensitive, so this should work.
-                * We'll still send the cookies back in the same case we got them, though.
-                */
-               $index = strtoupper( $name );
-
-               if ( isset( $this->cookie[$index] ) ) {
-                       $this->cookie[$index]->set( $value, $attr );
-               } else {
-                       $this->cookie[$index] = new Cookie( $name, $value, $attr );
-               }
-       }
-
-       /**
-        * @see Cookie::serializeToHttpRequest
-        * @param string $path
-        * @param string $domain
-        * @return string
-        */
-       public function serializeToHttpRequest( $path, $domain ) {
-               $cookies = [];
-
-               foreach ( $this->cookie as $c ) {
-                       $serialized = $c->serializeToHttpRequest( $path, $domain );
-
-                       if ( $serialized ) {
-                               $cookies[] = $serialized;
-                       }
-               }
-
-               return implode( '; ', $cookies );
-       }
-
-       /**
-        * Parse the content of an Set-Cookie HTTP Response header.
-        *
-        * @param string $cookie
-        * @param string $domain Cookie's domain
-        * @return null
-        */
-       public function parseCookieResponseHeader( $cookie, $domain ) {
-               $len = strlen( 'Set-Cookie:' );
-
-               if ( substr_compare( 'Set-Cookie:', $cookie, 0, $len, true ) === 0 ) {
-                       $cookie = substr( $cookie, $len );
-               }
-
-               $bit = array_map( 'trim', explode( ';', $cookie ) );
-
-               if ( count( $bit ) >= 1 ) {
-                       list( $name, $value ) = explode( '=', array_shift( $bit ), 2 );
-                       $attr = [];
-
-                       foreach ( $bit as $piece ) {
-                               $parts = explode( '=', $piece );
-                               if ( count( $parts ) > 1 ) {
-                                       $attr[strtolower( $parts[0] )] = $parts[1];
-                               } else {
-                                       $attr[strtolower( $parts[0] )] = true;
-                               }
-                       }
-
-                       if ( !isset( $attr['domain'] ) ) {
-                               $attr['domain'] = $domain;
-                       } elseif ( !Cookie::validateCookieDomain( $attr['domain'], $domain ) ) {
-                               return null;
-                       }
-
-                       $this->setCookie( $name, $value, $attr );
-               }
-       }
-}
diff --git a/includes/libs/CookieJar.php b/includes/libs/CookieJar.php
new file mode 100644 (file)
index 0000000..910a7ca
--- /dev/null
@@ -0,0 +1,103 @@
+<?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
+ * @ingroup HTTP
+ */
+
+class CookieJar {
+       private $cookie = [];
+
+       /**
+        * Set a cookie in the cookie jar. Make sure only one cookie per-name exists.
+        * @see Cookie::set()
+        * @param string $name
+        * @param string $value
+        * @param array $attr
+        */
+       public function setCookie( $name, $value, $attr ) {
+               /* cookies: case insensitive, so this should work.
+                * We'll still send the cookies back in the same case we got them, though.
+                */
+               $index = strtoupper( $name );
+
+               if ( isset( $this->cookie[$index] ) ) {
+                       $this->cookie[$index]->set( $value, $attr );
+               } else {
+                       $this->cookie[$index] = new Cookie( $name, $value, $attr );
+               }
+       }
+
+       /**
+        * @see Cookie::serializeToHttpRequest
+        * @param string $path
+        * @param string $domain
+        * @return string
+        */
+       public function serializeToHttpRequest( $path, $domain ) {
+               $cookies = [];
+
+               foreach ( $this->cookie as $c ) {
+                       $serialized = $c->serializeToHttpRequest( $path, $domain );
+
+                       if ( $serialized ) {
+                               $cookies[] = $serialized;
+                       }
+               }
+
+               return implode( '; ', $cookies );
+       }
+
+       /**
+        * Parse the content of an Set-Cookie HTTP Response header.
+        *
+        * @param string $cookie
+        * @param string $domain Cookie's domain
+        * @return null
+        */
+       public function parseCookieResponseHeader( $cookie, $domain ) {
+               $len = strlen( 'Set-Cookie:' );
+
+               if ( substr_compare( 'Set-Cookie:', $cookie, 0, $len, true ) === 0 ) {
+                       $cookie = substr( $cookie, $len );
+               }
+
+               $bit = array_map( 'trim', explode( ';', $cookie ) );
+
+               if ( count( $bit ) >= 1 ) {
+                       list( $name, $value ) = explode( '=', array_shift( $bit ), 2 );
+                       $attr = [];
+
+                       foreach ( $bit as $piece ) {
+                               $parts = explode( '=', $piece );
+                               if ( count( $parts ) > 1 ) {
+                                       $attr[strtolower( $parts[0] )] = $parts[1];
+                               } else {
+                                       $attr[strtolower( $parts[0] )] = true;
+                               }
+                       }
+
+                       if ( !isset( $attr['domain'] ) ) {
+                               $attr['domain'] = $domain;
+                       } elseif ( !Cookie::validateCookieDomain( $attr['domain'], $domain ) ) {
+                               return null;
+                       }
+
+                       $this->setCookie( $name, $value, $attr );
+               }
+       }
+}
index cd9aad8..a9da366 100644 (file)
@@ -33,7 +33,7 @@
  * @file
  */
 class MWMessagePack {
-       /** @var boolean|null Whether current system is bigendian. **/
+       /** @var bool|null Whether current system is bigendian. **/
        public static $bigendian = null;
 
        /**
index b4206a2..10d4c71 100644 (file)
@@ -58,7 +58,7 @@ class StatusValue {
         * Factory function for fatal errors
         *
         * @param string|MessageSpecifier $message Message key or object
-        * @return Status
+        * @return StatusValue
         */
        public static function newFatal( $message /*, parameters...*/ ) {
                $params = func_get_args();
@@ -71,7 +71,7 @@ class StatusValue {
         * Factory function for good results
         *
         * @param mixed $value
-        * @return Status
+        * @return StatusValue
         */
        public static function newGood( $value = null ) {
                $result = new static();
index d2226b6..6b10c09 100644 (file)
@@ -30,83 +30,28 @@ class StringUtils {
         * 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.
-        *
         * @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.
         *
         * @since 1.21
         * @param string $value String to check
-        * @param bool $disableMbstring Whether to use the pure PHP
-        *  implementation instead of trying mb_check_encoding. Intended for unit
-        *  testing. Default: false
         * @return bool Whether the given $value is a valid UTF-8 encoded string
         */
-       static function isUtf8( $value, $disableMbstring = false ) {
+       static function isUtf8( $value ) {
                $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;
+               // HHVM 3.4 and older come with an outdated version of libmbfl that
+               // incorrectly allows values above U+10FFFF, so we have to check
+               // for them separately. (This issue also exists in PHP 5.3 and
+               // older, which are no longer supported.)
+               static $newPHP;
+               if ( $newPHP === null ) {
+                       $newPHP = !mb_check_encoding( "\xf4\x90\x80\x80", 'UTF-8' );
                }
 
-               // 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 = [
-                               // 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;
+               return mb_check_encoding( $value, 'UTF-8' ) &&
+                       ( $newPHP || preg_match( "/\xf4[\x90-\xbf]|[\xf5-\xff]/S", $value ) === 0 );
        }
 
        /**
@@ -288,6 +233,31 @@ class StringUtils {
                return $items;
        }
 
+       /**
+        * More or less "markup-safe" str_replace()
+        * Ignores any instances of the separator inside `<...>`
+        * @param string $search
+        * @param string $replace
+        * @param string $text
+        * @return string
+        */
+       static function replaceMarkup( $search, $replace, $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( $search, $placeholder );
+               $cleaned = StringUtils::delimiterReplaceCallback( '<', '>', $replacer->cb(), $text );
+
+               // Explode, then put the replaced separators back in
+               $cleaned = str_replace( $search, $replace, $cleaned );
+               $text = str_replace( $placeholder, $search, $cleaned );
+
+               return $text;
+       }
+
        /**
         * Escape a string to make it suitable for inclusion in a preg_replace()
         * replacement parameter.
index c385c38..b61cae7 100644 (file)
@@ -55,11 +55,3 @@ abstract class EventRelayer {
        abstract protected function doNotify( $channel, array $events );
 }
 
-/**
- * No-op class for publishing messages into a PubSub system
- */
-class EventRelayerNull extends EventRelayer {
-       public function doNotify( $channel, array $events ) {
-               return true;
-       }
-}
diff --git a/includes/libs/eventrelayer/EventRelayerNull.php b/includes/libs/eventrelayer/EventRelayerNull.php
new file mode 100644 (file)
index 0000000..b8ec55f
--- /dev/null
@@ -0,0 +1,29 @@
+<?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
+ * @author Aaron Schulz
+ */
+
+/**
+ * No-op class for publishing messages into a PubSub system
+ */
+class EventRelayerNull extends EventRelayer {
+       public function doNotify( $channel, array $events ) {
+               return true;
+       }
+}
index 3d5d383..60ec922 100644 (file)
@@ -21,8 +21,6 @@
  * @ingroup Cache
  */
 
-use Psr\Log\LoggerInterface;
-
 /**
  * Wrapper around a BagOStuff that caches data in memory
  *
index e43d37b..b212e97 100644 (file)
@@ -918,6 +918,15 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                $this->lastRelayError = self::ERR_NONE;
        }
 
+       /**
+        * Clear the in-process caches; useful for testing
+        *
+        * @since 1.27
+        */
+       public function clearProcessCache() {
+               $this->procCache->clear();
+       }
+
        /**
         * Do the actual async bus purge of a key
         *
diff --git a/includes/libs/stats/BufferingStatsdDataFactory.php b/includes/libs/stats/BufferingStatsdDataFactory.php
new file mode 100644 (file)
index 0000000..9c18b10
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Copyright 2015
+ *
+ * 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
+ */
+
+use Liuggio\StatsdClient\Entity\StatsdData;
+use Liuggio\StatsdClient\Entity\StatsdDataInterface;
+use Liuggio\StatsdClient\Factory\StatsdDataFactory;
+
+/**
+ * A factory for application metric data.
+ *
+ * This class prepends a context-specific prefix to each metric key and keeps
+ * a reference to each constructed metric in an internal array buffer.
+ *
+ * @since 1.25
+ */
+class BufferingStatsdDataFactory extends StatsdDataFactory {
+       protected $buffer = [];
+
+       public function __construct( $prefix ) {
+               parent::__construct();
+               $this->prefix = $prefix;
+       }
+
+       /**
+        * Normalize a metric key for StatsD
+        *
+        * Replace occurences of '::' with dots and any other non-alphanumeric
+        * characters with underscores. Combine runs of dots or underscores.
+        * Then trim leading or trailing dots or underscores.
+        *
+        * @param string $key
+        * @since 1.26
+        */
+       private static function normalizeMetricKey( $key ) {
+               $key = preg_replace( '/[:.]+/', '.', $key );
+               $key = preg_replace( '/[^a-z0-9.]+/i', '_', $key );
+               $key = trim( $key, '_.' );
+               return str_replace( [ '._', '_.' ], '.', $key );
+       }
+
+       public function produceStatsdData(
+               $key, $value = 1, $metric = StatsdDataInterface::STATSD_METRIC_COUNT
+       ) {
+               $entity = $this->produceStatsdDataEntity();
+               if ( $key !== null ) {
+                       $key = self::normalizeMetricKey( "{$this->prefix}.{$key}" );
+                       $entity->setKey( $key );
+               }
+               if ( $value !== null ) {
+                       $entity->setValue( $value );
+               }
+               if ( $metric !== null ) {
+                       $entity->setMetric( $metric );
+               }
+               // Don't bother buffering a counter update with a delta of zero.
+               if ( !( $metric === StatsdDataInterface::STATSD_METRIC_COUNT && !$value ) ) {
+                       $this->buffer[] = $entity;
+               }
+               return $entity;
+       }
+
+       /**
+        * @return StatsdData[]
+        */
+       public function getBuffer() {
+               return $this->buffer;
+       }
+}
diff --git a/includes/libs/stats/NullStatsdDataFactory.php b/includes/libs/stats/NullStatsdDataFactory.php
new file mode 100644 (file)
index 0000000..3b272e2
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+
+use Liuggio\StatsdClient\Entity\StatsdData;
+use Liuggio\StatsdClient\Entity\StatsdDataInterface;
+use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
+
+/**
+ * @author Addshore
+ * @since 1.27
+ */
+class NullStatsdDataFactory implements StatsdDataFactoryInterface {
+
+       /**
+        * This function creates a 'timing' StatsdData.
+        *
+        * @param string|array $key The metric(s) to set.
+        * @param float $time The elapsed time (ms) to log
+        **/
+       public function timing( $key, $time ) {
+       }
+
+       /**
+        * This function creates a 'gauge' StatsdData.
+        *
+        * @param string|array $key The metric(s) to set.
+        * @param float $value The value for the stats.
+        **/
+       public function gauge( $key, $value ) {
+       }
+
+       /**
+        * This function creates a 'set' StatsdData object
+        * A "Set" is a count of unique events.
+        * This data type acts like a counter, but supports counting
+        * of unique occurrences of values between flushes. The backend
+        * receives the number of unique events that happened since
+        * the last flush.
+        *
+        * The reference use case involved tracking the number of active
+        * and logged in users by sending the current userId of a user
+        * with each request with a key of "uniques" (or similar).
+        *
+        * @param  string|array $key The metric(s) to set.
+        * @param  float $value The value for the stats.
+        *
+        * @return array
+        **/
+       public function set( $key, $value ) {
+               return [];
+       }
+
+       /**
+        * This function creates a 'increment' StatsdData object.
+        *
+        * @param string|array $key The metric(s) to increment.
+        * @param float|1      $sampleRate The rate (0-1) for sampling.
+        *
+        * @return array
+        **/
+       public function increment( $key ) {
+               return [];
+       }
+
+       /**
+        * This function creates a 'decrement' StatsdData object.
+        *
+        *
+        * @param string|array $key The metric(s) to decrement.
+        * @param float|1      $sampleRate The rate (0-1) for sampling.
+        *
+        * @return mixed
+        **/
+       public function decrement( $key ) {
+               return [];
+       }
+
+       /**
+        * This function creates a 'updateCount' StatsdData object.
+        *
+        * @param string|array $key The metric(s) to decrement.
+        * @param integer $delta The delta to add to the each metric
+        *
+        * @return mixed
+        **/
+       public function updateCount( $key, $delta ) {
+               return [];
+       }
+
+       /**
+        * Produce a StatsdDataInterface Object.
+        *
+        * @param string $key The key of the metric
+        * @param int $value The amount to increment/decrement each metric by.
+        * @param string $metric The metric type
+        *                      ("c" for count, "ms" for timing, "g" for gauge, "s" for set)
+        *
+        * @return StatsdDataInterface
+        **/
+       public function produceStatsdData(
+               $key,
+               $value = 1,
+               $metric = StatsdDataInterface::STATSD_METRIC_COUNT
+       ) {
+               $data = new StatsdData();
+               $data->setKey( $key );
+               $data->setValue( $value );
+               $data->setMetric( $metric );
+               return $data;
+       }
+
+}
diff --git a/includes/libs/stats/StatsdAwareInterface.php b/includes/libs/stats/StatsdAwareInterface.php
new file mode 100644 (file)
index 0000000..b0b941a
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
+
+/**
+ * Describes a Statsd aware interface
+ *
+ * @since 1.27
+ * @author Addshore
+ */
+interface StatsdAwareInterface {
+
+       /**
+        * Sets a StatsdDataFactory instance on the object
+        *
+        * @param StatsdDataFactoryInterface $statsFactory
+        * @return null
+        */
+       public function setStatsdDataFactory( StatsdDataFactoryInterface $statsFactory );
+
+}
index aa90d1d..21e40ec 100644 (file)
@@ -58,7 +58,8 @@ class BlockLogFormatter extends LogFormatter {
                        // is shown on the correct side of the tooltip text.
                        $durationTooltip = '&lrm;' . htmlspecialchars( $params[4] );
                        $params[4] = Message::rawParam( "<span class='blockExpiry' title='$durationTooltip'>" .
-                               $this->context->getLanguage()->translateBlockExpiry( $params[4] ) . '</span>' );
+                               $this->context->getLanguage()->translateBlockExpiry( $params[4],
+                                       $this->context->getUser() ) . '</span>' );
                        $params[5] = isset( $params[5] ) ?
                                self::formatBlockFlags( $params[5], $this->context->getLanguage() ) : '';
                }
index 1d0a543..20d0217 100644 (file)
@@ -428,6 +428,9 @@ class ManualLogEntry extends LogEntryBase {
        /** @var int ID of the log entry */
        protected $id;
 
+       /** @var Can this log entry be patrolled? */
+       protected $isPatrollable = false;
+
        /** @var bool Whether this is a legacy log entry */
        protected $legacy = false;
 
@@ -545,6 +548,19 @@ class ManualLogEntry extends LogEntryBase {
                $this->tags = $tags;
        }
 
+       /**
+        * Set whether this log entry should be made patrollable
+        * This shouldn't depend on config, only on whether there is full support
+        * in the software for patrolling this log entry.
+        * False by default
+        *
+        * @since 1.27
+        * @param bool $patrollable
+        */
+       public function setIsPatrollable( $patrollable ) {
+               $this->isPatrollable = (bool)$patrollable;
+       }
+
        /**
         * Set the 'legacy' flag
         *
@@ -679,7 +695,8 @@ class ManualLogEntry extends LogEntryBase {
                        LogEntryBase::makeParamBlob( $this->getParameters() ),
                        $newId,
                        $formatter->getIRCActionComment(), // Used for IRC feeds
-                       $this->getAssociatedRevId() // Used for e.g. moves and uploads
+                       $this->getAssociatedRevId(), // Used for e.g. moves and uploads
+                       $this->getIsPatrollable()
                );
        }
 
@@ -706,8 +723,8 @@ class ManualLogEntry extends LogEntryBase {
                        $rc->notifyRCFeeds();
                }
 
-               // Log the autopatrol if an associated rev id was passed
-               if ( $this->getAssociatedRevId() > 0 &&
+               // Log the autopatrol if the log entry is patrollable
+               if ( $this->getIsPatrollable() &&
                        $rc->getAttribute( 'rc_patrolled' ) === 1 ) {
                        PatrolLog::record( $rc, true, $this->getPerformer() );
                }
@@ -775,6 +792,16 @@ class ManualLogEntry extends LogEntryBase {
                return $this->tags;
        }
 
+       /**
+        * Whether this log entry is patrollable
+        *
+        * @since 1.27
+        * @return bool
+        */
+       public function getIsPatrollable() {
+               return $this->isPatrollable;
+       }
+
        /**
         * @since 1.25
         * @return bool
index c96c0db..da5527e 100644 (file)
@@ -40,6 +40,11 @@ class LogEventsList extends ContextSource {
         */
        protected $showTagEditUI;
 
+       /**
+        * @var array
+        */
+       protected $allowedActions = null;
+
        /**
         * Constructor.
         * The first two parameters used to be $skin and $out, but now only a context
@@ -74,9 +79,10 @@ class LogEventsList extends ContextSource {
         * @param int $month Month
         * @param array $filter
         * @param string $tagFilter Tag to select by default
+        * @param string $action
         */
        public function showOptions( $types = [], $user = '', $page = '', $pattern = '', $year = 0,
-               $month = 0, $filter = null, $tagFilter = ''
+               $month = 0, $filter = null, $tagFilter = '', $action = null
        ) {
                global $wgScript, $wgMiserMode;
 
@@ -113,6 +119,11 @@ class LogEventsList extends ContextSource {
                        $html .= Xml::tags( 'p', null, $this->getFilterLinks( $filter ) );
                }
 
+               // Action filter
+               if ( $action !== null ) {
+                       $html .= Xml::tags( 'p', null, $this->getActionSelector( $types, $action ) );
+               }
+
                // Submit button
                $html .= Xml::submitButton( $this->msg( 'logeventslist-submit' )->text() );
 
@@ -184,7 +195,7 @@ class LogEventsList extends ContextSource {
                $selector = $this->getTypeSelector();
                $selector->setDefault( $queryType );
 
-               return $selector->getHtml();
+               return $selector->getHTML();
        }
 
        /**
@@ -287,6 +298,41 @@ class LogEventsList extends ContextSource {
                return '';
        }
 
+       /**
+        * Drop down menu for selection of actions that can be used to filter the log
+        * @param array $types
+        * @param string $action
+        * @return string
+        * @since 1.27
+        */
+       private function getActionSelector( $types, $action ) {
+               if ( $this->allowedActions === null || !count( $this->allowedActions ) ) {
+                       return '';
+               }
+               $html = '';
+               $html .= xml::label( wfMessage( 'log-action-filter-' . $types[0] )->text(),
+                       'action-filter-' .$types[0] ) . "\n";
+               $select = new XmlSelect( 'subtype' );
+               $select->addOption( wfMessage( 'log-action-filter-all' )->text(), '' );
+               foreach ( $this->allowedActions as $value ) {
+                       $msgKey = 'log-action-filter-' . $types[0] . '-' . $value;
+                       $select->addOption( wfMessage( $msgKey )->text(), $value );
+               }
+               $select->setDefault( $action );
+               $html .= $select->getHtml();
+               return $html;
+       }
+
+       /**
+        * Sets the action types allowed for log filtering
+        * To one action type may correspond several log_actions
+        * @param array $actions
+        * @since 1.27
+        */
+       public function setAllowedActions( $actions ) {
+               $this->allowedActions = $actions;
+       }
+
        /**
         * @return string
         */
index 11ae5d6..410c970 100644 (file)
@@ -42,6 +42,9 @@ class LogPager extends ReverseChronologicalPager {
        /** @var string */
        private $typeCGI = '';
 
+       /** @var string */
+       private $action = '';
+
        /** @var LogEventsList */
        public $mLogEventsList;
 
@@ -57,9 +60,12 @@ class LogPager extends ReverseChronologicalPager {
         * @param int|bool $year The year to start from. Default: false
         * @param int|bool $month The month to start from. Default: false
         * @param string $tagFilter Tag
+        * @param string $action Specific action (subtype) requested
         */
-       public function __construct( $list, $types = [], $performer = '', $title = '', $pattern = '',
-               $conds = [], $year = false, $month = false, $tagFilter = '' ) {
+       public function __construct( $list, $types = [], $performer = '', $title = '',
+               $pattern = '', $conds = [], $year = false, $month = false, $tagFilter = '',
+               $action = ''
+       ) {
                parent::__construct( $list->getContext() );
                $this->mConds = $conds;
 
@@ -68,6 +74,7 @@ class LogPager extends ReverseChronologicalPager {
                $this->limitType( $types ); // also excludes hidden types
                $this->limitPerformer( $performer );
                $this->limitTitle( $title, $pattern );
+               $this->limitAction( $action );
                $this->getDateCond( $year, $month );
                $this->mTagFilter = $tagFilter;
 
@@ -209,7 +216,7 @@ class LogPager extends ReverseChronologicalPager {
 
                $doUserRightsLogLike = false;
                if ( $this->types == [ 'rights' ] ) {
-                       $parts = explode( $wgUserrightsInterwikiDelimiter, $title->getDBKey() );
+                       $parts = explode( $wgUserrightsInterwikiDelimiter, $title->getDBkey() );
                        if ( count( $parts ) == 2 ) {
                                list( $name, $database ) = array_map( 'trim', $parts );
                                if ( strstr( $database, '*' ) ) { // Search for wildcard in database name
@@ -256,6 +263,31 @@ class LogPager extends ReverseChronologicalPager {
                }
        }
 
+       /**
+        * Set the log_action field to a specified value (or values)
+        *
+        * @param string $action
+        */
+       private function limitAction( $action ) {
+               global $wgActionFilteredLogs;
+               // Allow to filter the log by actions
+               $type = $this->typeCGI;
+               if ( $type === '' ) {
+                       // nothing to do
+                       return;
+               }
+               $actions = $wgActionFilteredLogs;
+               if ( isset( $actions[$type] ) ) {
+                       // log type can be filtered by actions
+                       $this->mLogEventsList->setAllowedActions( array_keys( $actions[$type] ) );
+                       if ( $action !== '' && isset( $actions[$type][$action] ) ) {
+                               // add condition to query
+                               $this->mConds['log_action'] = $actions[$type][$action];
+                               $this->action = $action;
+                       }
+               }
+       }
+
        /**
         * Constructs the most part of the query. Extra conditions are sprinkled in
         * all over this class.
@@ -381,6 +413,10 @@ class LogPager extends ReverseChronologicalPager {
                return $this->mTagFilter;
        }
 
+       public function getAction() {
+               return $this->action;
+       }
+
        public function doQuery() {
                // Workaround MySQL optimizer bug
                $this->mDb->setBigSelects();
index f6ecc50..d1de2cd 100644 (file)
@@ -58,7 +58,9 @@ class PatrolLog {
                        $user = $wgUser;
                }
 
-               $entry = new ManualLogEntry( 'patrol', 'patrol' );
+               $action = $auto ? 'autopatrol' : 'patrol';
+
+               $entry = new ManualLogEntry( 'patrol', $action );
                $entry->setTarget( $rc->getTitle() );
                $entry->setParameters( self::buildParams( $rc, $auto ) );
                $entry->setPerformer( $user );
index e6f9fb6..5b933ce 100644 (file)
  */
 class PatrolLogFormatter extends LogFormatter {
        protected function getMessageKey() {
-               $key = parent::getMessageKey();
                $params = $this->getMessageParameters();
                if ( isset( $params[5] ) && $params[5] ) {
-                       // Messages: logentry-patrol-patrol-auto
-                       $key .= '-auto';
+                       $key = 'logentry-patrol-patrol-auto';
+               } else {
+                       $key = 'logentry-patrol-patrol';
                }
 
                return $key;
index 4f8f6b3..fe24c34 100644 (file)
@@ -155,7 +155,7 @@ class EmailNotification {
                                $title,
                                [
                                        'editor' => $editor->getName(),
-                                       'editorID' => $editor->getID(),
+                                       'editorID' => $editor->getId(),
                                        'timestamp' => $timestamp,
                                        'summary' => $summary,
                                        'minorEdit' => $minorEdit,
@@ -232,7 +232,7 @@ class EmailNotification {
                                        if ( $watchingUser->getOption( 'enotifwatchlistpages' )
                                                && ( !$minorEdit || $watchingUser->getOption( 'enotifminoredits' ) )
                                                && $watchingUser->isEmailConfirmed()
-                                               && $watchingUser->getID() != $userTalkId
+                                               && $watchingUser->getId() != $userTalkId
                                                && !in_array( $watchingUser->getName(), $wgUsersNotifiedOnAllChanges )
                                                && !( $wgBlockDisablesLogin && $watchingUser->isBlocked() )
                                        ) {
index 1c7fb98..1059d7b 100644 (file)
@@ -107,9 +107,6 @@ class UserMailer {
         *              'contentType' string default 'text/plain; charset=UTF-8'
         *              'headers' array Extra headers to set
         *
-        * Previous versions of this function had $replyto as the 5th argument and $contentType
-        * as the 6th. These are still supported for backwards compatability, but deprecated.
-        *
         * @throws MWException
         * @throws Exception
         * @return Status
@@ -117,14 +114,6 @@ class UserMailer {
        public static function send( $to, $from, $subject, $body, $options = [] ) {
                global $wgAllowHTMLEmail;
 
-               if ( !is_array( $options ) ) {
-                       // Old calling style
-                       wfDeprecated( __METHOD__ . ' with $replyto as 5th parameter', '1.26' );
-                       $options = [ 'replyTo' => $options ];
-                       if ( func_num_args() === 6 ) {
-                               $options['contentType'] = func_get_arg( 5 );
-                       }
-               }
                if ( !isset( $options['contentType'] ) ) {
                        $options['contentType'] = 'text/plain; charset=UTF-8';
                }
index b055d16..4da41c8 100644 (file)
@@ -115,7 +115,7 @@ class BitmapHandler extends TransformationalImageHandler {
        protected function transformImageMagick( $image, $params ) {
                # use ImageMagick
                global $wgSharpenReductionThreshold, $wgSharpenParameter, $wgMaxAnimatedGifArea,
-                       $wgImageMagickTempDir, $wgImageMagickConvertCommand, $wgMaxInterlacingAreas;
+                       $wgImageMagickTempDir, $wgImageMagickConvertCommand;
 
                $quality = [];
                $sharpen = [];
index b91fb8a..56b20ac 100644 (file)
@@ -55,6 +55,6 @@ class BitmapHandler_ClientOnly extends BitmapHandler {
                        return new TransformParameterError( $params );
                }
 
-               return new ThumbnailImage( $image, $image->getURL(), $image->getLocalRefPath(), $params );
+               return new ThumbnailImage( $image, $image->getUrl(), $image->getLocalRefPath(), $params );
        }
 }
index d4ef8a8..9add138 100644 (file)
@@ -393,25 +393,24 @@ class DjVuHandler extends ImageHandler {
        }
 
        protected function getDimensionInfo( File $file ) {
-               $that = $this;
-
-               return ObjectCache::getMainWANInstance()->getWithSetCallback(
-                       wfMemcKey( 'file-djvu', 'dimensions', $file->getSha1() ),
-                       WANObjectCache::TTL_INDEFINITE,
-                       function () use ( $that, $file ) {
-                               $tree = $that->getMetaTree( $file );
+               $cache = ObjectCache::getMainWANInstance();
+               return $cache->getWithSetCallback(
+                       $cache->makeKey( 'file-djvu', 'dimensions', $file->getSha1() ),
+                       $cache::TTL_INDEFINITE,
+                       function () use ( $file ) {
+                               $tree = $this->getMetaTree( $file );
                                if ( !$tree ) {
                                        return false;
                                }
 
                                $dimsByPage = [];
                                $count = count( $tree->xpath( '//OBJECT' ) );
-                               for ( $i = 0; $i < $count; ++$i ) {
+                               for ( $i = 0; $i < $count; $i++ ) {
                                        $o = $tree->BODY[0]->OBJECT[$i];
                                        if ( $o ) {
                                                $dimsByPage[$i] = [
                                                        'width' => (int)$o['width'],
-                                                       'height' => (int)$o['height']
+                                                       'height' => (int)$o['height'],
                                                ];
                                        } else {
                                                $dimsByPage[$i] = false;
@@ -419,7 +418,8 @@ class DjVuHandler extends ImageHandler {
                                }
 
                                return [ 'pageCount' => $count, 'dimensionsByPage' => $dimsByPage ];
-                       }
+                       },
+                       [ 'pcTTL' => $cache::TTL_INDEFINITE ]
                );
        }
 
index 9a6547f..9176b54 100644 (file)
@@ -395,7 +395,7 @@ class ThumbnailImage extends MediaTransformOutput {
                                $query
                        );
                } elseif ( !empty( $options['file-link'] ) ) {
-                       $linkAttribs = [ 'href' => $this->file->getURL() ];
+                       $linkAttribs = [ 'href' => $this->file->getUrl() ];
                } else {
                        $linkAttribs = false;
                        if ( !empty( $options['title'] ) ) {
index 7e77b25..2bb6d13 100644 (file)
@@ -468,7 +468,7 @@ class SvgHandler extends ImageHandler {
                        return ( $value > 0 );
                } elseif ( $name == 'lang' ) {
                        // Validate $code
-                       if ( $value === '' || !Language::isValidBuiltinCode( $value ) ) {
+                       if ( $value === '' || !Language::isValidBuiltInCode( $value ) ) {
                                wfDebug( "Invalid user language code\n" );
 
                                return false;
index f777230..62b5c2c 100644 (file)
@@ -229,7 +229,7 @@ class SVGReader {
                }
                // @todo Find and store type of xml snippet. metadata['metadataType'] = "rdf"
                if ( method_exists( $this->reader, 'readInnerXML' ) ) {
-                       $this->metadata[$metafield] = trim( $this->reader->readInnerXML() );
+                       $this->metadata[$metafield] = trim( $this->reader->readInnerXml() );
                } else {
                        throw new MWException( "The PHP XMLReader extension does not come " .
                                "with readInnerXML() method. Your libxml is probably out of " .
index f6483a1..f1f2161 100644 (file)
@@ -335,7 +335,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
                        'height' => $scalerParams['clientHeight']
                ];
 
-               return new ThumbnailImage( $image, $image->getURL(), null, $params );
+               return new ThumbnailImage( $image, $image->getUrl(), null, $params );
        }
 
        /**
index 8fda751..35e885f 100644 (file)
@@ -63,9 +63,9 @@ class WebPHandler extends BitmapHandler {
                                return self::METADATA_GOOD;
                }
 
-               wfSuppressWarnings();
+               MediaWiki\suppressWarnings();
                $data = unserialize( $metadata );
-               wfRestoreWarnings();
+               MediaWiki\restoreWarnings();
 
                if ( !$data || !is_array( $data ) ) {
                                wfDebug( __METHOD__ . " invalid WebP metadata\n" );
@@ -154,7 +154,7 @@ class WebPHandler extends BitmapHandler {
        /**
         * Decodes a lossy chunk header
         * @param string $header Header string
-        * @return boolean|array See WebPHandler::decodeHeader
+        * @return bool|array See WebPHandler::decodeHeader
         */
        protected static function decodeLossyChunkHeader( $header ) {
                // Bytes 0-3 are 'VP8 '
@@ -180,7 +180,7 @@ class WebPHandler extends BitmapHandler {
        /**
         * Decodes a lossless chunk header
         * @param string $header Header string
-        * @return boolean|array See WebPHandler::decodeHeader
+        * @return bool|array See WebPHandler::decodeHeader
         */
        public static function decodeLosslessChunkHeader( $header ) {
                // Bytes 0-3 are 'VP8L'
@@ -205,7 +205,7 @@ class WebPHandler extends BitmapHandler {
        /**
         * Decodes an extended chunk header
         * @param string $header Header string
-        * @return boolean|array See WebPHandler::decodeHeader
+        * @return bool|array See WebPHandler::decodeHeader
         */
        public static function decodeExtendedChunkHeader( $header ) {
                // Bytes 0-3 are 'VP8X'
@@ -234,9 +234,9 @@ class WebPHandler extends BitmapHandler {
                        $metadata = $file->getMetadata();
                }
 
-               wfSuppressWarnings();
+               MediaWiki\suppressWarnings();
                $metadata = unserialize( $metadata );
-               wfRestoreWarnings();
+               MediaWiki\restoreWarnings();
 
                if ( $metadata == false ) {
                        return false;
index f8fa252..6ac675e 100644 (file)
@@ -68,21 +68,15 @@ class XCFHandler extends BitmapHandler {
 
                # Forge a return array containing metadata information just like getimagesize()
                # See PHP documentation at: http://www.php.net/getimagesize
-               $metadata = [];
-               $metadata[0] = $header['width'];
-               $metadata[1] = $header['height'];
-               $metadata[2] = null; # IMAGETYPE constant, none exist for XCF.
-               $metadata[3] = sprintf(
-                       'height="%s" width="%s"', $header['height'], $header['width']
-               );
-               $metadata['mime'] = 'image/x-xcf';
-               $metadata['channels'] = null;
-               $metadata['bits'] = 8; # Always 8-bits per color
-
-               assert( '7 == count($metadata); ' .
-                       '# return array must contains 7 elements just like getimagesize() return' );
-
-               return $metadata;
+               return [
+                       0 => $header['width'],
+                       1 => $header['height'],
+                       2 => null, # IMAGETYPE constant, none exist for XCF.
+                       3 => "height=\"{$header['height']}\" width=\"{$header['width']}\"",
+                       'mime' => 'image/x-xcf',
+                       'channels' => null,
+                       'bits' => 8, # Always 8-bits per color
+               ];
        }
 
        /**
@@ -161,7 +155,7 @@ class XCFHandler extends BitmapHandler {
         * @return string
         */
        public function getMetadata( $file, $filename ) {
-               $header = self::getXCFMetadata( $filename );
+               $header = self::getXCFMetaData( $filename );
                $metadata = [];
                if ( $header ) {
                        // Try to be consistent with the names used by PNG files.
index f6b490a..6c42e34 100644 (file)
@@ -225,7 +225,7 @@ class Article implements Page {
         */
        protected function getContentObject() {
 
-               if ( $this->mPage->getID() === 0 ) {
+               if ( $this->mPage->getId() === 0 ) {
                        # If this is a MediaWiki:x message, then load the messages
                        # and return the message value for x.
                        if ( $this->getTitle()->getNamespace() == NS_MEDIAWIKI ) {
@@ -282,7 +282,7 @@ class Article implements Page {
                                $this->mRevision = Revision::newFromId( $oldid );
                                if ( $this->mRevision !== null ) {
                                        // Revision title doesn't match the page title given?
-                                       if ( $this->mPage->getID() != $this->mRevision->getPage() ) {
+                                       if ( $this->mPage->getId() != $this->mRevision->getPage() ) {
                                                $function = [ get_class( $this->mPage ), 'newFromID' ];
                                                $this->mPage = call_user_func( $function, $this->mRevision->getPage() );
                                        }
@@ -768,7 +768,7 @@ class Article implements Page {
                                ->params( $oldid )
                                ->numParams( 1 )
                                ->parseAsBlock();
-                       $this->getContext()->getOutput()->addHtml( $msg );
+                       $this->getContext()->getOutput()->addHTML( $msg );
                        return;
                }
 
@@ -863,7 +863,7 @@ class Article implements Page {
                        }
                }
 
-               if ( $this->mPage->getID() === 0 || $this->getOldID() ) {
+               if ( $this->mPage->getId() === 0 || $this->getOldID() ) {
                        # Non-articles (special pages etc), and old revisions
                        return [
                                'index' => 'noindex',
@@ -1445,7 +1445,7 @@ class Article implements Page {
                $outputPage->addSubtitle( "<div id=\"mw-{$infomsg}\">" .
                        $context->msg( $infomsg, $td )
                                ->rawParams( $userlinks )
-                               ->params( $revision->getID(), $tddate, $tdtime, $revision->getUserText() )
+                               ->params( $revision->getId(), $tddate, $tdtime, $revision->getUserText() )
                                ->rawParams( Linker::revComment( $revision, true, true ) )
                                ->parse() .
                        "</div>"
@@ -1572,9 +1572,8 @@ class Article implements Page {
                                $title,
                                htmlspecialchars( $title->getFullText() ),
                                [],
-                               // Automatically append redirect=no to each link, since most of them are
-                               // redirect pages themselves.
-                               [ 'redirect' => 'no' ],
+                               // Make sure wiki page redirects are not followed
+                               $title->isRedirect() ? [ 'redirect' => 'no' ] : [],
                                ( $forceKnown ? [ 'known', 'noclasses' ] : [] )
                        ) . '</li>';
                }
@@ -1644,6 +1643,7 @@ class Article implements Page {
                $title = $this->getTitle();
                $context = $this->getContext();
                $user = $context->getUser();
+               $request = $context->getRequest();
 
                # Check permissions
                $permissionErrors = $title->getUserPermissionsErrors( 'delete', $user );
@@ -1657,7 +1657,9 @@ class Article implements Page {
                }
 
                # Better double-check that it hasn't been deleted yet!
-               $this->mPage->loadPageData( 'fromdbmaster' );
+               $this->mPage->loadPageData(
+                       $request->wasPosted() ? WikiPage::READ_LATEST : WikiPage::READ_NORMAL
+               );
                if ( !$this->mPage->exists() ) {
                        $deleteLogPage = new LogPage( 'delete' );
                        $outputPage = $context->getOutput();
@@ -1677,7 +1679,6 @@ class Article implements Page {
                        return;
                }
 
-               $request = $context->getRequest();
                $deleteReasonList = $request->getText( 'wpDeleteReasonList', 'other' );
                $deleteReason = $request->getText( 'wpReason' );
 
@@ -1961,7 +1962,7 @@ class Article implements Page {
                $cacheable = false;
 
                if ( HTMLFileCache::useFileCache( $this->getContext() ) ) {
-                       $cacheable = $this->mPage->getID()
+                       $cacheable = $this->mPage->getId()
                                && !$this->mRedirectedFrom && !$this->getTitle()->isRedirect();
                        // Extension may have reason to disable file caching on some pages.
                        if ( $cacheable ) {
@@ -2378,15 +2379,6 @@ class Article implements Page {
                return $this->mPage->getUndoContent( $undo, $undoafter );
        }
 
-       /**
-        * Call to WikiPage function for backwards compatibility.
-        * @see WikiPage::getUndoText
-        */
-       public function getUndoText( Revision $undo, Revision $undoafter = null ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-               return $this->mPage->getUndoText( $undo, $undoafter );
-       }
-
        /**
         * Call to WikiPage function for backwards compatibility.
         * @see WikiPage::getUser
@@ -2549,19 +2541,6 @@ class Article implements Page {
                return $this->mPage->protectDescriptionLog( $limit, $expiry );
        }
 
-       /**
-        * Call to WikiPage function for backwards compatibility.
-        * @see WikiPage::replaceSection
-        */
-       public function replaceSection( $sectionId, $text, $sectionTitle = '',
-               $edittime = null
-       ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-               return $this->mPage->replaceSection( $sectionId, $text, $sectionTitle,
-                       $edittime
-               );
-       }
-
        /**
         * Call to WikiPage function for backwards compatibility.
         * @see WikiPage::replaceSectionAtRev
index e569762..106911c 100644 (file)
@@ -160,7 +160,7 @@ class ImagePage extends Article {
                }
 
                # No need to display noarticletext, we use our own message, output in openShowImage()
-               if ( $this->mPage->getID() ) {
+               if ( $this->mPage->getId() ) {
                        # NS_FILE is in the user language, but this section (the actual wikitext)
                        # should be in page content language
                        $pageLang = $this->getTitle()->getPageViewLanguage();
@@ -299,7 +299,7 @@ class ImagePage extends Article {
         */
        public function getContentObject() {
                $this->loadFile();
-               if ( $this->mPage->getFile() && !$this->mPage->getFile()->isLocal() && 0 == $this->getID() ) {
+               if ( $this->mPage->getFile() && !$this->mPage->getFile()->isLocal() && 0 == $this->getId() ) {
                        return null;
                }
                return parent::getContentObject();
@@ -565,7 +565,7 @@ EOT
                                if ( is_null( $currentLanguage ) ) {
                                        $currentLanguage = $defaultLang;
                                }
-                               $out->addHtml( $this->doRenderLangOpt( $renderLangOptions, $currentLanguage, $defaultLang ) );
+                               $out->addHTML( $this->doRenderLangOpt( $renderLangOptions, $currentLanguage, $defaultLang ) );
                        }
 
                        // Add cannot animate thumbnail warning
@@ -592,7 +592,7 @@ EOT
                        }
                } else {
                        # Image does not exist
-                       if ( !$this->getID() ) {
+                       if ( !$this->getId() ) {
                                # No article exists either
                                # Show deletion log to be consistent with normal articles
                                LogEventsList::showLogExtract(
@@ -623,7 +623,7 @@ EOT
                        // by Article::View().
                        $out->setRobotPolicy( 'noindex,nofollow' );
                        $out->wrapWikiMsg( "<div id='mw-imagepage-nofile' class='plainlinks'>\n$1\n</div>", $nofile );
-                       if ( !$this->getID() && $wgSend404Code ) {
+                       if ( !$this->getId() && $wgSend404Code ) {
                                // If there is no image, no shared image, and no description page,
                                // output a 404, to be consistent with Article::showMissingArticle.
                                $request->response()->statusHeader( 404 );
@@ -635,7 +635,7 @@ EOT
        /**
         * Make the text under the image to say what size preview
         *
-        * @param $params Array parameters for thumbnail
+        * @param $params array parameters for thumbnail
         * @param $sizeLinkBigImagePreview HTML for the current size
         * @return string HTML output
         */
@@ -704,7 +704,7 @@ EOT
                $descText = $this->mPage->getFile()->getDescriptionText( $this->getContext()->getLanguage() );
 
                /* Add canonical to head if there is no local page for this shared file */
-               if ( $descUrl && $this->mPage->getID() == 0 ) {
+               if ( $descUrl && $this->mPage->getId() == 0 ) {
                        $out->setCanonicalUrl( $descUrl );
                }
 
diff --git a/includes/page/Page.php b/includes/page/Page.php
new file mode 100644 (file)
index 0000000..2cb1fc0
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
+ */
+interface Page {
+}
index d81efa6..5e5532f 100644 (file)
  * @file
  */
 
-/**
- * Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
- */
-interface Page {
-}
-
 /**
  * Class representing a MediaWiki article and history.
  *
@@ -1351,76 +1345,6 @@ class WikiPage implements Page, IDBAccessObject {
                return $handler->getUndoContent( $this->getRevision(), $undo, $undoafter );
        }
 
-       /**
-        * Get the text that needs to be saved in order to undo all revisions
-        * between $undo and $undoafter. Revisions must belong to the same page,
-        * must exist and must not be deleted
-        * @param Revision $undo
-        * @param Revision $undoafter Must be an earlier revision than $undo
-        * @return string|bool String on success, false on failure
-        * @deprecated since 1.21: use ContentHandler::getUndoContent() instead.
-        */
-       public function getUndoText( Revision $undo, Revision $undoafter = null ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-
-               $this->loadLastEdit();
-
-               if ( $this->mLastRevision ) {
-                       if ( is_null( $undoafter ) ) {
-                               $undoafter = $undo->getPrevious();
-                       }
-
-                       $handler = $this->getContentHandler();
-                       $undone = $handler->getUndoContent( $this->mLastRevision, $undo, $undoafter );
-
-                       if ( !$undone ) {
-                               return false;
-                       } else {
-                               return ContentHandler::getContentText( $undone );
-                       }
-               }
-
-               return false;
-       }
-
-       /**
-        * @param string|number|null|bool $sectionId Section identifier as a number or string
-        * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
-        * or 'new' for a new section.
-        * @param string $text New text of the section.
-        * @param string $sectionTitle New section's subject, only if $section is "new".
-        * @param string $edittime Revision timestamp or null to use the current revision.
-        *
-        * @throws MWException
-        * @return string|null New complete article text, or null if error.
-        *
-        * @deprecated since 1.21, use replaceSectionAtRev() instead
-        */
-       public function replaceSection( $sectionId, $text, $sectionTitle = '',
-               $edittime = null
-       ) {
-               ContentHandler::deprecated( __METHOD__, '1.21' );
-
-               // NOTE: keep condition in sync with condition in replaceSectionContent!
-               if ( strval( $sectionId ) === '' ) {
-                       // Whole-page edit; let the whole text through
-                       return $text;
-               }
-
-               if ( !$this->supportsSections() ) {
-                       throw new MWException( "sections not supported for content model " .
-                               $this->getContentHandler()->getModelID() );
-               }
-
-               // could even make section title, but that's not required.
-               $sectionContent = ContentHandler::makeContent( $text, $this->getTitle() );
-
-               $newContent = $this->replaceSectionContent( $sectionId, $sectionContent, $sectionTitle,
-                       $edittime );
-
-               return ContentHandler::getContentText( $newContent );
-       }
-
        /**
         * Returns true if this page's content model supports sections.
         *
@@ -2880,7 +2804,7 @@ class WikiPage implements Page, IDBAccessObject {
                $dbw->startAtomic( __METHOD__ );
 
                $this->loadPageData( self::READ_LATEST );
-               $id = $this->getID();
+               $id = $this->getId();
                // T98706: lock the page from various other updates but avoid using
                // WikiPage::READ_LOCKING as that will carry over the FOR UPDATE to
                // the revisions queries (which also JOIN on user). Only lock the page
index 2c415d6..31c9c6d 100644 (file)
@@ -115,7 +115,7 @@ abstract class ReverseChronologicalPager extends IndexPager {
 
                // Treat the given time in the wiki timezone and get a UTC timestamp for the database lookup
                $timestamp = MWTimestamp::getInstance( "${ymd}000000" );
-               $timestamp->setTimeZone( $this->getConfig()->get( 'Localtimezone' ) );
+               $timestamp->setTimezone( $this->getConfig()->get( 'Localtimezone' ) );
 
                $this->mOffset = $this->mDb->timestamp( $timestamp->getTimestamp() );
        }
index e22ceba..0a89e4e 100644 (file)
@@ -264,26 +264,23 @@ abstract class TablePager extends IndexPager {
        }
 
        /**
-        * @protected
         * @return string
         */
-       function getTableClass() {
+       protected function getTableClass() {
                return 'TablePager';
        }
 
        /**
-        * @protected
         * @return string
         */
-       function getNavClass() {
+       protected function getNavClass() {
                return 'TablePager_nav';
        }
 
        /**
-        * @protected
         * @return string
         */
-       function getSortHeaderClass() {
+       protected function getSortHeaderClass() {
                return 'TablePager_sort';
        }
 
index 1cc0efc..a55ddf3 100644 (file)
@@ -634,7 +634,7 @@ class CoreParserFunctions {
                if ( is_null( $t ) ) {
                        return '';
                }
-               return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getRootText() ) ) );
+               return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getRootText() ) ) );
        }
        public static function basepagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
@@ -648,7 +648,7 @@ class CoreParserFunctions {
                if ( is_null( $t ) ) {
                        return '';
                }
-               return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getBaseText() ) ) );
+               return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getBaseText() ) ) );
        }
        public static function talkpagename( $parser, $title = null ) {
                $t = Title::newFromText( $title );
index d7ba266..d2e4bf0 100644 (file)
@@ -1115,7 +1115,7 @@ class Parser {
 
                                // Implies both are valid for table headings.
                                if ( $first_character === '!' ) {
-                                       $line = str_replace( '!!', '||', $line );
+                                       $line = StringUtils::replaceMarkup( '!!', '||', $line );
                                }
 
                                # Split up multiple cells on the same line.
@@ -3000,7 +3000,7 @@ class Parser {
                                $value = wfEscapeWikiText( $this->mTitle->getRootText() );
                                break;
                        case 'rootpagenamee':
-                               $value = wfEscapeWikiText( wfUrlEncode( str_replace(
+                               $value = wfEscapeWikiText( wfUrlencode( str_replace(
                                        ' ',
                                        '_',
                                        $this->mTitle->getRootText()
@@ -3010,7 +3010,7 @@ class Parser {
                                $value = wfEscapeWikiText( $this->mTitle->getBaseText() );
                                break;
                        case 'basepagenamee':
-                               $value = wfEscapeWikiText( wfUrlEncode( str_replace(
+                               $value = wfEscapeWikiText( wfUrlencode( str_replace(
                                        ' ',
                                        '_',
                                        $this->mTitle->getBaseText()
index bd5afaf..916cfc2 100644 (file)
@@ -64,7 +64,7 @@ class ParserCache {
                global $wgRequest;
 
                // idhash seem to mean 'page id' + 'rendering hash' (r3710)
-               $pageid = $article->getID();
+               $pageid = $article->getId();
                $renderkey = (int)( $wgRequest->getVal( 'action' ) == 'render' );
 
                $key = wfMemcKey( 'pcache', 'idhash', "{$pageid}-{$renderkey}!{$hash}" );
@@ -76,7 +76,7 @@ class ParserCache {
         * @return mixed|string
         */
        protected function getOptionsKey( $article ) {
-               $pageid = $article->getID();
+               $pageid = $article->getId();
                return wfMemcKey( 'pcache', 'idoptions', "{$pageid}" );
        }
 
index d2559f7..729b9db 100644 (file)
@@ -860,7 +860,7 @@ class ParserOptions {
                                                'page' => $title->getArticleID(),
                                                'user_text' => $user->getName(),
                                                'user' => $user->getId(),
-                                               'parent_id' => $title->getLatestRevId(),
+                                               'parent_id' => $title->getLatestRevID(),
                                                'title' => $title,
                                                'content' => $content
                                        ] );
index 368d79e..cc98abd 100644 (file)
@@ -260,8 +260,8 @@ interface PPFrame {
 
        /**
         * Get an argument to this frame by name
-        * @param string $name
-        * @return bool
+        * @param int|string $name
+        * @return string|bool
         */
        public function getArgument( $name );
 
index 79a66e0..a28c0aa 100644 (file)
@@ -196,6 +196,7 @@ class Preprocessor_DOM extends Preprocessor {
                $forInclusion = $flags & Parser::PTD_FOR_INCLUSION;
 
                $xmlishElements = $this->parser->getStripList();
+               $xmlishAllowMissingEndTag = [ 'includeonly', 'noinclude', 'onlyinclude' ];
                $enableOnlyinclude = false;
                if ( $forInclusion ) {
                        $ignoredTags = [ 'includeonly', '/includeonly' ];
@@ -237,6 +238,8 @@ class Preprocessor_DOM extends Preprocessor {
                $inHeading = false;
                // True if there are no more greater-than (>) signs right of $i
                $noMoreGT = false;
+               // Map of tag name => true if there are no more closing tags of given type right of $i
+               $noMoreClosingTag = [];
                // True to ignore all input up to the next <onlyinclude>
                $findOnlyinclude = $enableOnlyinclude;
                // Do a line-start run without outputting an LF character
@@ -457,17 +460,29 @@ class Preprocessor_DOM extends Preprocessor {
                                } else {
                                        $attrEnd = $tagEndPos;
                                        // Find closing tag
-                                       if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i",
+                                       if (
+                                               !isset( $noMoreClosingTag[$name] ) &&
+                                               preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i",
                                                        $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 )
                                        ) {
                                                $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 );
                                                $i = $matches[0][1] + strlen( $matches[0][0] );
                                                $close = '<close>' . htmlspecialchars( $matches[0][0] ) . '</close>';
                                        } else {
-                                               // No end tag -- let it run out to the end of the text.
-                                               $inner = substr( $text, $tagEndPos + 1 );
-                                               $i = $lengthText;
-                                               $close = '';
+                                               // No end tag
+                                               if ( in_array( $name, $xmlishAllowMissingEndTag ) ) {
+                                                       // Let it run out to the end of the text.
+                                                       $inner = substr( $text, $tagEndPos + 1 );
+                                                       $i = $lengthText;
+                                                       $close = '';
+                                               } else {
+                                                       // Don't match the tag, treat opening tag as literal and resume parsing.
+                                                       $i = $tagEndPos + 1;
+                                                       $accum .= htmlspecialchars( substr( $text, $tagStartPos, $tagEndPos + 1 - $tagStartPos ) );
+                                                       // Cache results, otherwise we have O(N^2) performance for input like <foo><foo><foo>...
+                                                       $noMoreClosingTag[$name] = true;
+                                                       continue;
+                                               }
                                        }
                                }
                                // <includeonly> and <noinclude> just become <ignore> tags
@@ -1462,6 +1477,10 @@ class PPFrame_DOM implements PPFrame {
                return true;
        }
 
+       /**
+        * @param int|string $name
+        * @return bool Always false in this implementation.
+        */
        public function getArgument( $name ) {
                return false;
        }
@@ -1646,6 +1665,10 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $arguments;
        }
 
+       /**
+        * @param int $index
+        * @return string|bool
+        */
        public function getNumberedArgument( $index ) {
                if ( !isset( $this->numberedArgs[$index] ) ) {
                        return false;
@@ -1660,6 +1683,10 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $this->numberedExpansionCache[$index];
        }
 
+       /**
+        * @param string $name
+        * @return string|bool
+        */
        public function getNamedArgument( $name ) {
                if ( !isset( $this->namedArgs[$name] ) ) {
                        return false;
@@ -1672,6 +1699,10 @@ class PPTemplateFrame_DOM extends PPFrame_DOM {
                return $this->namedExpansionCache[$name];
        }
 
+       /**
+        * @param int|string $name
+        * @return string|bool
+        */
        public function getArgument( $name ) {
                $text = $this->getNumberedArgument( $name );
                if ( $text === false ) {
@@ -1738,6 +1769,10 @@ class PPCustomFrame_DOM extends PPFrame_DOM {
                return !count( $this->args );
        }
 
+       /**
+        * @param int|string $index
+        * @return string|bool
+        */
        public function getArgument( $index ) {
                if ( !isset( $this->args[$index] ) ) {
                        return false;
index 24baae4..0e11967 100644 (file)
@@ -120,6 +120,7 @@ class Preprocessor_Hash extends Preprocessor {
                $forInclusion = $flags & Parser::PTD_FOR_INCLUSION;
 
                $xmlishElements = $this->parser->getStripList();
+               $xmlishAllowMissingEndTag = [ 'includeonly', 'noinclude', 'onlyinclude' ];
                $enableOnlyinclude = false;
                if ( $forInclusion ) {
                        $ignoredTags = [ 'includeonly', '/includeonly' ];
@@ -160,6 +161,8 @@ class Preprocessor_Hash extends Preprocessor {
                $inHeading = false;
                // True if there are no more greater-than (>) signs right of $i
                $noMoreGT = false;
+               // Map of tag name => true if there are no more closing tags of given type right of $i
+               $noMoreClosingTag = [];
                // True to ignore all input up to the next <onlyinclude>
                $findOnlyinclude = $enableOnlyinclude;
                // Do a line-start run without outputting an LF character
@@ -380,17 +383,29 @@ class Preprocessor_Hash extends Preprocessor {
                                } else {
                                        $attrEnd = $tagEndPos;
                                        // Find closing tag
-                                       if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i",
+                                       if (
+                                               !isset( $noMoreClosingTag[$name] ) &&
+                                               preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i",
                                                        $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 )
                                        ) {
                                                $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 );
                                                $i = $matches[0][1] + strlen( $matches[0][0] );
                                                $close = $matches[0][0];
                                        } else {
-                                               // No end tag -- let it run out to the end of the text.
-                                               $inner = substr( $text, $tagEndPos + 1 );
-                                               $i = $lengthText;
-                                               $close = null;
+                                               // No end tag
+                                               if ( in_array( $name, $xmlishAllowMissingEndTag ) ) {
+                                                       // Let it run out to the end of the text.
+                                                       $inner = substr( $text, $tagEndPos + 1 );
+                                                       $i = $lengthText;
+                                                       $close = null;
+                                               } else {
+                                                       // Don't match the tag, treat opening tag as literal and resume parsing.
+                                                       $i = $tagEndPos + 1;
+                                                       $accum->addLiteral( substr( $text, $tagStartPos, $tagEndPos + 1 - $tagStartPos ) );
+                                                       // Cache results, otherwise we have O(N^2) performance for input like <foo><foo><foo>...
+                                                       $noMoreClosingTag[$name] = true;
+                                                       continue;
+                                               }
                                        }
                                }
                                // <includeonly> and <noinclude> just become <ignore> tags
@@ -1355,8 +1370,8 @@ class PPFrame_Hash implements PPFrame {
        }
 
        /**
-        * @param string $name
-        * @return bool
+        * @param int|string $name
+        * @return bool Always false in this implementation.
         */
        public function getArgument( $name ) {
                return false;
@@ -1549,7 +1564,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
 
        /**
         * @param int $index
-        * @return array|bool
+        * @return string|bool
         */
        public function getNumberedArgument( $index ) {
                if ( !isset( $this->numberedArgs[$index] ) ) {
@@ -1567,7 +1582,7 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
 
        /**
         * @param string $name
-        * @return bool
+        * @return string|bool
         */
        public function getNamedArgument( $name ) {
                if ( !isset( $this->namedArgs[$name] ) ) {
@@ -1582,8 +1597,8 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
        }
 
        /**
-        * @param string $name
-        * @return array|bool
+        * @param int|string $name
+        * @return string|bool
         */
        public function getArgument( $name ) {
                $text = $this->getNumberedArgument( $name );
@@ -1652,8 +1667,8 @@ class PPCustomFrame_Hash extends PPFrame_Hash {
        }
 
        /**
-        * @param int $index
-        * @return bool
+        * @param int|string $index
+        * @return string|bool
         */
        public function getArgument( $index ) {
                if ( !isset( $this->args[$index] ) ) {
index 1ec14aa..acdbd81 100644 (file)
@@ -71,11 +71,11 @@ abstract class PoolCounter {
        protected $timeout;
 
        /**
-        * @var boolean Whether the key is a "might wait" key
+        * @var bool Whether the key is a "might wait" key
         */
        private $isMightWaitKey;
        /**
-        * @var boolean Whether this process holds a "might wait" lock key
+        * @var bool Whether this process holds a "might wait" lock key
         */
        private static $acquiredMightWaitKey = 0;
 
index fe9304f..7c60aa5 100644 (file)
@@ -168,12 +168,12 @@ class ExtensionProcessor implements Processor {
                $this->extractCredits( $path, $info );
                foreach ( $info as $key => $val ) {
                        if ( in_array( $key, self::$globalSettings ) ) {
-                               $this->storeToArray( "wg$key", $val, $this->globals );
+                               $this->storeToArray( $path, "wg$key", $val, $this->globals );
                        // Ignore anything that starts with a @
                        } elseif ( $key[0] !== '@' && !in_array( $key, self::$notAttributes )
                                && !in_array( $key, self::$creditsAttributes )
                        ) {
-                               $this->storeToArray( $key, $val, $this->attributes );
+                               $this->storeToArray( $path, $key, $val, $this->attributes );
                        }
                }
        }
@@ -367,14 +367,15 @@ class ExtensionProcessor implements Processor {
        }
 
        /**
+        * @param string $path
         * @param string $name
         * @param array $value
         * @param array &$array
         * @throws InvalidArgumentException
         */
-       protected function storeToArray( $name, $value, &$array ) {
+       protected function storeToArray( $path, $name, $value, &$array ) {
                if ( !is_array( $value ) ) {
-                       throw new InvalidArgumentException( "The value for '$name' should be an array" );
+                       throw new InvalidArgumentException( "The value for '$name' should be an array (from $path)" );
                }
                if ( isset( $array[$name] ) ) {
                        $array[$name] = array_merge_recursive( $array[$name], $value );
index 33395f7..dc53ca4 100644 (file)
@@ -274,13 +274,12 @@ class ExtensionRegistry {
                foreach ( $info['defines'] as $name => $val ) {
                        define( $name, $val );
                }
-               foreach ( $info['callbacks'] as $cb ) {
-                       call_user_func( $cb );
-               }
-
                foreach ( $info['autoloaderPaths'] as $path ) {
                        require_once $path;
                }
+               foreach ( $info['callbacks'] as $cb ) {
+                       call_user_func( $cb );
+               }
 
                $this->loaded += $info['credits'];
                if ( $info['attributes'] ) {
index c689979..0aa08be 100644 (file)
@@ -88,7 +88,7 @@ class ResourceLoader implements LoggerAwareInterface {
        private $logger;
 
        /** @var string JavaScript / CSS pragma to disable minification. **/
-       const FILTER_NOMIN = ' /* @nomin */ ';
+       const FILTER_NOMIN = '/*@nomin*/';
 
        /**
         * Load information stored in the database about modules.
@@ -1362,8 +1362,8 @@ MESSAGE;
         * @return string
         */
        public static function makeLoaderConditionalScript( $script ) {
-               return "(window.RLQ = window.RLQ || []).push(function () {\n" .
-                       trim( $script ) . "\n} );";
+               return '(window.RLQ=window.RLQ||[]).push(function(){' .
+                       trim( $script ) . '});';
        }
 
        /**
@@ -1379,8 +1379,8 @@ MESSAGE;
                $js = self::makeLoaderConditionalScript( $script );
                return new WrappedString(
                        Html::inlineScript( $js ),
-                       "<script>(window.RLQ = window.RLQ || []).push(function () {\n",
-                       "\n} );</script>"
+                       '<script>(window.RLQ=window.RLQ||[]).push(function(){',
+                       '});</script>'
                );
        }
 
@@ -1396,7 +1396,7 @@ MESSAGE;
                        'mw.config.set',
                        [ $configuration ],
                        ResourceLoader::inDebugMode()
-               ) . ResourceLoader::FILTER_NOMIN;
+               );
        }
 
        /**
index 6458e71..8e0239a 100644 (file)
@@ -211,6 +211,18 @@ class ResourceLoaderContext {
                return $this->user;
        }
 
+       /**
+        * Get a Message object with context set.  See wfMessage for parameters.
+        *
+        * @since 1.27
+        * @param mixed ...
+        * @return Message
+        */
+       public function msg() {
+               return call_user_func_array( 'wfMessage', func_get_args() )
+                       ->inLanguage( $this->getLanguage() );
+       }
+
        /**
         * Get the possibly-cached User object for the specified username
         *
index 43fd2db..87e5fd7 100644 (file)
@@ -179,7 +179,7 @@ class ResourceLoaderImage {
                        'version' => $context->getVersion(),
                ];
 
-               return wfExpandUrl( wfAppendQuery( $script, $query ), PROTO_RELATIVE );
+               return wfAppendQuery( $script, $query );
        }
 
        /**
@@ -272,7 +272,7 @@ class ResourceLoaderImage {
         */
        protected function variantize( $variantConf, ResourceLoaderContext $context ) {
                $dom = new DomDocument;
-               $dom->loadXml( file_get_contents( $this->getPath( $context ) ) );
+               $dom->loadXML( file_get_contents( $this->getPath( $context ) ) );
                $root = $dom->documentElement;
                $wrapper = $dom->createElement( 'g' );
                while ( $root->firstChild ) {
@@ -280,7 +280,7 @@ class ResourceLoaderImage {
                }
                $root->appendChild( $wrapper );
                $wrapper->setAttribute( 'fill', $variantConf['color'] );
-               return $dom->saveXml();
+               return $dom->saveXML();
        }
 
        /**
@@ -295,7 +295,7 @@ class ResourceLoaderImage {
         */
        protected function massageSvgPathdata( $svg ) {
                $dom = new DomDocument;
-               $dom->loadXml( $svg );
+               $dom->loadXML( $svg );
                foreach ( $dom->getElementsByTagName( 'path' ) as $node ) {
                        $pathData = $node->getAttribute( 'd' );
                        // Make sure there is at least one space between numbers, and that leading zero is not omitted.
@@ -305,7 +305,7 @@ class ResourceLoaderImage {
                        $pathData = preg_replace( '/([ -])0(\d)/', '$1$2', $pathData );
                        $node->setAttribute( 'd', $pathData );
                }
-               return $dom->saveXml();
+               return $dom->saveXML();
        }
 
        /**
index d9005fa..beab53e 100644 (file)
@@ -31,7 +31,7 @@ class ResourceLoaderRawFileModule extends ResourceLoaderFileModule {
        /**
         * Enable raw mode to omit mw.loader.state() call as mw.loader
         * does not yet exist when these modules execute.
-        * @var boolean
+        * @var bool
         */
        protected $raw = true;
 
index 6a40e27..34866f3 100644 (file)
@@ -40,8 +40,17 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                }
 
                global $wgContLang;
+               $conf = $this->getConfig();
 
-               $mainPage = Title::newMainPage();
+               // We can't use Title::newMainPage() if 'mainpage' is in
+               // $wgForceUIMsgAsContentMsg because that will try to use the session
+               // user's language and we have no session user. This does the
+               // equivalent but falling back to our ResourceLoaderContext language
+               // instead.
+               $mainPage = Title::newFromText( $context->msg( 'mainpage' )->inContentLanguage()->text() );
+               if ( !$mainPage ) {
+                       $mainPage = Title::newFromText( 'Main Page' );
+               }
 
                /**
                 * Namespace related preparation
@@ -57,7 +66,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        }
                }
 
-               $conf = $this->getConfig();
                // Build list of variables
                $vars = [
                        'wgLoadScript' => wfScript( 'load' ),
@@ -279,15 +287,12 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
        }
 
        public static function getLegacyModules() {
-               global $wgIncludeLegacyJavaScript, $wgPreloadJavaScriptMwUtil;
+               global $wgIncludeLegacyJavaScript;
 
                $legacyModules = [];
                if ( $wgIncludeLegacyJavaScript ) {
                        $legacyModules[] = 'mediawiki.legacy.wikibits';
                }
-               if ( $wgPreloadJavaScriptMwUtil ) {
-                       $legacyModules[] = 'mediawiki.util';
-               }
 
                return $legacyModules;
        }
index bf4e8a7..cea1f39 100644 (file)
@@ -54,8 +54,7 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule {
        /**
         * Generate the JavaScript content of this module.
         *
-        * Add '@nomin' annotation to prevent the module's contents from getting
-        * cached (T84960).
+        * Add FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
         *
         * @param ResourceLoaderContext $context
         * @return string
index 7b0d93a..796dc20 100644 (file)
@@ -298,7 +298,8 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
 
                        if ( !$batch->isEmpty() ) {
                                $res = $dbr->select( [ 'page', 'revision' ],
-                                       [ 'page_namespace', 'page_title', 'rev_len', 'rev_sha1' ],
+                                       // Include page_touched to allow purging if cache is poisoned (T117587, T113916)
+                                       [ 'page_namespace', 'page_title', 'page_touched', 'rev_len', 'rev_sha1' ],
                                        $batch->constructSet( 'page', $dbr ),
                                        __METHOD__,
                                        [],
@@ -311,6 +312,7 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
                                        $this->titleInfo[$key][$title->getPrefixedText()] = [
                                                'rev_len' => $row->rev_len,
                                                'rev_sha1' => $row->rev_sha1,
+                                               'page_touched' => $row->page_touched,
                                        ];
                                }
                        }
index 65b0309..1ea7271 100644 (file)
@@ -55,11 +55,11 @@ class RevDelLogItem extends RevDelItem {
                $dbw = wfGetDB( DB_MASTER );
 
                $dbw->update( 'logging',
-                       array( 'log_deleted' => $bits ),
-                       array(
+                       [ 'log_deleted' => $bits ],
+                       [
                                'log_id' => $this->row->log_id,
                                'log_deleted' => $this->getBits() // cas
-                       ),
+                       ],
                        __METHOD__
                );
 
@@ -69,14 +69,14 @@ class RevDelLogItem extends RevDelItem {
                }
 
                $dbw->update( 'recentchanges',
-                       array(
+                       [
                                'rc_deleted' => $bits,
                                'rc_patrolled' => 1
-                       ),
-                       array(
+                       ],
+                       [
                                'rc_logid' => $this->row->log_id,
                                'rc_timestamp' => $this->row->log_timestamp // index
-                       ),
+                       ],
                        __METHOD__
                );
 
@@ -95,8 +95,8 @@ class RevDelLogItem extends RevDelItem {
                $loglink = Linker::link(
                        SpecialPage::getTitleFor( 'Log' ),
                        $this->list->msg( 'log' )->escaped(),
-                       array(),
-                       array( 'page' => $title->getPrefixedText() )
+                       [],
+                       [ 'page' => $title->getPrefixedText() ]
                );
                $loglink = $this->list->msg( 'parentheses' )->rawParams( $loglink )->escaped();
                // User links and action text
@@ -115,34 +115,34 @@ class RevDelLogItem extends RevDelItem {
        public function getApiData( ApiResult $result ) {
                $logEntry = DatabaseLogEntry::newFromRow( $this->row );
                $user = $this->list->getUser();
-               $ret = array(
+               $ret = [
                        'id' => $logEntry->getId(),
                        'type' => $logEntry->getType(),
                        'action' => $logEntry->getSubtype(),
-               );
+               ];
                $ret += $logEntry->isDeleted( LogPage::DELETED_USER )
-                       ? array( 'userhidden' => '' )
-                       : array();
+                       ? [ 'userhidden' => '' ]
+                       : [];
                $ret += $logEntry->isDeleted( LogPage::DELETED_COMMENT )
-                       ? array( 'commenthidden' => '' )
-                       : array();
+                       ? [ 'commenthidden' => '' ]
+                       : [];
                $ret += $logEntry->isDeleted( LogPage::DELETED_ACTION )
-                       ? array( 'actionhidden' => '' )
-                       : array();
+                       ? [ 'actionhidden' => '' ]
+                       : [];
 
                if ( LogEventsList::userCan( $this->row, LogPage::DELETED_ACTION, $user ) ) {
                        $ret['params'] = LogFormatter::newFromEntry( $logEntry )->formatParametersForApi();
                }
                if ( LogEventsList::userCan( $this->row, LogPage::DELETED_USER, $user ) ) {
-                       $ret += array(
+                       $ret += [
                                'userid' => $this->row->log_user,
                                'user' => $this->row->log_user_text,
-                       );
+                       ];
                }
                if ( LogEventsList::userCan( $this->row, LogPage::DELETED_COMMENT, $user ) ) {
-                       $ret += array(
+                       $ret += [
                                'comment' => $this->row->log_comment,
-                       );
+                       ];
                }
 
                return $ret;
index 1344f4c..b263fb3 100644 (file)
@@ -708,10 +708,6 @@ class SearchEngine {
         * @return SearchSuggestionSet
         */
        protected function processCompletionResults( $search, SearchSuggestionSet $suggestions ) {
-               if ( $suggestions->getSize() == 0 ) {
-                       // If we don't have anything, don't bother
-                       return $suggestions;
-               }
                $search = trim( $search );
                // preload the titles with LinkBatch
                $titles = $suggestions->map( function( SearchSuggestion $sugg ) {
@@ -726,6 +722,10 @@ class SearchEngine {
                } );
 
                // Rescore results with an exact title match
+               // NOTE: in some cases like cross-namespace redirects
+               // (frequently used as shortcuts e.g. WP:WP on huwiki) some
+               // backends like Cirrus will return no results. We should still
+               // try an exact title match to workaround this limitation
                $rescorer = new SearchExactMatchRescorer();
                $rescoredResults = $rescorer->rescore( $search, $this->namespaces, $results, $this->limit );
 
index d3b9d5c..40cfe39 100644 (file)
@@ -41,7 +41,7 @@ class SearchExactMatchRescorer {
         */
        public function rescore( $search, $namespaces, $srchres, $limit ) {
                // Pick namespace (based on PrefixSearch::defaultSearchBackend)
-               $ns = in_array( NS_MAIN, $namespaces ) ? NS_MAIN : $namespaces[0];
+               $ns = in_array( NS_MAIN, $namespaces ) ? NS_MAIN : reset( $namespaces );
                $t = Title::newFromText( $search, $ns );
                if ( !$t || !$t->exists() ) {
                        // No exact match so just return the search results
index cd9062b..80a437b 100644 (file)
@@ -84,7 +84,7 @@ class SearchSuggestion {
         */
        public function setText( $text, $setTitle = true ) {
                $this->text = $text;
-               if ( $setTitle && $text ) {
+               if ( $setTitle && $text !== '' && $text !== null ) {
                        $this->setSuggestedTitle( Title::makeTitle( 0, $text ) );
                }
        }
index bbdfdc3..5831b09 100644 (file)
@@ -147,7 +147,7 @@ class BotPasswordSessionProvider extends ImmutableSessionProviderWithCookie {
                }
 
                $status = $bp->getRestrictions()->check( $request );
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        $this->logger->info(
                                'Session "{session}": Restrictions check failed',
                                [
index 0fd8fa8..4188f4f 100644 (file)
@@ -335,7 +335,7 @@ final class Session implements \Countable, \Iterator, \ArrayAccess {
         *
         * @param string|string[] $salt Token salt
         * @param string $key Token key
-        * @return MediaWiki\\Session\\SessionToken
+        * @return Token
         */
        public function getToken( $salt = '', $key = 'default' ) {
                $new = false;
index 1e2b476..2626aa8 100644 (file)
@@ -31,7 +31,7 @@ use WebRequest;
 /**
  * This is the actual workhorse for Session.
  *
- * Most code does not need to use this class, you want \\MediaWiki\\Session\\Session.
+ * Most code does not need to use this class, you want \MediaWiki\Session\Session.
  * The exceptions are SessionProviders and SessionMetadata hook functions,
  * which get an instance of this class rather than Session.
  *
@@ -176,7 +176,7 @@ final class SessionBackend {
 
        /**
         * Deregister a Session
-        * @private For use by \\MediaWiki\\Session\\Session::__destruct() only
+        * @private For use by \MediaWiki\Session\Session::__destruct() only
         * @param int $index
         */
        public function deregisterSession( $index ) {
@@ -498,7 +498,7 @@ final class SessionBackend {
         * Note the caller is responsible for calling $this->dirty() if anything in
         * the array is changed.
         *
-        * @private For use by \\MediaWiki\\Session\\Session only.
+        * @private For use by \MediaWiki\Session\Session only.
         * @return array
         */
        public function &getData() {
@@ -530,7 +530,7 @@ final class SessionBackend {
 
        /**
         * Mark data as dirty
-        * @private For use by \\MediaWiki\\Session\\Session only.
+        * @private For use by \MediaWiki\Session\Session only.
         */
        public function dirty() {
                $this->dataDirty = true;
index 0669100..33ea046 100644 (file)
@@ -56,7 +56,7 @@ final class SessionId {
 
        /**
         * Set the ID
-        * @private For use by \\MediaWiki\\Session\\SessionManager only
+        * @private For use by \MediaWiki\Session\SessionManager only
         * @param string $id
         */
        public function setId( $id ) {
index 0a304a9..fc73335 100644 (file)
@@ -197,13 +197,17 @@ final class SessionManager implements SessionManagerInterface {
                }
 
                $session = null;
+               $info = new SessionInfo( SessionInfo::MIN_PRIORITY, [ 'id' => $id, 'idIsSafe' => true ] );
 
-               // Test this here to provide a better log message for the common case
-               // of "no such ID"
+               // If we already have the backend loaded, use it directly
+               if ( isset( $this->allSessionBackends[$id] ) ) {
+                       return $this->getSessionFromInfo( $info, $request );
+               }
+
+               // Test if the session is in storage, and if so try to load it.
                $key = wfMemcKey( 'MWSession', $id );
                if ( is_array( $this->store->get( $key ) ) ) {
-                       $create = false;
-                       $info = new SessionInfo( SessionInfo::MIN_PRIORITY, [ 'id' => $id, 'idIsSafe' => true ] );
+                       $create = false; // If loading fails, don't bother creating because it probably will fail too.
                        if ( $this->loadSessionInfoFromStore( $info, $request ) ) {
                                $session = $this->getSessionFromInfo( $info, $request );
                        }
@@ -548,7 +552,7 @@ final class SessionManager implements SessionManagerInterface {
         * The intention is that the named account will never again be usable for
         * normal login (i.e. there is no way to undo the prevention of access).
         *
-        * @private For use from \\User::newSystemUser only
+        * @private For use from \User::newSystemUser only
         * @param string $username
         */
        public function preventSessionsForUser( $username ) {
@@ -1022,7 +1026,7 @@ final class SessionManager implements SessionManagerInterface {
 
        /**
         * Deregister a SessionBackend
-        * @private For use from \\MediaWiki\\Session\\SessionBackend only
+        * @private For use from \MediaWiki\Session\SessionBackend only
         * @param SessionBackend $backend
         */
        public function deregisterSessionBackend( SessionBackend $backend ) {
@@ -1040,7 +1044,7 @@ final class SessionManager implements SessionManagerInterface {
 
        /**
         * Change a SessionBackend's ID
-        * @private For use from \\MediaWiki\\Session\\SessionBackend only
+        * @private For use from \MediaWiki\Session\SessionBackend only
         * @param SessionBackend $backend
         */
        public function changeBackendId( SessionBackend $backend ) {
index 14af630..b3e28fe 100644 (file)
@@ -43,7 +43,7 @@ interface SessionManagerInterface extends LoggerAwareInterface {
         * @param WebRequest $request Any existing associated session will be reset
         *  to the session corresponding to the data in the request itself.
         * @return Session
-        * @throws \\OverflowException if there are multiple sessions tied for top
+        * @throws \OverflowException if there are multiple sessions tied for top
         *  priority in the request. Exception has a property "sessionInfos"
         *  holding the SessionInfo objects for the sessions involved.
         */
index 1975ee8..8ee1272 100644 (file)
@@ -145,7 +145,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * @note The SessionProvider must not attempt to auto-create users.
         *  MediaWiki will do this later (when it's safe) if the chosen session has
         *  a user with a valid name but no ID.
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @param WebRequest $request
         * @return SessionInfo|null
         */
@@ -158,7 +158,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * implementation assumes that it only makes sense if a session ID can be
         * persisted and changing users is allowed.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @param string|null $id ID to force for the new session
         * @return SessionInfo|null
         *  If non-null, must return true for $info->isIdSafe(); pass true for
@@ -182,7 +182,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * The default implementation checks that anything in both arrays is
         * identical, then returns $providedMetadata.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @param array $savedMetadata Saved provider metadata
         * @param array $providedMetadata Provided provider metadata
         * @return array Resulting metadata
@@ -209,7 +209,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * allows for updating the provider metadata. On failure, the provider is
         * expected to write an appropriate message to its logger.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @param SessionInfo $info
         * @param WebRequest $request
         * @param array|null &$metadata Provider metadata, may be altered.
@@ -242,7 +242,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * the session ID into a cookie can easily just set the cookie to a
         * different value.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionBackend only
+        * @protected For use by \MediaWiki\Session\SessionBackend only
         * @return bool
         */
        abstract public function persistsSessionId();
@@ -269,7 +269,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * different user. A session provider that shoves information into cookies,
         * on the other hand, could easily do so.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionBackend only
+        * @protected For use by \MediaWiki\Session\SessionBackend only
         * @return bool
         */
        abstract public function canChangeUser();
@@ -279,7 +279,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         *
         * No need to persist here, persistSession() will be called if appropriate.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionBackend only
+        * @protected For use by \MediaWiki\Session\SessionBackend only
         * @param SessionBackend $session Session to persist
         * @param string $oldId Old session ID
         * @codeCoverageIgnore
@@ -310,7 +310,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * A backend that cannot persist sesison ID or user info should implement
         * this as a no-op.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionBackend only
+        * @protected For use by \MediaWiki\Session\SessionBackend only
         * @param SessionBackend $session Session to persist
         * @param WebRequest $request Request into which to persist the session
         */
@@ -324,7 +324,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * A backend that cannot persist sesison ID or user info should implement
         * this as a no-op.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @param WebRequest $request Request from which to remove any session data
         */
        abstract public function unpersistSession( WebRequest $request );
@@ -347,7 +347,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         * User::idFromName( $username ) === 0); the name should still be
         * prevented, if applicable.
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @param string $username
         */
        public function preventSessionsForUser( $username ) {
@@ -368,7 +368,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         *  }
         * @endcode
         *
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @return array
         */
        public function getVaryHeaders() {
@@ -377,7 +377,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
 
        /**
         * Return the list of cookies that need varying on.
-        * @protected For use by \\MediaWiki\\Session\\SessionManager only
+        * @protected For use by \MediaWiki\Session\SessionManager only
         * @return string[]
         */
        public function getVaryCookies() {
@@ -386,7 +386,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
 
        /**
         * Get a suggested username for the login form
-        * @protected For use by \\MediaWiki\\Session\\SessionBackend only
+        * @protected For use by \MediaWiki\Session\SessionBackend only
         * @param WebRequest $request
         * @return string|null
         */
@@ -424,7 +424,7 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI
         *
         * This default implementation takes the class name, lowercases it,
         * replaces backslashes with dashes, and prefixes 'sessionprovider-' to
-        * determine the message key. For example, MediaWiki\\Session\\CookieSessionProvider
+        * determine the message key. For example, MediaWiki\Session\CookieSessionProvider
         * produces 'sessionprovider-mediawiki-session-cookiesessionprovider'.
         *
         * @note If self::__toString() is overridden, this will likely need to be
index 756bb51..974789f 100644 (file)
@@ -26,6 +26,7 @@
  *
  * @license GNU GPL v2+
  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author Daniel Kinzler
  */
 class DBSiteStore implements SiteStore {
 
@@ -35,15 +36,20 @@ class DBSiteStore implements SiteStore {
        protected $sites = null;
 
        /**
-        * @since 1.25
-        * @param null $sitesTable Unused since 1.27
+        * @var LoadBalancer
         */
-       public function __construct( $sitesTable = null ) {
-               if ( $sitesTable !== null ) {
-                       throw new InvalidArgumentException(
-                               __METHOD__ . ': $sitesTable parameter must be null'
-                       );
-               }
+       private $dbLoadBalancer;
+
+       /**
+        * @since 1.27
+        *
+        * @todo: inject some kind of connection manager that is aware of the target wiki,
+        * instead of injecting a LoadBalancer.
+        *
+        * @param LoadBalancer $dbLoadBalancer
+        */
+       public function __construct( LoadBalancer $dbLoadBalancer ) {
+               $this->dbLoadBalancer = $dbLoadBalancer;
        }
 
        /**
@@ -67,7 +73,7 @@ class DBSiteStore implements SiteStore {
        protected function loadSites() {
                $this->sites = new SiteList();
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = $this->dbLoadBalancer->getConnection( DB_SLAVE );
 
                $res = $dbr->select(
                        'sites',
@@ -124,6 +130,8 @@ class DBSiteStore implements SiteStore {
                                $this->sites->setSite( $site );
                        }
                }
+
+               $this->dbLoadBalancer->reuseConnection( $dbr );
        }
 
        /**
@@ -170,7 +178,7 @@ class DBSiteStore implements SiteStore {
                        return true;
                }
 
-               $dbw = wfGetDB( DB_MASTER );
+               $dbw = $this->dbLoadBalancer->getConnection( DB_MASTER );
 
                $dbw->startAtomic( __METHOD__ );
 
@@ -241,6 +249,8 @@ class DBSiteStore implements SiteStore {
 
                $dbw->endAtomic( __METHOD__ );
 
+               $this->dbLoadBalancer->reuseConnection( $dbw );
+
                $this->reset();
 
                return $success;
@@ -263,13 +273,15 @@ class DBSiteStore implements SiteStore {
         * @return bool Success
         */
        public function clear() {
-               $dbw = wfGetDB( DB_MASTER );
+               $dbw = $this->dbLoadBalancer->getConnection( DB_MASTER );
 
                $dbw->startAtomic( __METHOD__ );
                $ok = $dbw->delete( 'sites', '*', __METHOD__ );
                $ok = $dbw->delete( 'site_identifiers', '*', __METHOD__ ) && $ok;
                $dbw->endAtomic( __METHOD__ );
 
+               $this->dbLoadBalancer->reuseConnection( $dbw );
+
                $this->reset();
 
                return $ok;
index 0d0e448..198d331 100644 (file)
@@ -50,7 +50,7 @@ class HashSiteStore implements SiteStore {
         *
         * @param Site $site
         *
-        * @return boolean Success indicator
+        * @return bool Success indicator
         */
        public function saveSite( Site $site ) {
                $this->sites[$site->getGlobalId()] = $site;
@@ -65,7 +65,7 @@ class HashSiteStore implements SiteStore {
         *
         * @param Site[] $sites
         *
-        * @return boolean Success indicator
+        * @return bool Success indicator
         */
        public function saveSites( array $sites ) {
                foreach ( $sites as $site ) {
index 0f7e5d7..6734d5f 100644 (file)
@@ -39,20 +39,6 @@ class MediaWikiSite extends Site {
        const PATH_FILE = 'file_path';
        const PATH_PAGE = 'page_path';
 
-       /**
-        * @since 1.21
-        * @deprecated since 1.21 Just use the constructor or the factory Site::newForType
-        *
-        * @param int $globalId
-        *
-        * @return MediaWikiSite
-        */
-       public static function newFromGlobalId( $globalId ) {
-               $site = new static();
-               $site->setGlobalId( $globalId );
-               return $site;
-       }
-
        /**
         * Constructor.
         *
index e61179b..a4116ae 100644 (file)
@@ -1,9 +1,7 @@
 <?php
 
 /**
- * Represents the site configuration of a wiki.
- * Holds a list of sites (ie SiteList) and takes care
- * of retrieving and caching site information when appropriate.
+ * Dummy class for accessing the global SiteStore instance.
  *
  * 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
  * @ingroup Site
  *
  * @license GNU GPL v2+
- * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author Daniel Kinzler
  */
-class SiteSQLStore extends CachingSiteStore {
+class SiteSQLStore {
 
        /**
+        * Returns the global SiteStore instance. This is a relict of the first implementation
+        * of SiteStore, and is kept around for compatibility.
+        *
+        * @note This does not return an instance of SiteSQLStore!
+        *
         * @since 1.21
-        * @deprecated 1.25 Construct a SiteStore instance directly instead.
+        * @deprecated 1.27 use MediaWikiServices::getSiteStore() or MediaWikiServices::getSiteLookup()
+        *             instead.
         *
-        * @param null $sitesTable Unused
-        * @param BagOStuff|null $cache
+        * @param null $sitesTable IGNORED
+        * @param null $cache IGNORED
         *
         * @return SiteStore
         */
@@ -46,13 +50,11 @@ class SiteSQLStore extends CachingSiteStore {
                        );
                }
 
-               if ( $cache === null ) {
-                       $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING );
-               }
-
-               $siteStore = new DBSiteStore();
+               // NOTE: we silently ignore $cache for now, since some existing callers
+               // specify it. If we break compatibility with them, we could just as
+               // well just remove this class.
 
-               return new static( $siteStore, $cache );
+               return \MediaWiki\MediaWikiServices::getInstance()->getSiteStore();
        }
 
 }
index b80788b..e5b9cb9 100644 (file)
@@ -81,15 +81,6 @@ abstract class Skin extends ContextSource {
                return $allowedSkins;
        }
 
-       /**
-        * @deprecated since 1.23, use getAllowedSkins
-        * @return string[]
-        */
-       public static function getUsableSkins() {
-               wfDeprecated( __METHOD__, '1.23' );
-               return self::getAllowedSkins();
-       }
-
        /**
         * Normalize a skin preference value to a form that can be loaded.
         *
@@ -140,23 +131,6 @@ abstract class Skin extends ContextSource {
                }
        }
 
-       /**
-        * Factory method for loading a skin of a given type
-        * @param string $key 'monobook', 'vector', etc.
-        * @return Skin
-        * @deprecated since 1.24; Use SkinFactory instead
-        */
-       static function &newFromKey( $key ) {
-               wfDeprecated( __METHOD__, '1.24' );
-
-               $key = Skin::normalizeKey( $key );
-               $factory = SkinFactory::getDefaultInstance();
-
-               // normalizeKey() guarantees that a skin with this key will exist.
-               $skin = $factory->makeSkin( $key );
-               return $skin;
-       }
-
        /**
         * @return string Skin name
         */
@@ -451,7 +425,7 @@ abstract class Skin extends ContextSource {
        }
 
        /**
-        * @return string
+        * @return string HTML
         */
        function getCategoryLinks() {
                global $wgUseCategoryBrowser;
@@ -542,25 +516,27 @@ abstract class Skin extends ContextSource {
        }
 
        /**
-        * @return string
+        * @return string HTML
         */
        function getCategories() {
                $out = $this->getOutput();
-
                $catlinks = $this->getCategoryLinks();
 
-               $classes = 'catlinks';
-
                // Check what we're showing
                $allCats = $out->getCategoryLinks();
                $showHidden = $this->getUser()->getBoolOption( 'showhiddencats' ) ||
                                                $this->getTitle()->getNamespace() == NS_CATEGORY;
 
+               $classes = [ 'catlinks' ];
                if ( empty( $allCats['normal'] ) && !( !empty( $allCats['hidden'] ) && $showHidden ) ) {
-                       $classes .= ' catlinks-allhidden';
+                       $classes[] = 'catlinks-allhidden';
                }
 
-               return "<div id='catlinks' class='$classes' data-mw='interface'>{$catlinks}</div>";
+               return Html::rawElement(
+                       'div',
+                       [ 'id' => 'catlinks', 'class' => $classes, 'data-mw' => 'interface' ],
+                       $catlinks
+               );
        }
 
        /**
@@ -799,12 +775,12 @@ abstract class Skin extends ContextSource {
         * @return null|string
         */
        function getCopyrightIcon() {
-               global $wgRightsUrl, $wgRightsText, $wgRightsIcon, $wgCopyrightIcon;
+               global $wgRightsUrl, $wgRightsText, $wgRightsIcon, $wgFooterIcons;
 
                $out = '';
 
-               if ( $wgCopyrightIcon ) {
-                       $out = $wgCopyrightIcon;
+               if ( $wgFooterIcons['copyright']['copyright'] ) {
+                       $out = $wgFooterIcons['copyright']['copyright'];
                } elseif ( $wgRightsIcon ) {
                        $icon = htmlspecialchars( $wgRightsIcon );
 
@@ -1022,21 +998,6 @@ abstract class Skin extends ContextSource {
                        $targetUser->canReceiveEmail();
        }
 
-       /**
-        * This function previously returned a fully resolved style path URL to images or styles stored in
-        * the legacy skins/common/ directory.
-        *
-        * That directory has been removed in 1.24 and the function always returns an empty string.
-        *
-        * @deprecated since 1.24
-        * @param string $name The name or path of a skin resource file
-        * @return string Empty string
-        */
-       function getCommonStylePath( $name ) {
-               wfDeprecated( __METHOD__, '1.24' );
-               return '';
-       }
-
        /**
         * Return a fully resolved style path url to images or styles stored in the current skins's folder.
         * This method returns a url resolved using the configured skin style path
@@ -1357,22 +1318,6 @@ abstract class Skin extends ContextSource {
                return $bar;
        }
 
-       /**
-        * This function previously controlled whether the 'mediawiki.legacy.wikiprintable' module
-        * should be loaded by OutputPage. That module no longer exists and the return value of this
-        * method is ignored.
-        *
-        * If your skin doesn't provide its own print styles, the 'mediawiki.legacy.commonPrint' module
-        * can be used instead (SkinTemplate-based skins do it automatically).
-        *
-        * @deprecated since 1.22
-        * @return bool
-        */
-       public function commonPrintStylesheet() {
-               wfDeprecated( __METHOD__, '1.22' );
-               return false;
-       }
-
        /**
         * Gets new talk page messages for the current user and returns an
         * appropriate alert message (or an empty string if there are no messages)
index 92311b5..e5dc59f 100644 (file)
@@ -45,6 +45,14 @@ class SkinTemplate extends Skin {
         */
        public $template = 'QuickTemplate';
 
+       public $thispage;
+       public $titletxt;
+       public $userpage;
+       public $thisquery;
+       public $loggedin;
+       public $username;
+       public $userpageUrlDetails;
+
        /**
         * Add specific styles for this skin
         *
@@ -252,6 +260,7 @@ class SkinTemplate extends Skin {
         * Wrap the body text with language information and identifiable element
         *
         * @param Title $title
+        * @param string $html body text
         * @return string html
         */
        protected function wrapHTML( $title, $html ) {
index 6a04c6a..fb153fc 100644 (file)
@@ -342,10 +342,10 @@ class SpecialPage {
                        return [];
                }
 
-               $search = SearchEngine::create();
-               $search->setLimitOffset( $limit, $offset );
-               $search->setNamespaces( [] );
-               $result = $search->defaultPrefixSearch( $search );
+               $searchEngine = SearchEngine::create();
+               $searchEngine->setLimitOffset( $limit, $offset );
+               $searchEngine->setNamespaces( [] );
+               $result = $searchEngine->defaultPrefixSearch( $search );
                return array_map( function( Title $t ) {
                        return $t->getPrefixedText();
                }, $result );
@@ -395,15 +395,20 @@ class SpecialPage {
        final public function run( $subPage ) {
                /**
                 * Gets called before @see SpecialPage::execute.
+                * Return false to prevent calling execute() (since 1.27+).
                 *
                 * @since 1.20
                 *
                 * @param SpecialPage $this
                 * @param string|null $subPage
                 */
-               Hooks::run( 'SpecialPageBeforeExecute', [ $this, $subPage ] );
+               if ( !Hooks::run( 'SpecialPageBeforeExecute', [ $this, $subPage ] ) ) {
+                       return;
+               }
 
-               $this->beforeExecute( $subPage );
+               if ( $this->beforeExecute( $subPage ) === false ) {
+                       return;
+               }
                $this->execute( $subPage );
                $this->afterExecute( $subPage );
 
@@ -420,10 +425,12 @@ class SpecialPage {
 
        /**
         * Gets called before @see SpecialPage::execute.
+        * Return false to prevent calling execute() (since 1.27+).
         *
         * @since 1.20
         *
         * @param string|null $subPage
+        * @return bool|void
         */
        protected function beforeExecute( $subPage ) {
                // No-op
index 8ce480e..725c4fc 100644 (file)
@@ -182,6 +182,7 @@ class SpecialPageFactory {
 
        private static $list;
        private static $aliases;
+       private static $pageObjectCache = [];
 
        /**
         * Reset the internal list of special pages. Useful when changing $wgSpecialPages after
@@ -190,6 +191,7 @@ class SpecialPageFactory {
        public static function resetList() {
                self::$list = null;
                self::$aliases = null;
+               self::$pageObjectCache = [];
        }
 
        /**
@@ -373,6 +375,10 @@ class SpecialPageFactory {
        public static function getPage( $name ) {
                list( $realName, /*...*/ ) = self::resolveAlias( $name );
 
+               if ( isset( self::$pageObjectCache[$realName] ) ) {
+                       return self::$pageObjectCache[$realName];
+               }
+
                $specialPageList = self::getPageList();
 
                if ( isset( $specialPageList[$realName] ) ) {
@@ -400,6 +406,7 @@ class SpecialPageFactory {
                                $page = null;
                        }
 
+                       self::$pageObjectCache[$realName] = $page;
                        if ( $page instanceof SpecialPage ) {
                                return $page;
                        } else {
index 9c5fc2f..d6d4500 100644 (file)
  * @ingroup SpecialPage
  */
 
-/**
- * This class is used to get a list of active users. The ones with specials
- * rights (sysop, bureaucrat, developer) will have them displayed
- * next to their names.
- *
- * @ingroup SpecialPage
- */
-class ActiveUsersPager extends UsersPager {
-       /**
-        * @var FormOptions
-        */
-       protected $opts;
-
-       /**
-        * @var array
-        */
-       protected $hideGroups = [];
-
-       /**
-        * @var array
-        */
-       protected $hideRights = [];
-
-       /**
-        * @var array
-        */
-       private $blockStatusByUid;
-
-       /**
-        * @param IContextSource $context
-        * @param null $group Unused
-        * @param string $par Parameter passed to the page
-        */
-       function __construct( IContextSource $context = null, $group = null, $par = null ) {
-               parent::__construct( $context );
-
-               $this->RCMaxAge = $this->getConfig()->get( 'ActiveUserDays' );
-               $un = $this->getRequest()->getText( 'username', $par );
-               $this->requestedUser = '';
-               if ( $un != '' ) {
-                       $username = Title::makeTitleSafe( NS_USER, $un );
-                       if ( !is_null( $username ) ) {
-                               $this->requestedUser = $username->getText();
-                       }
-               }
-
-               $this->setupOptions();
-       }
-
-       public function setupOptions() {
-               $this->opts = new FormOptions();
-
-               $this->opts->add( 'hidebots', false, FormOptions::BOOL );
-               $this->opts->add( 'hidesysops', false, FormOptions::BOOL );
-
-               $this->opts->fetchValuesFromRequest( $this->getRequest() );
-
-               if ( $this->opts->getValue( 'hidebots' ) == 1 ) {
-                       $this->hideRights[] = 'bot';
-               }
-               if ( $this->opts->getValue( 'hidesysops' ) == 1 ) {
-                       $this->hideGroups[] = 'sysop';
-               }
-       }
-
-       function getIndexField() {
-               return 'qcc_title';
-       }
-
-       function getQueryInfo() {
-               $dbr = $this->getDatabase();
-
-               $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
-               $timestamp = $dbr->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
-               $conds = [
-                       'qcc_type' => 'activeusers',
-                       'qcc_namespace' => NS_USER,
-                       'user_name = qcc_title',
-                       'rc_user_text = qcc_title',
-                       'rc_type != ' . $dbr->addQuotes( RC_EXTERNAL ), // Don't count wikidata.
-                       'rc_log_type IS NULL OR rc_log_type != ' . $dbr->addQuotes( 'newusers' ),
-                       'rc_timestamp >= ' . $dbr->addQuotes( $timestamp ),
-               ];
-               if ( $this->requestedUser != '' ) {
-                       $conds[] = 'qcc_title >= ' . $dbr->addQuotes( $this->requestedUser );
-               }
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
-                       $conds[] = 'NOT EXISTS (' . $dbr->selectSQLText(
-                               'ipblocks', '1', [ 'ipb_user=user_id', 'ipb_deleted' => 1 ]
-                       ) . ')';
-               }
-
-               if ( $dbr->implicitGroupby() ) {
-                       $options = [ 'GROUP BY' => [ 'qcc_title' ] ];
-               } else {
-                       $options = [ 'GROUP BY' => [ 'user_name', 'user_id', 'qcc_title' ] ];
-               }
-
-               return [
-                       'tables' => [ 'querycachetwo', 'user', 'recentchanges' ],
-                       'fields' => [ 'user_name', 'user_id', 'recentedits' => 'COUNT(*)', 'qcc_title' ],
-                       'options' => $options,
-                       'conds' => $conds
-               ];
-       }
-
-       function doBatchLookups() {
-               parent::doBatchLookups();
-
-               $uids = [];
-               foreach ( $this->mResult as $row ) {
-                       $uids[] = $row->user_id;
-               }
-               // Fetch the block status of the user for showing "(blocked)" text and for
-               // striking out names of suppressed users when privileged user views the list.
-               // Although the first query already hits the block table for un-privileged, this
-               // is done in two queries to avoid huge quicksorts and to make COUNT(*) correct.
-               $dbr = $this->getDatabase();
-               $res = $dbr->select( 'ipblocks',
-                       [ 'ipb_user', 'MAX(ipb_deleted) AS block_status' ],
-                       [ 'ipb_user' => $uids ],
-                       __METHOD__,
-                       [ 'GROUP BY' => [ 'ipb_user' ] ]
-               );
-               $this->blockStatusByUid = [];
-               foreach ( $res as $row ) {
-                       $this->blockStatusByUid[$row->ipb_user] = $row->block_status; // 0 or 1
-               }
-               $this->mResult->seek( 0 );
-       }
-
-       function formatRow( $row ) {
-               $userName = $row->user_name;
-
-               $ulinks = Linker::userLink( $row->user_id, $userName );
-               $ulinks .= Linker::userToolLinks( $row->user_id, $userName );
-
-               $lang = $this->getLanguage();
-
-               $list = [];
-               $user = User::newFromId( $row->user_id );
-
-               // User right filter
-               foreach ( $this->hideRights as $right ) {
-                       // Calling User::getRights() within the loop so that
-                       // if the hideRights() filter is empty, we don't have to
-                       // trigger the lazy-init of the big userrights array in the
-                       // User object
-                       if ( in_array( $right, $user->getRights() ) ) {
-                               return '';
-                       }
-               }
-
-               // User group filter
-               // Note: This is a different loop than for user rights,
-               // because we're reusing it to build the group links
-               // at the same time
-               $groups_list = self::getGroups( intval( $row->user_id ), $this->userGroupCache );
-               foreach ( $groups_list as $group ) {
-                       if ( in_array( $group, $this->hideGroups ) ) {
-                               return '';
-                       }
-                       $list[] = self::buildGroupLink( $group, $userName );
-               }
-
-               $groups = $lang->commaList( $list );
-
-               $item = $lang->specialList( $ulinks, $groups );
-
-               $isBlocked = isset( $this->blockStatusByUid[$row->user_id] );
-               if ( $isBlocked && $this->blockStatusByUid[$row->user_id] == 1 ) {
-                       $item = "<span class=\"deleted\">$item</span>";
-               }
-               $count = $this->msg( 'activeusers-count' )->numParams( $row->recentedits )
-                       ->params( $userName )->numParams( $this->RCMaxAge )->escaped();
-               $blocked = $isBlocked ? ' ' . $this->msg( 'listusers-blocked', $userName )->escaped() : '';
-
-               return Html::rawElement( 'li', [], "{$item} [{$count}]{$blocked}" );
-       }
-
-       function getPageHeader() {
-               $self = $this->getTitle();
-               $limit = $this->mLimit ? Html::hidden( 'limit', $this->mLimit ) : '';
-
-               # Form tag
-               $out = Xml::openElement( 'form', [ 'method' => 'get', 'action' => wfScript() ] );
-               $out .= Xml::fieldset( $this->msg( 'activeusers' )->text() ) . "\n";
-               $out .= Html::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n";
-
-               # Username field (with autocompletion support)
-               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
-               $out .= Xml::inputLabel(
-                       $this->msg( 'activeusers-from' )->text(),
-                       'username',
-                       'offset',
-                       20,
-                       $this->requestedUser,
-                       [
-                               'class' => 'mw-ui-input-inline mw-autocomplete-user',
-                               'tabindex' => 1,
-                       ] + (
-                               // Set autofocus on blank input
-                               $this->requestedUser === '' ? [ 'autofocus' => '' ] : []
-                       )
-               ) . '<br />';
-
-               $out .= Xml::checkLabel( $this->msg( 'activeusers-hidebots' )->text(),
-                       'hidebots', 'hidebots', $this->opts->getValue( 'hidebots' ), [ 'tabindex' => 2 ] );
-
-               $out .= Xml::checkLabel(
-                       $this->msg( 'activeusers-hidesysops' )->text(),
-                       'hidesysops',
-                       'hidesysops',
-                       $this->opts->getValue( 'hidesysops' ),
-                       [ 'tabindex' => 3 ]
-               ) . '<br />';
-
-               # Submit button and form bottom
-               $out .= Xml::submitButton(
-                       $this->msg( 'activeusers-submit' )->text(),
-                       [ 'tabindex' => 4 ]
-               ) . "\n";
-               $out .= Xml::closeElement( 'fieldset' );
-               $out .= Xml::closeElement( 'form' );
-
-               return $out;
-       }
-}
-
 /**
  * @ingroup SpecialPage
  */
index 49d5d6e..49ca9f4 100644 (file)
@@ -77,403 +77,3 @@ class SpecialAllMessages extends SpecialPage {
                return 'wiki';
        }
 }
-
-/**
- * Use TablePager for prettified output. We have to pretend that we're
- * getting data from a table when in fact not all of it comes from the database.
- */
-class AllMessagesTablePager extends TablePager {
-       protected $filter, $prefix, $langcode, $displayPrefix;
-
-       public $mLimitsShown;
-
-       /**
-        * @var Language
-        */
-       public $lang;
-
-       /**
-        * @var null|bool
-        */
-       public $custom;
-
-       function __construct( $page, $conds, $langObj = null ) {
-               parent::__construct( $page->getContext() );
-               $this->mIndexField = 'am_title';
-               $this->mPage = $page;
-               $this->mConds = $conds;
-               // FIXME: Why does this need to be set to DIR_DESCENDING to produce ascending ordering?
-               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
-               $this->mLimitsShown = [ 20, 50, 100, 250, 500, 5000 ];
-
-               global $wgContLang;
-
-               $this->talk = $this->msg( 'talkpagelinktext' )->escaped();
-
-               $this->lang = ( $langObj ? $langObj : $wgContLang );
-               $this->langcode = $this->lang->getCode();
-               $this->foreign = $this->langcode !== $wgContLang->getCode();
-
-               $request = $this->getRequest();
-
-               $this->filter = $request->getVal( 'filter', 'all' );
-               if ( $this->filter === 'all' ) {
-                       $this->custom = null; // So won't match in either case
-               } else {
-                       $this->custom = ( $this->filter === 'unmodified' );
-               }
-
-               $prefix = $this->getLanguage()->ucfirst( $request->getVal( 'prefix', '' ) );
-               $prefix = $prefix !== '' ?
-                       Title::makeTitleSafe( NS_MEDIAWIKI, $request->getVal( 'prefix', null ) ) :
-                       null;
-
-               if ( $prefix !== null ) {
-                       $this->displayPrefix = $prefix->getDBkey();
-                       $this->prefix = '/^' . preg_quote( $this->displayPrefix, '/' ) . '/i';
-               } else {
-                       $this->displayPrefix = false;
-                       $this->prefix = false;
-               }
-
-               // The suffix that may be needed for message names if we're in a
-               // different language (eg [[MediaWiki:Foo/fr]]: $suffix = '/fr'
-               if ( $this->foreign ) {
-                       $this->suffix = '/' . $this->langcode;
-               } else {
-                       $this->suffix = '';
-               }
-       }
-
-       function buildForm() {
-               $attrs = [ 'id' => 'mw-allmessages-form-lang', 'name' => 'lang' ];
-               $msg = wfMessage( 'allmessages-language' );
-               $langSelect = Xml::languageSelector( $this->langcode, false, null, $attrs, $msg );
-
-               $out = Xml::openElement( 'form', [
-                               'method' => 'get',
-                               'action' => $this->getConfig()->get( 'Script' ),
-                               'id' => 'mw-allmessages-form'
-                       ] ) .
-                       Xml::fieldset( $this->msg( 'allmessages-filter-legend' )->text() ) .
-                       Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
-                       Xml::openElement( 'table', [ 'class' => 'mw-allmessages-table' ] ) . "\n" .
-                       '<tr>
-                               <td class="mw-label">' .
-                       Xml::label( $this->msg( 'allmessages-prefix' )->text(), 'mw-allmessages-form-prefix' ) .
-                       "</td>\n
-                       <td class=\"mw-input\">" .
-                       Xml::input(
-                               'prefix',
-                               20,
-                               str_replace( '_', ' ', $this->displayPrefix ),
-                               [ 'id' => 'mw-allmessages-form-prefix' ]
-                       ) .
-                       "</td>\n
-                       </tr>
-                       <tr>\n
-                       <td class='mw-label'>" .
-                       $this->msg( 'allmessages-filter' )->escaped() .
-                       "</td>\n
-                               <td class='mw-input'>" .
-                       Xml::radioLabel( $this->msg( 'allmessages-filter-unmodified' )->text(),
-                               'filter',
-                               'unmodified',
-                               'mw-allmessages-form-filter-unmodified',
-                               ( $this->filter === 'unmodified' )
-                       ) .
-                       Xml::radioLabel( $this->msg( 'allmessages-filter-all' )->text(),
-                               'filter',
-                               'all',
-                               'mw-allmessages-form-filter-all',
-                               ( $this->filter === 'all' )
-                       ) .
-                       Xml::radioLabel( $this->msg( 'allmessages-filter-modified' )->text(),
-                               'filter',
-                               'modified',
-                               'mw-allmessages-form-filter-modified',
-                               ( $this->filter === 'modified' )
-                       ) .
-                       "</td>\n
-                       </tr>
-                       <tr>\n
-                               <td class=\"mw-label\">" . $langSelect[0] . "</td>\n
-                               <td class=\"mw-input\">" . $langSelect[1] . "</td>\n
-                       </tr>" .
-
-                       '<tr>
-                               <td class="mw-label">' .
-                       Xml::label( $this->msg( 'table_pager_limit_label' )->text(), 'mw-table_pager_limit_label' ) .
-                       '</td>
-                       <td class="mw-input">' .
-                       $this->getLimitSelect( [ 'id' => 'mw-table_pager_limit_label' ] ) .
-                       '</td>
-                       <tr>
-                               <td></td>
-                               <td>' .
-                       Xml::submitButton( $this->msg( 'allmessages-filter-submit' )->text() ) .
-                       "</td>\n
-                       </tr>" .
-
-                       Xml::closeElement( 'table' ) .
-                       $this->getHiddenFields( [ 'title', 'prefix', 'filter', 'lang', 'limit' ] ) .
-                       Xml::closeElement( 'fieldset' ) .
-                       Xml::closeElement( 'form' );
-
-               return $out;
-       }
-
-       function getAllMessages( $descending ) {
-               $messageNames = Language::getLocalisationCache()->getSubitemList( 'en', 'messages' );
-
-               // Normalise message names so they look like page titles and sort correctly - T86139
-               $messageNames = array_map( [ $this->lang, 'ucfirst' ], $messageNames );
-
-               if ( $descending ) {
-                       rsort( $messageNames );
-               } else {
-                       asort( $messageNames );
-               }
-
-               return $messageNames;
-       }
-
-       /**
-        * Determine which of the MediaWiki and MediaWiki_talk namespace pages exist.
-        * Returns array( 'pages' => ..., 'talks' => ... ), where the subarrays have
-        * an entry for each existing page, with the key being the message name and
-        * value arbitrary.
-        *
-        * @param array $messageNames
-        * @param string $langcode What language code
-        * @param bool $foreign Whether the $langcode is not the content language
-        * @return array A 'pages' and 'talks' array with the keys of existing pages
-        */
-       public static function getCustomisedStatuses( $messageNames, $langcode = 'en', $foreign = false ) {
-               // FIXME: This function should be moved to Language:: or something.
-
-               $dbr = wfGetDB( DB_SLAVE );
-               $res = $dbr->select( 'page',
-                       [ 'page_namespace', 'page_title' ],
-                       [ 'page_namespace' => [ NS_MEDIAWIKI, NS_MEDIAWIKI_TALK ] ],
-                       __METHOD__,
-                       [ 'USE INDEX' => 'name_title' ]
-               );
-               $xNames = array_flip( $messageNames );
-
-               $pageFlags = $talkFlags = [];
-
-               foreach ( $res as $s ) {
-                       $exists = false;
-
-                       if ( $foreign ) {
-                               $titleParts = explode( '/', $s->page_title );
-                               if ( count( $titleParts ) === 2 &&
-                                       $langcode === $titleParts[1] &&
-                                       isset( $xNames[$titleParts[0]] )
-                               ) {
-                                       $exists = $titleParts[0];
-                               }
-                       } elseif ( isset( $xNames[$s->page_title] ) ) {
-                               $exists = $s->page_title;
-                       }
-
-                       $title = Title::newFromRow( $s );
-                       if ( $exists && $title->inNamespace( NS_MEDIAWIKI ) ) {
-                               $pageFlags[$exists] = true;
-                       } elseif ( $exists && $title->inNamespace( NS_MEDIAWIKI_TALK ) ) {
-                               $talkFlags[$exists] = true;
-                       }
-               }
-
-               return [ 'pages' => $pageFlags, 'talks' => $talkFlags ];
-       }
-
-       /**
-        *  This function normally does a database query to get the results; we need
-        * to make a pretend result using a FakeResultWrapper.
-        * @param string $offset
-        * @param int $limit
-        * @param bool $descending
-        * @return FakeResultWrapper
-        */
-       function reallyDoQuery( $offset, $limit, $descending ) {
-               $result = new FakeResultWrapper( [] );
-
-               $messageNames = $this->getAllMessages( $descending );
-               $statuses = self::getCustomisedStatuses( $messageNames, $this->langcode, $this->foreign );
-
-               $count = 0;
-               foreach ( $messageNames as $key ) {
-                       $customised = isset( $statuses['pages'][$key] );
-                       if ( $customised !== $this->custom &&
-                               ( $descending && ( $key < $offset || !$offset ) || !$descending && $key > $offset ) &&
-                               ( ( $this->prefix && preg_match( $this->prefix, $key ) ) || $this->prefix === false )
-                       ) {
-                               $actual = wfMessage( $key )->inLanguage( $this->langcode )->plain();
-                               $default = wfMessage( $key )->inLanguage( $this->langcode )->useDatabase( false )->plain();
-                               $result->result[] = [
-                                       'am_title' => $key,
-                                       'am_actual' => $actual,
-                                       'am_default' => $default,
-                                       'am_customised' => $customised,
-                                       'am_talk_exists' => isset( $statuses['talks'][$key] )
-                               ];
-                               $count++;
-                       }
-
-                       if ( $count === $limit ) {
-                               break;
-                       }
-               }
-
-               return $result;
-       }
-
-       function getStartBody() {
-               $tableClass = $this->getTableClass();
-               return Xml::openElement( 'table', [
-                               'class' => "mw-datatable $tableClass",
-                               'id' => 'mw-allmessagestable'
-                       ] ) .
-                       "\n" .
-                       "<thead><tr>
-                               <th rowspan=\"2\">" .
-                       $this->msg( 'allmessagesname' )->escaped() . "
-                               </th>
-                               <th>" .
-                       $this->msg( 'allmessagesdefault' )->escaped() .
-                       "</th>
-                       </tr>\n
-                       <tr>
-                               <th>" .
-                       $this->msg( 'allmessagescurrent' )->escaped() .
-                       "</th>
-                       </tr></thead><tbody>\n";
-       }
-
-       function formatValue( $field, $value ) {
-               switch ( $field ) {
-                       case 'am_title' :
-                               $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
-                               $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
-                               $translation = Linker::makeExternalLink(
-                                       'https://translatewiki.net/w/i.php?' . wfArrayToCgi( [
-                                               'title' => 'Special:SearchTranslations',
-                                               'group' => 'mediawiki',
-                                               'grouppath' => 'mediawiki',
-                                               'query' => 'language:' . $this->getLanguage()->getCode() . '^25 ' .
-                                                       'messageid:"MediaWiki:' . $value . '"^10 "' .
-                                                       $this->msg( $value )->inLanguage( 'en' )->plain() . '"'
-                                       ] ),
-                                       $this->msg( 'allmessages-filter-translate' )->text()
-                               );
-
-                               if ( $this->mCurrentRow->am_customised ) {
-                                       $title = Linker::linkKnown( $title, $this->getLanguage()->lcfirst( $value ) );
-                               } else {
-                                       $title = Linker::link(
-                                               $title,
-                                               $this->getLanguage()->lcfirst( $value ),
-                                               [],
-                                               [],
-                                               [ 'broken' ]
-                                       );
-                               }
-                               if ( $this->mCurrentRow->am_talk_exists ) {
-                                       $talk = Linker::linkKnown( $talk, $this->talk );
-                               } else {
-                                       $talk = Linker::link(
-                                               $talk,
-                                               $this->talk,
-                                               [],
-                                               [],
-                                               [ 'broken' ]
-                                       );
-                               }
-
-                               return $title . ' ' .
-                                       $this->msg( 'parentheses' )->rawParams( $talk )->escaped() .
-                                       ' ' .
-                                       $this->msg( 'parentheses' )->rawParams( $translation )->escaped();
-
-                       case 'am_default' :
-                       case 'am_actual' :
-                               return Sanitizer::escapeHtmlAllowEntities( $value );
-               }
-
-               return '';
-       }
-
-       function formatRow( $row ) {
-               // Do all the normal stuff
-               $s = parent::formatRow( $row );
-
-               // But if there's a customised message, add that too.
-               if ( $row->am_customised ) {
-                       $s .= Xml::openElement( 'tr', $this->getRowAttrs( $row, true ) );
-                       $formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) );
-
-                       if ( $formatted === '' ) {
-                               $formatted = '&#160;';
-                       }
-
-                       $s .= Xml::tags( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted )
-                               . "</tr>\n";
-               }
-
-               return $s;
-       }
-
-       function getRowAttrs( $row, $isSecond = false ) {
-               $arr = [];
-
-               if ( $row->am_customised ) {
-                       $arr['class'] = 'allmessages-customised';
-               }
-
-               if ( !$isSecond ) {
-                       $arr['id'] = Sanitizer::escapeId( 'msg_' . $this->getLanguage()->lcfirst( $row->am_title ) );
-               }
-
-               return $arr;
-       }
-
-       function getCellAttrs( $field, $value ) {
-               if ( $this->mCurrentRow->am_customised && $field === 'am_title' ) {
-                       return [ 'rowspan' => '2', 'class' => $field ];
-               } elseif ( $field === 'am_title' ) {
-                       return [ 'class' => $field ];
-               } else {
-                       return [
-                               'lang' => $this->lang->getHtmlCode(),
-                               'dir' => $this->lang->getDir(),
-                               'class' => $field
-                       ];
-               }
-       }
-
-       // This is not actually used, as getStartBody is overridden above
-       function getFieldNames() {
-               return [
-                       'am_title' => $this->msg( 'allmessagesname' )->text(),
-                       'am_default' => $this->msg( 'allmessagesdefault' )->text()
-               ];
-       }
-
-       function getTitle() {
-               return SpecialPage::getTitleFor( 'Allmessages', false );
-       }
-
-       function isFieldSortable( $x ) {
-               return false;
-       }
-
-       function getDefaultSort() {
-               return '';
-       }
-
-       function getQueryInfo() {
-               return '';
-       }
-}
index e589ecb..dbbee71 100644 (file)
@@ -222,244 +222,3 @@ class SpecialBlockList extends SpecialPage {
                return 'users';
        }
 }
-
-class BlockListPager extends TablePager {
-       protected $conds;
-       protected $page;
-
-       /**
-        * @param SpecialPage $page
-        * @param array $conds
-        */
-       function __construct( $page, $conds ) {
-               $this->page = $page;
-               $this->conds = $conds;
-               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
-               parent::__construct( $page->getContext() );
-       }
-
-       function getFieldNames() {
-               static $headers = null;
-
-               if ( $headers === null ) {
-                       $headers = [
-                               'ipb_timestamp' => 'blocklist-timestamp',
-                               'ipb_target' => 'blocklist-target',
-                               'ipb_expiry' => 'blocklist-expiry',
-                               'ipb_by' => 'blocklist-by',
-                               'ipb_params' => 'blocklist-params',
-                               'ipb_reason' => 'blocklist-reason',
-                       ];
-                       foreach ( $headers as $key => $val ) {
-                               $headers[$key] = $this->msg( $val )->text();
-                       }
-               }
-
-               return $headers;
-       }
-
-       function formatValue( $name, $value ) {
-               static $msg = null;
-               if ( $msg === null ) {
-                       $keys = [
-                               'anononlyblock',
-                               'createaccountblock',
-                               'noautoblockblock',
-                               'emailblock',
-                               'blocklist-nousertalk',
-                               'unblocklink',
-                               'change-blocklink',
-                       ];
-
-                       foreach ( $keys as $key ) {
-                               $msg[$key] = $this->msg( $key )->escaped();
-                       }
-               }
-
-               /** @var $row object */
-               $row = $this->mCurrentRow;
-
-               $language = $this->getLanguage();
-
-               $formatted = '';
-
-               switch ( $name ) {
-                       case 'ipb_timestamp':
-                               $formatted = htmlspecialchars( $language->userTimeAndDate( $value, $this->getUser() ) );
-                               break;
-
-                       case 'ipb_target':
-                               if ( $row->ipb_auto ) {
-                                       $formatted = $this->msg( 'autoblockid', $row->ipb_id )->parse();
-                               } else {
-                                       list( $target, $type ) = Block::parseTarget( $row->ipb_address );
-                                       switch ( $type ) {
-                                               case Block::TYPE_USER:
-                                               case Block::TYPE_IP:
-                                                       $formatted = Linker::userLink( $target->getId(), $target );
-                                                       $formatted .= Linker::userToolLinks(
-                                                               $target->getId(),
-                                                               $target,
-                                                               false,
-                                                               Linker::TOOL_LINKS_NOBLOCK
-                                                       );
-                                                       break;
-                                               case Block::TYPE_RANGE:
-                                                       $formatted = htmlspecialchars( $target );
-                                       }
-                               }
-                               break;
-
-                       case 'ipb_expiry':
-                               $formatted = htmlspecialchars( $language->formatExpiry(
-                                       $value,
-                                       /* User preference timezone */true
-                               ) );
-                               if ( $this->getUser()->isAllowed( 'block' ) ) {
-                                       if ( $row->ipb_auto ) {
-                                               $links[] = Linker::linkKnown(
-                                                       SpecialPage::getTitleFor( 'Unblock' ),
-                                                       $msg['unblocklink'],
-                                                       [],
-                                                       [ 'wpTarget' => "#{$row->ipb_id}" ]
-                                               );
-                                       } else {
-                                               $links[] = Linker::linkKnown(
-                                                       SpecialPage::getTitleFor( 'Unblock', $row->ipb_address ),
-                                                       $msg['unblocklink']
-                                               );
-                                               $links[] = Linker::linkKnown(
-                                                       SpecialPage::getTitleFor( 'Block', $row->ipb_address ),
-                                                       $msg['change-blocklink']
-                                               );
-                                       }
-                                       $formatted .= ' ' . Html::rawElement(
-                                               'span',
-                                               [ 'class' => 'mw-blocklist-actions' ],
-                                               $this->msg( 'parentheses' )->rawParams(
-                                                       $language->pipeList( $links ) )->escaped()
-                                       );
-                               }
-                               break;
-
-                       case 'ipb_by':
-                               if ( isset( $row->by_user_name ) ) {
-                                       $formatted = Linker::userLink( $value, $row->by_user_name );
-                                       $formatted .= Linker::userToolLinks( $value, $row->by_user_name );
-                               } else {
-                                       $formatted = htmlspecialchars( $row->ipb_by_text ); // foreign user?
-                               }
-                               break;
-
-                       case 'ipb_reason':
-                               $formatted = Linker::formatComment( $value );
-                               break;
-
-                       case 'ipb_params':
-                               $properties = [];
-                               if ( $row->ipb_anon_only ) {
-                                       $properties[] = $msg['anononlyblock'];
-                               }
-                               if ( $row->ipb_create_account ) {
-                                       $properties[] = $msg['createaccountblock'];
-                               }
-                               if ( $row->ipb_user && !$row->ipb_enable_autoblock ) {
-                                       $properties[] = $msg['noautoblockblock'];
-                               }
-
-                               if ( $row->ipb_block_email ) {
-                                       $properties[] = $msg['emailblock'];
-                               }
-
-                               if ( !$row->ipb_allow_usertalk ) {
-                                       $properties[] = $msg['blocklist-nousertalk'];
-                               }
-
-                               $formatted = $language->commaList( $properties );
-                               break;
-
-                       default:
-                               $formatted = "Unable to format $name";
-                               break;
-               }
-
-               return $formatted;
-       }
-
-       function getQueryInfo() {
-               $info = [
-                       'tables' => [ 'ipblocks', 'user' ],
-                       'fields' => [
-                               'ipb_id',
-                               'ipb_address',
-                               'ipb_user',
-                               'ipb_by',
-                               'ipb_by_text',
-                               'by_user_name' => 'user_name',
-                               'ipb_reason',
-                               'ipb_timestamp',
-                               'ipb_auto',
-                               'ipb_anon_only',
-                               'ipb_create_account',
-                               'ipb_enable_autoblock',
-                               'ipb_expiry',
-                               'ipb_range_start',
-                               'ipb_range_end',
-                               'ipb_deleted',
-                               'ipb_block_email',
-                               'ipb_allow_usertalk',
-                       ],
-                       'conds' => $this->conds,
-                       'join_conds' => [ 'user' => [ 'LEFT JOIN', 'user_id = ipb_by' ] ]
-               ];
-
-               # Filter out any expired blocks
-               $db = $this->getDatabase();
-               $info['conds'][] = 'ipb_expiry > ' . $db->addQuotes( $db->timestamp() );
-
-               # Is the user allowed to see hidden blocks?
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
-                       $info['conds']['ipb_deleted'] = 0;
-               }
-
-               return $info;
-       }
-
-       public function getTableClass() {
-               return parent::getTableClass() . ' mw-blocklist';
-       }
-
-       function getIndexField() {
-               return 'ipb_timestamp';
-       }
-
-       function getDefaultSort() {
-               return 'ipb_timestamp';
-       }
-
-       function isFieldSortable( $name ) {
-               return false;
-       }
-
-       /**
-        * Do a LinkBatch query to minimise database load when generating all these links
-        * @param ResultWrapper $result
-        */
-       function preprocessResults( $result ) {
-               # Do a link batch query
-               $lb = new LinkBatch;
-               $lb->setCaller( __METHOD__ );
-
-               foreach ( $result as $row ) {
-                       $lb->add( NS_USER, $row->ipb_address );
-                       $lb->add( NS_USER_TALK, $row->ipb_address );
-
-                       if ( isset( $row->by_user_name ) ) {
-                               $lb->add( NS_USER, $row->by_user_name );
-                               $lb->add( NS_USER_TALK, $row->by_user_name );
-                       }
-               }
-
-               $lb->execute();
-       }
-}
index 11357fb..1027f1f 100644 (file)
@@ -84,9 +84,6 @@ class SpecialBotPasswords extends FormSpecialPage {
        }
 
        protected function getFormFields() {
-               $user = $this->getUser();
-               $request = $this->getRequest();
-
                $fields = [];
 
                if ( $this->par !== null ) {
@@ -192,6 +189,7 @@ class SpecialBotPasswords extends FormSpecialPage {
                                'type' => 'textwithbutton',
                                'label-message' => 'botpasswords-label-appid',
                                'buttondefault' => $this->msg( 'botpasswords-label-create' )->text(),
+                               'buttonflags' => [ 'progressive', 'primary' ],
                                'required' => true,
                                'size' => BotPassword::APPID_MAXLENGTH,
                                'maxlength' => BotPassword::APPID_MAXLENGTH,
@@ -315,20 +313,21 @@ class SpecialBotPasswords extends FormSpecialPage {
        public function onSuccess() {
                $out = $this->getOutput();
 
+               $username = $this->getUser()->getName();
                switch ( $this->operation ) {
                        case 'insert':
                                $out->setPageTitle( $this->msg( 'botpasswords-created-title' )->text() );
-                               $out->addWikiMsg( 'botpasswords-created-body', $this->par );
+                               $out->addWikiMsg( 'botpasswords-created-body', $this->par, $username );
                                break;
 
                        case 'update':
                                $out->setPageTitle( $this->msg( 'botpasswords-updated-title' )->text() );
-                               $out->addWikiMsg( 'botpasswords-updated-body', $this->par );
+                               $out->addWikiMsg( 'botpasswords-updated-body', $this->par, $username );
                                break;
 
                        case 'delete':
                                $out->setPageTitle( $this->msg( 'botpasswords-deleted-title' )->text() );
-                               $out->addWikiMsg( 'botpasswords-deleted-body', $this->par );
+                               $out->addWikiMsg( 'botpasswords-deleted-body', $this->par, $username );
                                $this->password = null;
                                break;
                }
@@ -337,7 +336,7 @@ class SpecialBotPasswords extends FormSpecialPage {
                        $sep = BotPassword::getSeparator();
                        $out->addWikiMsg(
                                'botpasswords-newpassword',
-                               htmlspecialchars( $this->getUser()->getName() . $sep . $this->par ),
+                               htmlspecialchars( $username . $sep . $this->par ),
                                htmlspecialchars( $this->password )
                        );
                        $this->password = null;
index 5314f63..d7d338c 100644 (file)
@@ -92,109 +92,3 @@ class SpecialCategories extends SpecialPage {
                return 'pages';
        }
 }
-
-/**
- * TODO: Allow sorting by count.  We need to have a unique index to do this
- * properly.
- *
- * @ingroup SpecialPage Pager
- */
-class CategoryPager extends AlphabeticPager {
-
-       /**
-        * @var PageLinkRenderer
-        */
-       protected $linkRenderer;
-
-       /**
-        * @param IContextSource $context
-        * @param string $from
-        * @param PageLinkRenderer $linkRenderer
-        */
-       public function __construct( IContextSource $context, $from, PageLinkRenderer $linkRenderer
-       ) {
-               parent::__construct( $context );
-               $from = str_replace( ' ', '_', $from );
-               if ( $from !== '' ) {
-                       $from = Title::capitalize( $from, NS_CATEGORY );
-                       $this->setOffset( $from );
-                       $this->setIncludeOffset( true );
-               }
-
-               $this->linkRenderer = $linkRenderer;
-       }
-
-       function getQueryInfo() {
-               return [
-                       'tables' => [ 'category' ],
-                       'fields' => [ 'cat_title', 'cat_pages' ],
-                       'conds' => [ 'cat_pages > 0' ],
-                       'options' => [ 'USE INDEX' => 'cat_title' ],
-               ];
-       }
-
-       function getIndexField() {
-#              return array( 'abc' => 'cat_title', 'count' => 'cat_pages' );
-               return 'cat_title';
-       }
-
-       function getDefaultQuery() {
-               parent::getDefaultQuery();
-               unset( $this->mDefaultQuery['from'] );
-
-               return $this->mDefaultQuery;
-       }
-
-#      protected function getOrderTypeMessages() {
-#              return array( 'abc' => 'special-categories-sort-abc',
-#                      'count' => 'special-categories-sort-count' );
-#      }
-
-       protected function getDefaultDirections() {
-#              return array( 'abc' => false, 'count' => true );
-               return false;
-       }
-
-       /* Override getBody to apply LinksBatch on resultset before actually outputting anything. */
-       public function getBody() {
-               $batch = new LinkBatch;
-
-               $this->mResult->rewind();
-
-               foreach ( $this->mResult as $row ) {
-                       $batch->addObj( Title::makeTitleSafe( NS_CATEGORY, $row->cat_title ) );
-               }
-               $batch->execute();
-               $this->mResult->rewind();
-
-               return parent::getBody();
-       }
-
-       function formatRow( $result ) {
-               $title = new TitleValue( NS_CATEGORY, $result->cat_title );
-               $text = $title->getText();
-               $link = $this->linkRenderer->renderHtmlLink( $title, $text );
-
-               $count = $this->msg( 'nmembers' )->numParams( $result->cat_pages )->escaped();
-               return Html::rawElement( 'li', null, $this->getLanguage()->specialList( $link, $count ) ) . "\n";
-       }
-
-       public function getStartForm( $from ) {
-               return Xml::tags(
-                       'form',
-                       [ 'method' => 'get', 'action' => wfScript() ],
-                       Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
-                               Xml::fieldset(
-                                       $this->msg( 'categories' )->text(),
-                                       Xml::inputLabel(
-                                               $this->msg( 'categoriesfrom' )->text(),
-                                               'from', 'from', 20, $from, [ 'class' => 'mw-ui-input-inline' ] ) .
-                                               ' ' .
-                                               Html::submitButton(
-                                                       $this->msg( 'categories-submit' )->text(),
-                                                       [], [ 'mw-ui-progressive' ]
-                                               )
-                               )
-               );
-       }
-}
index 57c6fec..ee9f665 100644 (file)
@@ -43,6 +43,9 @@ class SpecialChangeContentModel extends FormSpecialPage {
                }
 
                $this->addHelpLink( 'Help:ChangeContentModel' );
+
+               // T120576
+               $form->setSubmitTextMsg( 'changecontentmodel-submit' );
        }
 
        public function validateTitle( $title ) {
index 2d0d020..5adc315 100644 (file)
@@ -332,7 +332,7 @@ class SpecialChangePassword extends FormSpecialPage {
                $dbw->update(
                        'user',
                        [ 'user_password_expires' => $dbw->timestampOrNull( $newExpire ) ],
-                       [ 'user_id' => $user->getID() ],
+                       [ 'user_id' => $user->getId() ],
                        __METHOD__
                );
        }
index 914781c..a656c2e 100644 (file)
@@ -56,8 +56,6 @@ class EmailConfirmation extends UnlistedSpecialPage {
                $this->checkReadOnly();
                $this->checkPermissions();
 
-               $this->requireLogin( 'confirmemail_needlogin' );
-
                // This could also let someone check the current email address, so
                // require both permissions.
                if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
@@ -65,6 +63,7 @@ class EmailConfirmation extends UnlistedSpecialPage {
                }
 
                if ( $code === null || $code === '' ) {
+                       $this->requireLogin( 'confirmemail_needlogin' );
                        if ( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) {
                                $this->showRequestForm();
                        } else {
index 5a351a7..431b556 100644 (file)
@@ -85,7 +85,7 @@ class SpecialContributions extends IncludableSpecialPage {
 
                        return;
                }
-               $id = $userObj->getID();
+               $id = $userObj->getId();
 
                if ( $this->opts['contribs'] != 'newbie' ) {
                        $target = $nt->getText();
@@ -673,508 +673,3 @@ class SpecialContributions extends IncludableSpecialPage {
                return 'users';
        }
 }
-
-/**
- * Pager for Special:Contributions
- * @ingroup SpecialPage Pager
- */
-class ContribsPager extends ReverseChronologicalPager {
-       public $mDefaultDirection = IndexPager::DIR_DESCENDING;
-       public $messages;
-       public $target;
-       public $namespace = '';
-       public $mDb;
-       public $preventClickjacking = false;
-
-       /** @var IDatabase */
-       public $mDbSecondary;
-
-       /**
-        * @var array
-        */
-       protected $mParentLens;
-
-       function __construct( IContextSource $context, array $options ) {
-               parent::__construct( $context );
-
-               $msgs = [
-                       'diff',
-                       'hist',
-                       'pipe-separator',
-                       'uctop'
-               ];
-
-               foreach ( $msgs as $msg ) {
-                       $this->messages[$msg] = $this->msg( $msg )->escaped();
-               }
-
-               $this->target = isset( $options['target'] ) ? $options['target'] : '';
-               $this->contribs = isset( $options['contribs'] ) ? $options['contribs'] : 'users';
-               $this->namespace = isset( $options['namespace'] ) ? $options['namespace'] : '';
-               $this->tagFilter = isset( $options['tagfilter'] ) ? $options['tagfilter'] : false;
-               $this->nsInvert = isset( $options['nsInvert'] ) ? $options['nsInvert'] : false;
-               $this->associated = isset( $options['associated'] ) ? $options['associated'] : false;
-
-               $this->deletedOnly = !empty( $options['deletedOnly'] );
-               $this->topOnly = !empty( $options['topOnly'] );
-               $this->newOnly = !empty( $options['newOnly'] );
-
-               $year = isset( $options['year'] ) ? $options['year'] : false;
-               $month = isset( $options['month'] ) ? $options['month'] : false;
-               $this->getDateCond( $year, $month );
-
-               // Most of this code will use the 'contributions' group DB, which can map to slaves
-               // with extra user based indexes or partioning by user. The additional metadata
-               // queries should use a regular slave since the lookup pattern is not all by user.
-               $this->mDbSecondary = wfGetDB( DB_SLAVE ); // any random slave
-               $this->mDb = wfGetDB( DB_SLAVE, 'contributions' );
-       }
-
-       function getDefaultQuery() {
-               $query = parent::getDefaultQuery();
-               $query['target'] = $this->target;
-
-               return $query;
-       }
-
-       /**
-        * This method basically executes the exact same code as the parent class, though with
-        * a hook added, to allow extensions to add additional queries.
-        *
-        * @param string $offset Index offset, inclusive
-        * @param int $limit Exact query limit
-        * @param bool $descending Query direction, false for ascending, true for descending
-        * @return ResultWrapper
-        */
-       function reallyDoQuery( $offset, $limit, $descending ) {
-               list( $tables, $fields, $conds, $fname, $options, $join_conds ) = $this->buildQueryInfo(
-                       $offset,
-                       $limit,
-                       $descending
-               );
-
-               /*
-                * This hook will allow extensions to add in additional queries, so they can get their data
-                * in My Contributions as well. Extensions should append their results to the $data array.
-                *
-                * Extension queries have to implement the navbar requirement as well. They should
-                * - have a column aliased as $pager->getIndexField()
-                * - have LIMIT set
-                * - have a WHERE-clause that compares the $pager->getIndexField()-equivalent column to the offset
-                * - have the ORDER BY specified based upon the details provided by the navbar
-                *
-                * See includes/Pager.php buildQueryInfo() method on how to build LIMIT, WHERE & ORDER BY
-                *
-                * &$data: an array of results of all contribs queries
-                * $pager: the ContribsPager object hooked into
-                * $offset: see phpdoc above
-                * $limit: see phpdoc above
-                * $descending: see phpdoc above
-                */
-               $data = [ $this->mDb->select(
-                       $tables, $fields, $conds, $fname, $options, $join_conds
-               ) ];
-               Hooks::run(
-                       'ContribsPager::reallyDoQuery',
-                       [ &$data, $this, $offset, $limit, $descending ]
-               );
-
-               $result = [];
-
-               // loop all results and collect them in an array
-               foreach ( $data as $query ) {
-                       foreach ( $query as $i => $row ) {
-                               // use index column as key, allowing us to easily sort in PHP
-                               $result[$row->{$this->getIndexField()} . "-$i"] = $row;
-                       }
-               }
-
-               // sort results
-               if ( $descending ) {
-                       ksort( $result );
-               } else {
-                       krsort( $result );
-               }
-
-               // enforce limit
-               $result = array_slice( $result, 0, $limit );
-
-               // get rid of array keys
-               $result = array_values( $result );
-
-               return new FakeResultWrapper( $result );
-       }
-
-       function getQueryInfo() {
-               list( $tables, $index, $userCond, $join_cond ) = $this->getUserCond();
-
-               $user = $this->getUser();
-               $conds = array_merge( $userCond, $this->getNamespaceCond() );
-
-               // Paranoia: avoid brute force searches (bug 17342)
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0';
-               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
-                       $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::SUPPRESSED_USER ) .
-                               ' != ' . Revision::SUPPRESSED_USER;
-               }
-
-               # Don't include orphaned revisions
-               $join_cond['page'] = Revision::pageJoinCond();
-               # Get the current user name for accounts
-               $join_cond['user'] = Revision::userJoinCond();
-
-               $options = [];
-               if ( $index ) {
-                       $options['USE INDEX'] = [ 'revision' => $index ];
-               }
-
-               $queryInfo = [
-                       'tables' => $tables,
-                       'fields' => array_merge(
-                               Revision::selectFields(),
-                               Revision::selectUserFields(),
-                               [ 'page_namespace', 'page_title', 'page_is_new',
-                                       'page_latest', 'page_is_redirect', 'page_len' ]
-                       ),
-                       'conds' => $conds,
-                       'options' => $options,
-                       'join_conds' => $join_cond
-               ];
-
-               ChangeTags::modifyDisplayQuery(
-                       $queryInfo['tables'],
-                       $queryInfo['fields'],
-                       $queryInfo['conds'],
-                       $queryInfo['join_conds'],
-                       $queryInfo['options'],
-                       $this->tagFilter
-               );
-
-               Hooks::run( 'ContribsPager::getQueryInfo', [ &$this, &$queryInfo ] );
-
-               return $queryInfo;
-       }
-
-       function getUserCond() {
-               $condition = [];
-               $join_conds = [];
-               $tables = [ 'revision', 'page', 'user' ];
-               $index = false;
-               if ( $this->contribs == 'newbie' ) {
-                       $max = $this->mDb->selectField( 'user', 'max(user_id)', false, __METHOD__ );
-                       $condition[] = 'rev_user >' . (int)( $max - $max / 100 );
-                       # ignore local groups with the bot right
-                       # @todo FIXME: Global groups may have 'bot' rights
-                       $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' );
-                       if ( count( $groupsWithBotPermission ) ) {
-                               $tables[] = 'user_groups';
-                               $condition[] = 'ug_group IS NULL';
-                               $join_conds['user_groups'] = [
-                                       'LEFT JOIN', [
-                                               'ug_user = rev_user',
-                                               'ug_group' => $groupsWithBotPermission
-                                       ]
-                               ];
-                       }
-               } else {
-                       $uid = User::idFromName( $this->target );
-                       if ( $uid ) {
-                               $condition['rev_user'] = $uid;
-                               $index = 'user_timestamp';
-                       } else {
-                               $condition['rev_user_text'] = $this->target;
-                               $index = 'usertext_timestamp';
-                       }
-               }
-
-               if ( $this->deletedOnly ) {
-                       $condition[] = 'rev_deleted != 0';
-               }
-
-               if ( $this->topOnly ) {
-                       $condition[] = 'rev_id = page_latest';
-               }
-
-               if ( $this->newOnly ) {
-                       $condition[] = 'rev_parent_id = 0';
-               }
-
-               return [ $tables, $index, $condition, $join_conds ];
-       }
-
-       function getNamespaceCond() {
-               if ( $this->namespace !== '' ) {
-                       $selectedNS = $this->mDb->addQuotes( $this->namespace );
-                       $eq_op = $this->nsInvert ? '!=' : '=';
-                       $bool_op = $this->nsInvert ? 'AND' : 'OR';
-
-                       if ( !$this->associated ) {
-                               return [ "page_namespace $eq_op $selectedNS" ];
-                       }
-
-                       $associatedNS = $this->mDb->addQuotes(
-                               MWNamespace::getAssociated( $this->namespace )
-                       );
-
-                       return [
-                               "page_namespace $eq_op $selectedNS " .
-                                       $bool_op .
-                                       " page_namespace $eq_op $associatedNS"
-                       ];
-               }
-
-               return [];
-       }
-
-       function getIndexField() {
-               return 'rev_timestamp';
-       }
-
-       function doBatchLookups() {
-               # Do a link batch query
-               $this->mResult->seek( 0 );
-               $parentRevIds = [];
-               $this->mParentLens = [];
-               $batch = new LinkBatch();
-               # Give some pointers to make (last) links
-               foreach ( $this->mResult as $row ) {
-                       if ( isset( $row->rev_parent_id ) && $row->rev_parent_id ) {
-                               $parentRevIds[] = $row->rev_parent_id;
-                       }
-                       if ( isset( $row->rev_id ) ) {
-                               $this->mParentLens[$row->rev_id] = $row->rev_len;
-                               if ( $this->contribs === 'newbie' ) { // multiple users
-                                       $batch->add( NS_USER, $row->user_name );
-                                       $batch->add( NS_USER_TALK, $row->user_name );
-                               }
-                               $batch->add( $row->page_namespace, $row->page_title );
-                       }
-               }
-               # Fetch rev_len for revisions not already scanned above
-               $this->mParentLens += Revision::getParentLengths(
-                       $this->mDbSecondary,
-                       array_diff( $parentRevIds, array_keys( $this->mParentLens ) )
-               );
-               $batch->execute();
-               $this->mResult->seek( 0 );
-       }
-
-       /**
-        * @return string
-        */
-       function getStartBody() {
-               return "<ul class=\"mw-contributions-list\">\n";
-       }
-
-       /**
-        * @return string
-        */
-       function getEndBody() {
-               return "</ul>\n";
-       }
-
-       /**
-        * Generates each row in the contributions list.
-        *
-        * Contributions which are marked "top" are currently on top of the history.
-        * For these contributions, a [rollback] link is shown for users with roll-
-        * back privileges. The rollback link restores the most recent version that
-        * was not written by the target user.
-        *
-        * @todo This would probably look a lot nicer in a table.
-        * @param object $row
-        * @return string
-        */
-       function formatRow( $row ) {
-
-               $ret = '';
-               $classes = [];
-
-               /*
-                * There may be more than just revision rows. To make sure that we'll only be processing
-                * revisions here, let's _try_ to build a revision out of our row (without displaying
-                * notices though) and then trying to grab data from the built object. If we succeed,
-                * we're definitely dealing with revision data and we may proceed, if not, we'll leave it
-                * to extensions to subscribe to the hook to parse the row.
-                */
-               MediaWiki\suppressWarnings();
-               try {
-                       $rev = new Revision( $row );
-                       $validRevision = (bool)$rev->getId();
-               } catch ( Exception $e ) {
-                       $validRevision = false;
-               }
-               MediaWiki\restoreWarnings();
-
-               if ( $validRevision ) {
-                       $classes = [];
-
-                       $page = Title::newFromRow( $row );
-                       $link = Linker::link(
-                               $page,
-                               htmlspecialchars( $page->getPrefixedText() ),
-                               [ 'class' => 'mw-contributions-title' ],
-                               $page->isRedirect() ? [ 'redirect' => 'no' ] : []
-                       );
-                       # Mark current revisions
-                       $topmarktext = '';
-                       $user = $this->getUser();
-                       if ( $row->rev_id == $row->page_latest ) {
-                               $topmarktext .= '<span class="mw-uctop">' . $this->messages['uctop'] . '</span>';
-                               # Add rollback link
-                               if ( !$row->page_is_new && $page->quickUserCan( 'rollback', $user )
-                                       && $page->quickUserCan( 'edit', $user )
-                               ) {
-                                       $this->preventClickjacking();
-                                       $topmarktext .= ' ' . Linker::generateRollback( $rev, $this->getContext() );
-                               }
-                       }
-                       # Is there a visible previous revision?
-                       if ( $rev->userCan( Revision::DELETED_TEXT, $user ) && $rev->getParentId() !== 0 ) {
-                               $difftext = Linker::linkKnown(
-                                       $page,
-                                       $this->messages['diff'],
-                                       [],
-                                       [
-                                               'diff' => 'prev',
-                                               'oldid' => $row->rev_id
-                                       ]
-                               );
-                       } else {
-                               $difftext = $this->messages['diff'];
-                       }
-                       $histlink = Linker::linkKnown(
-                               $page,
-                               $this->messages['hist'],
-                               [],
-                               [ 'action' => 'history' ]
-                       );
-
-                       if ( $row->rev_parent_id === null ) {
-                               // For some reason rev_parent_id isn't populated for this row.
-                               // Its rumoured this is true on wikipedia for some revisions (bug 34922).
-                               // Next best thing is to have the total number of bytes.
-                               $chardiff = ' <span class="mw-changeslist-separator">. .</span> ';
-                               $chardiff .= Linker::formatRevisionSize( $row->rev_len );
-                               $chardiff .= ' <span class="mw-changeslist-separator">. .</span> ';
-                       } else {
-                               $parentLen = 0;
-                               if ( isset( $this->mParentLens[$row->rev_parent_id] ) ) {
-                                       $parentLen = $this->mParentLens[$row->rev_parent_id];
-                               }
-
-                               $chardiff = ' <span class="mw-changeslist-separator">. .</span> ';
-                               $chardiff .= ChangesList::showCharacterDifference(
-                                       $parentLen,
-                                       $row->rev_len,
-                                       $this->getContext()
-                               );
-                               $chardiff .= ' <span class="mw-changeslist-separator">. .</span> ';
-                       }
-
-                       $lang = $this->getLanguage();
-                       $comment = $lang->getDirMark() . Linker::revComment( $rev, false, true );
-                       $date = $lang->userTimeAndDate( $row->rev_timestamp, $user );
-                       if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) {
-                               $d = Linker::linkKnown(
-                                       $page,
-                                       htmlspecialchars( $date ),
-                                       [ 'class' => 'mw-changeslist-date' ],
-                                       [ 'oldid' => intval( $row->rev_id ) ]
-                               );
-                       } else {
-                               $d = htmlspecialchars( $date );
-                       }
-                       if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
-                               $d = '<span class="history-deleted">' . $d . '</span>';
-                       }
-
-                       # Show user names for /newbies as there may be different users.
-                       # Note that we already excluded rows with hidden user names.
-                       if ( $this->contribs == 'newbie' ) {
-                               $userlink = ' . . ' . $lang->getDirMark()
-                                       . Linker::userLink( $rev->getUser(), $rev->getUserText() );
-                               $userlink .= ' ' . $this->msg( 'parentheses' )->rawParams(
-                                       Linker::userTalkLink( $rev->getUser(), $rev->getUserText() ) )->escaped() . ' ';
-                       } else {
-                               $userlink = '';
-                       }
-
-                       if ( $rev->getParentId() === 0 ) {
-                               $nflag = ChangesList::flag( 'newpage' );
-                       } else {
-                               $nflag = '';
-                       }
-
-                       if ( $rev->isMinor() ) {
-                               $mflag = ChangesList::flag( 'minor' );
-                       } else {
-                               $mflag = '';
-                       }
-
-                       $del = Linker::getRevDeleteLink( $user, $rev, $page );
-                       if ( $del !== '' ) {
-                               $del .= ' ';
-                       }
-
-                       $diffHistLinks = $this->msg( 'parentheses' )
-                               ->rawParams( $difftext . $this->messages['pipe-separator'] . $histlink )
-                               ->escaped();
-                       $ret = "{$del}{$d} {$diffHistLinks}{$chardiff}{$nflag}{$mflag} ";
-                       $ret .= "{$link}{$userlink} {$comment} {$topmarktext}";
-
-                       # Denote if username is redacted for this edit
-                       if ( $rev->isDeleted( Revision::DELETED_USER ) ) {
-                               $ret .= " <strong>" .
-                                       $this->msg( 'rev-deleted-user-contribs' )->escaped() .
-                                       "</strong>";
-                       }
-
-                       # Tags, if any.
-                       list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow(
-                               $row->ts_tags,
-                               'contributions',
-                               $this->getContext()
-                       );
-                       $classes = array_merge( $classes, $newClasses );
-                       $ret .= " $tagSummary";
-               }
-
-               // Let extensions add data
-               Hooks::run( 'ContributionsLineEnding', [ $this, &$ret, $row, &$classes ] );
-
-               if ( $classes === [] && $ret === '' ) {
-                       wfDebug( "Dropping Special:Contribution row that could not be formatted\n" );
-                       $ret = "<!-- Could not format Special:Contribution row. -->\n";
-               } else {
-                       $ret = Html::rawElement( 'li', [ 'class' => $classes ], $ret ) . "\n";
-               }
-
-               return $ret;
-       }
-
-       /**
-        * Overwrite Pager function and return a helpful comment
-        * @return string
-        */
-       function getSqlComment() {
-               if ( $this->namespace || $this->deletedOnly ) {
-                       // potentially slow, see CR r58153
-                       return 'contributions page filtered for namespace or RevisionDeleted edits';
-               } else {
-                       return 'contributions page unfiltered';
-               }
-       }
-
-       protected function preventClickjacking() {
-               $this->preventClickjacking = true;
-       }
-
-       /**
-        * @return bool
-        */
-       public function getPreventClickjacking() {
-               return $this->preventClickjacking;
-       }
-}
index b790fdf..190bf9f 100644 (file)
  * Implements Special:DeletedContributions to display archived revisions
  * @ingroup SpecialPage
  */
-class DeletedContribsPager extends IndexPager {
-       public $mDefaultDirection = IndexPager::DIR_DESCENDING;
-       public $messages;
-       public $target;
-       public $namespace = '';
-       public $mDb;
-
-       /**
-        * @var string Navigation bar with paging links.
-        */
-       protected $mNavigationBar;
-
-       function __construct( IContextSource $context, $target, $namespace = false ) {
-               parent::__construct( $context );
-               $msgs = [ 'deletionlog', 'undeleteviewlink', 'diff' ];
-               foreach ( $msgs as $msg ) {
-                       $this->messages[$msg] = $this->msg( $msg )->escaped();
-               }
-               $this->target = $target;
-               $this->namespace = $namespace;
-               $this->mDb = wfGetDB( DB_SLAVE, 'contributions' );
-       }
-
-       function getDefaultQuery() {
-               $query = parent::getDefaultQuery();
-               $query['target'] = $this->target;
-
-               return $query;
-       }
-
-       function getQueryInfo() {
-               list( $index, $userCond ) = $this->getUserCond();
-               $conds = array_merge( $userCond, $this->getNamespaceCond() );
-               $user = $this->getUser();
-               // Paranoia: avoid brute force searches (bug 17792)
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
-                       $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::DELETED_USER ) . ' = 0';
-               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
-                       $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::SUPPRESSED_USER ) .
-                               ' != ' . Revision::SUPPRESSED_USER;
-               }
-
-               return [
-                       'tables' => [ 'archive' ],
-                       'fields' => [
-                               'ar_rev_id', 'ar_namespace', 'ar_title', 'ar_timestamp', 'ar_comment',
-                               'ar_minor_edit', 'ar_user', 'ar_user_text', 'ar_deleted'
-                       ],
-                       'conds' => $conds,
-                       'options' => [ 'USE INDEX' => $index ]
-               ];
-       }
-
-       /**
-        * This method basically executes the exact same code as the parent class, though with
-        * a hook added, to allow extensions to add additional queries.
-        *
-        * @param string $offset Index offset, inclusive
-        * @param int $limit Exact query limit
-        * @param bool $descending Query direction, false for ascending, true for descending
-        * @return ResultWrapper
-        */
-       function reallyDoQuery( $offset, $limit, $descending ) {
-               $data = [ parent::reallyDoQuery( $offset, $limit, $descending ) ];
-
-               // This hook will allow extensions to add in additional queries, nearly
-               // identical to ContribsPager::reallyDoQuery.
-               Hooks::run(
-                       'DeletedContribsPager::reallyDoQuery',
-                       [ &$data, $this, $offset, $limit, $descending ]
-               );
-
-               $result = [];
-
-               // loop all results and collect them in an array
-               foreach ( $data as $query ) {
-                       foreach ( $query as $i => $row ) {
-                               // use index column as key, allowing us to easily sort in PHP
-                               $result[$row->{$this->getIndexField()} . "-$i"] = $row;
-                       }
-               }
-
-               // sort results
-               if ( $descending ) {
-                       ksort( $result );
-               } else {
-                       krsort( $result );
-               }
-
-               // enforce limit
-               $result = array_slice( $result, 0, $limit );
-
-               // get rid of array keys
-               $result = array_values( $result );
-
-               return new FakeResultWrapper( $result );
-       }
-
-       function getUserCond() {
-               $condition = [];
-
-               $condition['ar_user_text'] = $this->target;
-               $index = 'usertext_timestamp';
-
-               return [ $index, $condition ];
-       }
-
-       function getIndexField() {
-               return 'ar_timestamp';
-       }
-
-       function getStartBody() {
-               return "<ul>\n";
-       }
-
-       function getEndBody() {
-               return "</ul>\n";
-       }
-
-       function getNavigationBar() {
-               if ( isset( $this->mNavigationBar ) ) {
-                       return $this->mNavigationBar;
-               }
-
-               $linkTexts = [
-                       'prev' => $this->msg( 'pager-newer-n' )->numParams( $this->mLimit )->escaped(),
-                       'next' => $this->msg( 'pager-older-n' )->numParams( $this->mLimit )->escaped(),
-                       'first' => $this->msg( 'histlast' )->escaped(),
-                       'last' => $this->msg( 'histfirst' )->escaped()
-               ];
-
-               $pagingLinks = $this->getPagingLinks( $linkTexts );
-               $limitLinks = $this->getLimitLinks();
-               $lang = $this->getLanguage();
-               $limits = $lang->pipeList( $limitLinks );
-
-               $firstLast = $lang->pipeList( [ $pagingLinks['first'], $pagingLinks['last'] ] );
-               $firstLast = $this->msg( 'parentheses' )->rawParams( $firstLast )->escaped();
-               $prevNext = $this->msg( 'viewprevnext' )
-                       ->rawParams(
-                               $pagingLinks['prev'],
-                               $pagingLinks['next'],
-                               $limits
-                       )->escaped();
-               $separator = $this->msg( 'word-separator' )->escaped();
-               $this->mNavigationBar = $firstLast . $separator . $prevNext;
-
-               return $this->mNavigationBar;
-       }
-
-       function getNamespaceCond() {
-               if ( $this->namespace !== '' ) {
-                       return [ 'ar_namespace' => (int)$this->namespace ];
-               } else {
-                       return [];
-               }
-       }
-
-       /**
-        * Generates each row in the contributions list.
-        *
-        * @todo This would probably look a lot nicer in a table.
-        * @param stdClass $row
-        * @return string
-        */
-       function formatRow( $row ) {
-               $ret = '';
-               $classes = [];
-
-               /*
-                * There may be more than just revision rows. To make sure that we'll only be processing
-                * revisions here, let's _try_ to build a revision out of our row (without displaying
-                * notices though) and then trying to grab data from the built object. If we succeed,
-                * we're definitely dealing with revision data and we may proceed, if not, we'll leave it
-                * to extensions to subscribe to the hook to parse the row.
-                */
-               MediaWiki\suppressWarnings();
-               try {
-                       $rev = Revision::newFromArchiveRow( $row );
-                       $validRevision = (bool)$rev->getId();
-               } catch ( Exception $e ) {
-                       $validRevision = false;
-               }
-               MediaWiki\restoreWarnings();
-
-               if ( $validRevision ) {
-                       $ret = $this->formatRevisionRow( $row );
-               }
-
-               // Let extensions add data
-               Hooks::run( 'DeletedContributionsLineEnding', [ $this, &$ret, $row, &$classes ] );
-
-               if ( $classes === [] && $ret === '' ) {
-                       wfDebug( "Dropping Special:DeletedContribution row that could not be formatted\n" );
-                       $ret = "<!-- Could not format Special:DeletedContribution row. -->\n";
-               } else {
-                       $ret = Html::rawElement( 'li', [ 'class' => $classes ], $ret ) . "\n";
-               }
-
-               return $ret;
-       }
-
-       /**
-        * Generates each row in the contributions list for archive entries.
-        *
-        * Contributions which are marked "top" are currently on top of the history.
-        * For these contributions, a [rollback] link is shown for users with sysop
-        * privileges. The rollback link restores the most recent version that was not
-        * written by the target user.
-        *
-        * @todo This would probably look a lot nicer in a table.
-        * @param stdClass $row
-        * @return string
-        */
-       function formatRevisionRow( $row ) {
-               $page = Title::makeTitle( $row->ar_namespace, $row->ar_title );
-
-               $rev = new Revision( [
-                       'title' => $page,
-                       'id' => $row->ar_rev_id,
-                       'comment' => $row->ar_comment,
-                       'user' => $row->ar_user,
-                       'user_text' => $row->ar_user_text,
-                       'timestamp' => $row->ar_timestamp,
-                       'minor_edit' => $row->ar_minor_edit,
-                       'deleted' => $row->ar_deleted,
-               ] );
-
-               $undelete = SpecialPage::getTitleFor( 'Undelete' );
-
-               $logs = SpecialPage::getTitleFor( 'Log' );
-               $dellog = Linker::linkKnown(
-                       $logs,
-                       $this->messages['deletionlog'],
-                       [],
-                       [
-                               'type' => 'delete',
-                               'page' => $page->getPrefixedText()
-                       ]
-               );
-
-               $reviewlink = Linker::linkKnown(
-                       SpecialPage::getTitleFor( 'Undelete', $page->getPrefixedDBkey() ),
-                       $this->messages['undeleteviewlink']
-               );
-
-               $user = $this->getUser();
-
-               if ( $user->isAllowed( 'deletedtext' ) ) {
-                       $last = Linker::linkKnown(
-                               $undelete,
-                               $this->messages['diff'],
-                               [],
-                               [
-                                       'target' => $page->getPrefixedText(),
-                                       'timestamp' => $rev->getTimestamp(),
-                                       'diff' => 'prev'
-                               ]
-                       );
-               } else {
-                       $last = $this->messages['diff'];
-               }
-
-               $comment = Linker::revComment( $rev );
-               $date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user );
-               $date = htmlspecialchars( $date );
-
-               if ( !$user->isAllowed( 'undelete' ) || !$rev->userCan( Revision::DELETED_TEXT, $user ) ) {
-                       $link = $date; // unusable link
-               } else {
-                       $link = Linker::linkKnown(
-                               $undelete,
-                               $date,
-                               [ 'class' => 'mw-changeslist-date' ],
-                               [
-                                       'target' => $page->getPrefixedText(),
-                                       'timestamp' => $rev->getTimestamp()
-                               ]
-                       );
-               }
-               // Style deleted items
-               if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
-                       $link = '<span class="history-deleted">' . $link . '</span>';
-               }
-
-               $pagelink = Linker::link(
-                       $page,
-                       null,
-                       [ 'class' => 'mw-changeslist-title' ]
-               );
-
-               if ( $rev->isMinor() ) {
-                       $mflag = ChangesList::flag( 'minor' );
-               } else {
-                       $mflag = '';
-               }
-
-               // Revision delete link
-               $del = Linker::getRevDeleteLink( $user, $rev, $page );
-               if ( $del ) {
-                       $del .= ' ';
-               }
-
-               $tools = Html::rawElement(
-                       'span',
-                       [ 'class' => 'mw-deletedcontribs-tools' ],
-                       $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList(
-                               [ $last, $dellog, $reviewlink ] ) )->escaped()
-               );
-
-               $separator = '<span class="mw-changeslist-separator">. .</span>';
-               $ret = "{$del}{$link} {$tools} {$separator} {$mflag} {$pagelink} {$comment}";
-
-               # Denote if username is redacted for this edit
-               if ( $rev->isDeleted( Revision::DELETED_USER ) ) {
-                       $ret .= " <strong>" . $this->msg( 'rev-deleted-user-contribs' )->escaped() . "</strong>";
-               }
-
-               return $ret;
-       }
-
-       /**
-        * Get the Database object in use
-        *
-        * @return IDatabase
-        */
-       public function getDatabase() {
-               return $this->mDb;
-       }
-}
-
 class DeletedContributionsPage extends SpecialPage {
        function __construct() {
                parent::__construct( 'DeletedContributions', 'deletedhistory',
@@ -470,7 +139,7 @@ class DeletedContributionsPage extends SpecialPage {
                }
                $links = '';
                $nt = $userObj->getUserPage();
-               $id = $userObj->getID();
+               $id = $userObj->getId();
                $talk = $nt->getTalkPage();
                if ( $talk ) {
                        # Talk page link
index 1a9d096..c1abd6e 100644 (file)
@@ -49,10 +49,26 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
 
        private $badItems = [];
 
+       /**
+        * @var TitleParser
+        */
+       private $titleParser;
+
        public function __construct() {
                parent::__construct( 'EditWatchlist', 'editmywatchlist' );
        }
 
+       /**
+        * Initialize any services we'll need (unless it has already been provided via a setter).
+        * This allows for dependency injection even though we don't control object creation.
+        */
+       private function initServices() {
+               if ( !$this->titleParser ) {
+                       $lang = $this->getContext()->getLanguage();
+                       $this->titleParser = new MediaWikiTitleCodec( $lang, GenderCache::singleton() );
+               }
+       }
+
        public function doesWrites() {
                return true;
        }
@@ -63,6 +79,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         * @param int $mode
         */
        public function execute( $mode ) {
+               $this->initServices();
                $this->setHeaders();
 
                # Anons don't get a watchlist
@@ -307,32 +324,25 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
        private function getWatchlist() {
                $list = [];
 
-               $index = $this->getRequest()->wasPosted() ? DB_MASTER : DB_SLAVE;
-               $dbr = wfGetDB( $index );
-
-               $res = $dbr->select(
-                       'watchlist',
-                       [
-                               'wl_namespace', 'wl_title'
-                       ], [
-                               'wl_user' => $this->getUser()->getId(),
-                       ],
-                       __METHOD__
+               $watchedItems = WatchedItemStore::getDefaultInstance()->getWatchedItemsForUser(
+                       $this->getUser(),
+                       [ 'forWrite' => $this->getRequest()->wasPosted() ]
                );
 
-               if ( $res->numRows() > 0 ) {
+               if ( $watchedItems ) {
                        /** @var Title[] $titles */
                        $titles = [];
-                       foreach ( $res as $row ) {
-                               $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title );
+                       foreach ( $watchedItems as $watchedItem ) {
+                               $namespace = $watchedItem->getLinkTarget()->getNamespace();
+                               $dbKey = $watchedItem->getLinkTarget()->getDBkey();
+                               $title = Title::makeTitleSafe( $namespace, $dbKey );
 
-                               if ( $this->checkTitle( $title, $row->wl_namespace, $row->wl_title )
+                               if ( $this->checkTitle( $title, $namespace, $dbKey )
                                        && !$title->isTalkPage()
                                ) {
                                        $titles[] = $title;
                                }
                        }
-                       $res->free();
 
                        GenderCache::singleton()->doTitlesArray( $titles );
 
@@ -354,22 +364,18 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         */
        protected function getWatchlistInfo() {
                $titles = [];
-               $dbr = wfGetDB( DB_SLAVE );
 
-               $res = $dbr->select(
-                       [ 'watchlist' ],
-                       [ 'wl_namespace', 'wl_title' ],
-                       [ 'wl_user' => $this->getUser()->getId() ],
-                       __METHOD__,
-                       [ 'ORDER BY' => [ 'wl_namespace', 'wl_title' ] ]
-               );
+               $watchedItems = WatchedItemStore::getDefaultInstance()
+                       ->getWatchedItemsForUser( $this->getUser(), [ 'sort' => WatchedItemStore::SORT_ASC ] );
 
                $lb = new LinkBatch();
 
-               foreach ( $res as $row ) {
-                       $lb->add( $row->wl_namespace, $row->wl_title );
-                       if ( !MWNamespace::isTalk( $row->wl_namespace ) ) {
-                               $titles[$row->wl_namespace][$row->wl_title] = 1;
+               foreach ( $watchedItems as $watchedItem ) {
+                       $namespace = $watchedItem->getLinkTarget()->getNamespace();
+                       $dbKey = $watchedItem->getLinkTarget()->getDBkey();
+                       $lb->add( $namespace, $dbKey );
+                       if ( !MWNamespace::isTalk( $namespace ) ) {
+                               $titles[$namespace][$dbKey] = 1;
                        }
                }
 
@@ -413,22 +419,15 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                        return; // nothing to do
                }
 
-               $dbw = wfGetDB( DB_MASTER );
                $user = $this->getUser();
+               $store = WatchedItemStore::getDefaultInstance();
 
                foreach ( $this->badItems as $row ) {
                        list( $title, $namespace, $dbKey ) = $row;
                        $action = $title ? 'cleaning up' : 'deleting';
                        wfDebug( "User {$user->getName()} has broken watchlist item ns($namespace):$dbKey, $action.\n" );
 
-                       $dbw->delete( 'watchlist',
-                               [
-                                       'wl_user' => $user->getId(),
-                                       'wl_namespace' => $namespace,
-                                       'wl_title' => $dbKey,
-                               ],
-                               __METHOD__
-                       );
+                       $store->removeWatch( $user, new TitleValue( (int)$namespace, $dbKey ) );
 
                        // Can't just do an UPDATE instead of DELETE/INSERT due to unique index
                        if ( $title ) {
@@ -450,39 +449,32 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
        }
 
        /**
-        * Add a list of titles to a user's watchlist
+        * Add a list of targets to a user's watchlist
         *
-        * $titles can be an array of strings or Title objects; the former
-        * is preferred, since Titles are very memory-heavy
-        *
-        * @param array $titles Array of strings, or Title objects
+        * @param string[]|LinkTarget[] $targets
         */
-       private function watchTitles( $titles ) {
-               $dbw = wfGetDB( DB_MASTER );
-               $rows = [];
-
-               foreach ( $titles as $title ) {
-                       if ( !$title instanceof Title ) {
-                               $title = Title::newFromText( $title );
+       private function watchTitles( $targets ) {
+               $expandedTargets = [];
+               foreach ( $targets as $target ) {
+                       if ( !$target instanceof LinkTarget ) {
+                               try {
+                                       $target = $this->titleParser->parseTitle( $target, NS_MAIN );
+                               }
+                               catch ( MalformedTitleException $e ) {
+                                       continue;
+                               }
                        }
 
-                       if ( $title instanceof Title ) {
-                               $rows[] = [
-                                       'wl_user' => $this->getUser()->getId(),
-                                       'wl_namespace' => MWNamespace::getSubject( $title->getNamespace() ),
-                                       'wl_title' => $title->getDBkey(),
-                                       'wl_notificationtimestamp' => null,
-                               ];
-                               $rows[] = [
-                                       'wl_user' => $this->getUser()->getId(),
-                                       'wl_namespace' => MWNamespace::getTalk( $title->getNamespace() ),
-                                       'wl_title' => $title->getDBkey(),
-                                       'wl_notificationtimestamp' => null,
-                               ];
-                       }
+                       $ns = $target->getNamespace();
+                       $dbKey = $target->getDBkey();
+                       $expandedTargets[] = new TitleValue( MWNamespace::getSubject( $ns ), $dbKey );
+                       $expandedTargets[] = new TitleValue( MWNamespace::getTalk( $ns ), $dbKey );
                }
 
-               $dbw->insert( 'watchlist', $rows, __METHOD__, 'IGNORE' );
+               WatchedItemStore::getDefaultInstance()->addWatchBatchForUser(
+                       $this->getUser(),
+                       $expandedTargets
+               );
        }
 
        /**
@@ -494,7 +486,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         * @param array $titles Array of strings, or Title objects
         */
        private function unwatchTitles( $titles ) {
-               $dbw = wfGetDB( DB_MASTER );
+               $store = WatchedItemStore::getDefaultInstance();
 
                foreach ( $titles as $title ) {
                        if ( !$title instanceof Title ) {
@@ -502,25 +494,8 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                        }
 
                        if ( $title instanceof Title ) {
-                               $dbw->delete(
-                                       'watchlist',
-                                       [
-                                               'wl_user' => $this->getUser()->getId(),
-                                               'wl_namespace' => MWNamespace::getSubject( $title->getNamespace() ),
-                                               'wl_title' => $title->getDBkey(),
-                                       ],
-                                       __METHOD__
-                               );
-
-                               $dbw->delete(
-                                       'watchlist',
-                                       [
-                                               'wl_user' => $this->getUser()->getId(),
-                                               'wl_namespace' => MWNamespace::getTalk( $title->getNamespace() ),
-                                               'wl_title' => $title->getDBkey(),
-                                       ],
-                                       __METHOD__
-                               );
+                               $store->removeWatch( $this->getUser(), $title->getSubjectPage() );
+                               $store->removeWatch( $this->getUser(), $title->getTalkPage() );
 
                                $page = WikiPage::factory( $title );
                                Hooks::run( 'UnwatchArticleComplete', [ $this->getUser(), &$page ] );
index 3528be0..fb1943f 100644 (file)
@@ -154,6 +154,10 @@ class SpecialEmailUser extends UnlistedSpecialPage {
 
                $this->mTargetObj = $ret;
 
+               // Set the 'relevant user' in the skin, so it displays links like Contributions,
+               // User logs, UserRights, etc.
+               $this->getSkin()->setRelevantUser( $this->mTargetObj );
+
                $context = new DerivativeContext( $this->getContext() );
                $context->setTitle( $this->getPageTitle() ); // Remove subpage
                $form = new HTMLForm( $this->getFormFields(), $context );
index 35861e3..bb82d03 100644 (file)
@@ -79,7 +79,7 @@ class FileDuplicateSearchPage extends QueryPage {
                }
                $html[] = $this->closeList();
 
-               $this->getOutput()->addHtml( implode( "\n", $html ) );
+               $this->getOutput()->addHTML( implode( "\n", $html ) );
        }
 
        public function getQueryInfo() {
@@ -118,19 +118,17 @@ class FileDuplicateSearchPage extends QueryPage {
                                'id' => 'filename',
                                'size' => 50,
                                'value' => $this->filename,
-                               'cssclass' => 'mw-ui-input-inline'
                        ],
                ];
                $hiddenFields = [
-                       'title' => $this->getPageTitle()->getPrefixedDBKey(),
+                       'title' => $this->getPageTitle()->getPrefixedDBkey(),
                ];
-               $htmlForm = HTMLForm::factory( 'inline', $formFields, $this->getContext() );
+               $htmlForm = HTMLForm::factory( 'ooui', $formFields, $this->getContext() );
                $htmlForm->addHiddenFields( $hiddenFields );
                $htmlForm->setAction( wfScript() );
                $htmlForm->setMethod( 'get' );
                $htmlForm->setSubmitProgressive();
                $htmlForm->setSubmitTextMsg( $this->msg( 'fileduplicatesearch-submit' ) );
-               $htmlForm->setWrapperLegendMsg( 'fileduplicatesearch-legend' );
 
                // The form should be visible always, even if it was submitted (e.g. to perform another action).
                // To bypass the callback validation of HTMLForm, use prepareForm() and displayForm().
@@ -246,11 +244,11 @@ class FileDuplicateSearchPage extends QueryPage {
                        // No prefix suggestion outside of file namespace
                        return [];
                }
-               $search = SearchEngine::create();
-               $search->setLimitOffset( $limit, $offset );
+               $searchEngine = SearchEngine::create();
+               $searchEngine->setLimitOffset( $limit, $offset );
                // Autocomplete subpage the same as a normal search, but just for files
-               $search->setNamespaces( [ NS_FILE ] );
-               $result = $search->defaultPrefixSearch( $search );
+               $searchEngine->setNamespaces( [ NS_FILE ] );
+               $result = $searchEngine->defaultPrefixSearch( $search );
 
                return array_map( function ( Title $t ) {
                        // Remove namespace in search suggestion
index e20382c..5d36a3c 100644 (file)
  * @ingroup SpecialPage
  */
 class SpecialJavaScriptTest extends SpecialPage {
-       /**
-        * @var array Supported frameworks.
-        */
-       private static $frameworks = [
-               'qunit',
-       ];
 
        public function __construct() {
                parent::__construct( 'JavaScriptTest' );
@@ -42,102 +36,33 @@ class SpecialJavaScriptTest extends SpecialPage {
                $this->setHeaders();
                $out->disallowUserJs();
 
-               if ( $par === null ) {
-                       // No framework specified
-                       // If only one framework is configured, redirect to it. Otherwise display a list.
-                       if ( count( self::$frameworks ) === 1 ) {
-                               $out->redirect( $this->getPageTitle( self::$frameworks[0] . '/plain' )->getLocalURL() );
-                               return;
-                       }
-                       $out->setStatusCode( 404 );
-                       $out->setPageTitle( $this->msg( 'javascripttest' ) );
-                       $out->addHTML(
-                               $this->msg( 'javascripttest-pagetext-noframework' )->parseAsBlock()
-                               . $this->getFrameworkListHtml()
-                       );
-                       return;
-               }
-
-               // Determine framework and mode
-               $pars = explode( '/', $par, 2 );
-
-               $framework = $pars[0];
-               if ( !in_array( $framework, self::$frameworks ) ) {
-                       // Framework not found
-                       $out->setStatusCode( 404 );
-                       $out->addHTML(
-                               '<div class="error">'
-                               . $this->msg( 'javascripttest-pagetext-unknownframework' )
-                                       ->plaintextParams( $par )->parseAsBlock()
-                               . '</div>'
-                               . $this->getFrameworkListHtml()
-                       );
-                       return;
-               }
-
                // This special page is disabled by default ($wgEnableJavaScriptTest), and contains
                // no sensitive data. In order to allow TestSwarm to embed it into a test client window,
                // we need to allow iframing of this page.
                $out->allowClickjacking();
-               if ( count( self::$frameworks ) !== 1 ) {
-                       // If there's only one framework, don't set the subtitle since it
-                       // is going to redirect back to this page
-                       $out->setSubtitle(
-                               $this->msg( 'javascripttest-backlink' )
-                                       ->rawParams( Linker::linkKnown( $this->getPageTitle() ) )
-                       );
-               }
 
-               // Custom actions
-               if ( isset( $pars[1] ) ) {
-                       $action = $pars[1];
-                       if ( !in_array( $action, [ 'export', 'plain' ] ) ) {
-                               $out->setStatusCode( 404 );
-                               $out->addHTML(
-                                       '<div class="error">'
-                                       . $this->msg( 'javascripttest-pagetext-unknownaction' )
-                                               ->plaintextParams( $action )->parseAsBlock()
-                                       . '</div>'
-                               );
-                               return;
-                       }
-                       $method = $action . ucfirst( $framework );
-                       $this->$method();
+               // Sub resource: Internal JavaScript export bundle for QUnit
+               if ( $par === 'qunit/export' ) {
+                       $this->exportQUnit();
                        return;
                }
 
-               $method = 'view' . ucfirst( $framework );
-               $this->$method();
-               $out->setPageTitle( $this->msg(
-                       'javascripttest-title',
-                       // Messages: javascripttest-qunit-name
-                       $this->msg( "javascripttest-$framework-name" )->plain()
-               ) );
-       }
-
-       /**
-        * Get a list of frameworks (including introduction paragraph and links
-        * to the framework run pages)
-        *
-        * @return string HTML
-        */
-       private function getFrameworkListHtml() {
-               $list = '<ul>';
-               foreach ( self::$frameworks as $framework ) {
-                       $list .= Html::rawElement(
-                               'li',
-                               [],
-                               Linker::link(
-                                       $this->getPageTitle( $framework ),
-                                       // Message: javascripttest-qunit-name
-                                       $this->msg( "javascripttest-$framework-name" )->escaped()
-                               )
-                       );
+               // Regular view: QUnit test runner
+               // (Support "/qunit" and "/qunit/plain" for backwards compatibility)
+               if ( $par === null || $par === '' || $par === 'qunit' || $par === 'qunit/plain' ) {
+                       $this->plainQUnit();
+                       return;
                }
-               $list .= '</ul>';
 
-               return $this->msg( 'javascripttest-pagetext-frameworks' )->rawParams( $list )
-                       ->parseAsBlock();
+               // Unknown action
+               $out->setStatusCode( 404 );
+               $out->setPageTitle( $this->msg( 'javascripttest' ) );
+               $out->addHTML(
+                       '<div class="error">'
+                       . $this->msg( 'javascripttest-pagetext-unknownaction' )
+                               ->plaintextParams( $par )->parseAsBlock()
+                       . '</div>'
+               );
        }
 
        /**
@@ -152,37 +77,6 @@ class SpecialJavaScriptTest extends SpecialPage {
                return "<div id=\"mw-javascripttest-summary\">$summary</div>";
        }
 
-       /**
-        * Run the test suite on the Special page.
-        *
-        * Rendered by OutputPage and Skin.
-        */
-       private function viewQUnit() {
-               $out = $this->getOutput();
-
-               $modules = $out->getResourceLoader()->getTestModuleNames( 'qunit' );
-
-               $baseHtml = <<<HTML
-<div class="mw-content-ltr">
-<div id="qunit"></div>
-</div>
-HTML;
-
-               $out->addHtml( $this->getSummaryHtml() . $baseHtml );
-
-               // The testrunner configures QUnit and essentially depends on it. However, test suites
-               // are reusable in environments that preload QUnit (or a compatibility interface to
-               // another framework). Therefore we have to load it ourselves.
-               $out->addHtml( ResourceLoader::makeInlineScript(
-                       Xml::encodeJsCall( 'mw.loader.using', [
-                               [ 'jquery.qunit', 'jquery.qunit.completenessTest' ],
-                               new XmlJsCode(
-                                       'function () {' . Xml::encodeJsCall( 'mw.loader.load', [ $modules ] ) . '}'
-                               )
-                       ] )
-               ) );
-       }
-
        /**
         * Generate self-sufficient JavaScript payload to run the tests elsewhere.
         *
index bc33b8e..2a7046e 100644 (file)
@@ -158,7 +158,7 @@ class LinkSearchPage extends QueryPage {
 
                if ( $target != '' ) {
                        $this->setParams( [
-                               'query' => $target2,
+                               'query' => Parser::normalizeLinkUrl( $target2 ),
                                'namespace' => $namespace,
                                'protocol' => $protocol ] );
                        parent::execute( $par );
index ed7e954..49fa417 100644 (file)
@@ -96,12 +96,12 @@ class ListDuplicatedFilesPage extends QueryPage {
                // Future version might include a list of the first 5 duplicates
                // perhaps separated by an "↔".
                $image1 = Title::makeTitle( $result->namespace, $result->title );
-               $dupeSearch = SpecialPage::getTitleFor( 'FileDuplicateSearch', $image1->getDBKey() );
+               $dupeSearch = SpecialPage::getTitleFor( 'FileDuplicateSearch', $image1->getDBkey() );
 
                $msg = $this->msg( 'listduplicatedfiles-entry' )
                        ->params( $image1->getText() )
                        ->numParams( $result->value - 1 )
-                       ->params( $dupeSearch->getPrefixedDBKey() );
+                       ->params( $dupeSearch->getPrefixedDBkey() );
 
                return $msg->parse();
        }
index 16471fe..e6e1048 100644 (file)
@@ -52,6 +52,8 @@ class SpecialListFiles extends IncludableSpecialPage {
                if ( $this->including() ) {
                        $out->addParserOutputContent( $pager->getBodyOutput() );
                } else {
+                       $user = $pager->getRelevantUser();
+                       $this->getSkin()->setRelevantUser( $user );
                        $pager->getForm();
                        $out->addParserOutputContent( $pager->getFullOutput() );
                }
@@ -79,555 +81,3 @@ class SpecialListFiles extends IncludableSpecialPage {
                return 'media';
        }
 }
-
-/**
- * @ingroup SpecialPage Pager
- */
-class ImageListPager extends TablePager {
-       protected $mFieldNames = null;
-
-       // Subclasses should override buildQueryConds instead of using $mQueryConds variable.
-       protected $mQueryConds = [];
-
-       protected $mUserName = null;
-
-       protected $mSearch = '';
-
-       protected $mIncluding = false;
-
-       protected $mShowAll = false;
-
-       protected $mTableName = 'image';
-
-       function __construct( IContextSource $context, $userName = null, $search = '',
-               $including = false, $showAll = false
-       ) {
-               $this->setContext( $context );
-               $this->mIncluding = $including;
-               $this->mShowAll = $showAll;
-
-               if ( $userName !== null && $userName !== '' ) {
-                       $nt = Title::newFromText( $userName, NS_USER );
-                       $user = User::newFromName( $userName, false );
-                       if ( !is_null( $nt ) ) {
-                               $this->mUserName = $nt->getText();
-                       }
-                       if ( !$user || ( $user->isAnon() && !User::isIP( $user->getName() ) ) ) {
-                               $this->getOutput()->wrapWikiMsg(
-                                       "<div class=\"mw-userpage-userdoesnotexist error\">\n$1\n</div>",
-                                       [
-                                               'listfiles-userdoesnotexist',
-                                               wfEscapeWikiText( $userName ),
-                                       ]
-                               );
-                       }
-
-               }
-
-               if ( $search !== '' && !$this->getConfig()->get( 'MiserMode' ) ) {
-                       $this->mSearch = $search;
-                       $nt = Title::newFromText( $this->mSearch );
-
-                       if ( $nt ) {
-                               $dbr = wfGetDB( DB_SLAVE );
-                               $this->mQueryConds[] = 'LOWER(img_name)' .
-                                       $dbr->buildLike( $dbr->anyString(),
-                                               strtolower( $nt->getDBkey() ), $dbr->anyString() );
-                       }
-               }
-
-               if ( !$including ) {
-                       if ( $this->getRequest()->getText( 'sort', 'img_date' ) == 'img_date' ) {
-                               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
-                       } else {
-                               $this->mDefaultDirection = IndexPager::DIR_ASCENDING;
-                       }
-               } else {
-                       $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
-               }
-
-               parent::__construct( $context );
-       }
-
-       /**
-        * Build the where clause of the query.
-        *
-        * Replaces the older mQueryConds member variable.
-        * @param string $table Either "image" or "oldimage"
-        * @return array The query conditions.
-        */
-       protected function buildQueryConds( $table ) {
-               $prefix = $table === 'image' ? 'img' : 'oi';
-               $conds = [];
-
-               if ( !is_null( $this->mUserName ) ) {
-                       $conds[$prefix . '_user_text'] = $this->mUserName;
-               }
-
-               if ( $this->mSearch !== '' ) {
-                       $nt = Title::newFromText( $this->mSearch );
-                       if ( $nt ) {
-                               $dbr = wfGetDB( DB_SLAVE );
-                               $conds[] = 'LOWER(' . $prefix . '_name)' .
-                                       $dbr->buildLike( $dbr->anyString(),
-                                               strtolower( $nt->getDBkey() ), $dbr->anyString() );
-                       }
-               }
-
-               if ( $table === 'oldimage' ) {
-                       // Don't want to deal with revdel.
-                       // Future fixme: Show partial information as appropriate.
-                       // Would have to be careful about filtering by username when username is deleted.
-                       $conds['oi_deleted'] = 0;
-               }
-
-               // Add mQueryConds in case anyone was subclassing and using the old variable.
-               return $conds + $this->mQueryConds;
-       }
-
-       /**
-        * @return array
-        */
-       function getFieldNames() {
-               if ( !$this->mFieldNames ) {
-                       $this->mFieldNames = [
-                               'img_timestamp' => $this->msg( 'listfiles_date' )->text(),
-                               'img_name' => $this->msg( 'listfiles_name' )->text(),
-                               'thumb' => $this->msg( 'listfiles_thumb' )->text(),
-                               'img_size' => $this->msg( 'listfiles_size' )->text(),
-                       ];
-                       if ( is_null( $this->mUserName ) ) {
-                               // Do not show username if filtering by username
-                               $this->mFieldNames['img_user_text'] = $this->msg( 'listfiles_user' )->text();
-                       }
-                       // img_description down here, in order so that its still after the username field.
-                       $this->mFieldNames['img_description'] = $this->msg( 'listfiles_description' )->text();
-
-                       if ( !$this->getConfig()->get( 'MiserMode' ) && !$this->mShowAll ) {
-                               $this->mFieldNames['count'] = $this->msg( 'listfiles_count' )->text();
-                       }
-                       if ( $this->mShowAll ) {
-                               $this->mFieldNames['top'] = $this->msg( 'listfiles-latestversion' )->text();
-                       }
-               }
-
-               return $this->mFieldNames;
-       }
-
-       function isFieldSortable( $field ) {
-               if ( $this->mIncluding ) {
-                       return false;
-               }
-               $sortable = [ 'img_timestamp', 'img_name', 'img_size' ];
-               /* For reference, the indicies we can use for sorting are:
-                * On the image table: img_usertext_timestamp, img_size, img_timestamp
-                * On oldimage: oi_usertext_timestamp, oi_name_timestamp
-                *
-                * In particular that means we cannot sort by timestamp when not filtering
-                * by user and including old images in the results. Which is sad.
-                */
-               if ( $this->getConfig()->get( 'MiserMode' ) && !is_null( $this->mUserName ) ) {
-                       // If we're sorting by user, the index only supports sorting by time.
-                       if ( $field === 'img_timestamp' ) {
-                               return true;
-                       } else {
-                               return false;
-                       }
-               } elseif ( $this->getConfig()->get( 'MiserMode' )
-                       && $this->mShowAll /* && mUserName === null */
-               ) {
-                       // no oi_timestamp index, so only alphabetical sorting in this case.
-                       if ( $field === 'img_name' ) {
-                               return true;
-                       } else {
-                               return false;
-                       }
-               }
-
-               return in_array( $field, $sortable );
-       }
-
-       function getQueryInfo() {
-               // Hacky Hacky Hacky - I want to get query info
-               // for two different tables, without reimplementing
-               // the pager class.
-               $qi = $this->getQueryInfoReal( $this->mTableName );
-
-               return $qi;
-       }
-
-       /**
-        * Actually get the query info.
-        *
-        * This is to allow displaying both stuff from image and oldimage table.
-        *
-        * This is a bit hacky.
-        *
-        * @param string $table Either 'image' or 'oldimage'
-        * @return array Query info
-        */
-       protected function getQueryInfoReal( $table ) {
-               $prefix = $table === 'oldimage' ? 'oi' : 'img';
-
-               $tables = [ $table ];
-               $fields = array_keys( $this->getFieldNames() );
-
-               if ( $table === 'oldimage' ) {
-                       foreach ( $fields as $id => &$field ) {
-                               if ( substr( $field, 0, 4 ) !== 'img_' ) {
-                                       continue;
-                               }
-                               $field = $prefix . substr( $field, 3 ) . ' AS ' . $field;
-                       }
-                       $fields[array_search( 'top', $fields )] = "'no' AS top";
-               } else {
-                       if ( $this->mShowAll ) {
-                               $fields[array_search( 'top', $fields )] = "'yes' AS top";
-                       }
-               }
-               $fields[] = $prefix . '_user AS img_user';
-               $fields[array_search( 'thumb', $fields )] = $prefix . '_name AS thumb';
-
-               $options = $join_conds = [];
-
-               # Depends on $wgMiserMode
-               # Will also not happen if mShowAll is true.
-               if ( isset( $this->mFieldNames['count'] ) ) {
-                       $tables[] = 'oldimage';
-
-                       # Need to rewrite this one
-                       foreach ( $fields as &$field ) {
-                               if ( $field == 'count' ) {
-                                       $field = 'COUNT(oi_archive_name) AS count';
-                               }
-                       }
-                       unset( $field );
-
-                       $dbr = wfGetDB( DB_SLAVE );
-                       if ( $dbr->implicitGroupby() ) {
-                               $options = [ 'GROUP BY' => 'img_name' ];
-                       } else {
-                               $columnlist = preg_grep( '/^img/', array_keys( $this->getFieldNames() ) );
-                               $options = [ 'GROUP BY' => array_merge( [ 'img_user' ], $columnlist ) ];
-                       }
-                       $join_conds = [ 'oldimage' => [ 'LEFT JOIN', 'oi_name = img_name' ] ];
-               }
-
-               return [
-                       'tables' => $tables,
-                       'fields' => $fields,
-                       'conds' => $this->buildQueryConds( $table ),
-                       'options' => $options,
-                       'join_conds' => $join_conds
-               ];
-       }
-
-       /**
-        * Override reallyDoQuery to mix together two queries.
-        *
-        * @note $asc is named $descending in IndexPager base class. However
-        *   it is true when the order is ascending, and false when the order
-        *   is descending, so I renamed it to $asc here.
-        * @param int $offset
-        * @param int $limit
-        * @param bool $asc
-        * @return array
-        * @throws MWException
-        */
-       function reallyDoQuery( $offset, $limit, $asc ) {
-               $prevTableName = $this->mTableName;
-               $this->mTableName = 'image';
-               list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
-                       $this->buildQueryInfo( $offset, $limit, $asc );
-               $imageRes = $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
-               $this->mTableName = $prevTableName;
-
-               if ( !$this->mShowAll ) {
-                       return $imageRes;
-               }
-
-               $this->mTableName = 'oldimage';
-
-               # Hacky...
-               $oldIndex = $this->mIndexField;
-               if ( substr( $this->mIndexField, 0, 4 ) !== 'img_' ) {
-                       throw new MWException( "Expected to be sorting on an image table field" );
-               }
-               $this->mIndexField = 'oi_' . substr( $this->mIndexField, 4 );
-
-               list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
-                       $this->buildQueryInfo( $offset, $limit, $asc );
-               $oldimageRes = $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
-
-               $this->mTableName = $prevTableName;
-               $this->mIndexField = $oldIndex;
-
-               return $this->combineResult( $imageRes, $oldimageRes, $limit, $asc );
-       }
-
-       /**
-        * Combine results from 2 tables.
-        *
-        * Note: This will throw away some results
-        *
-        * @param ResultWrapper $res1
-        * @param ResultWrapper $res2
-        * @param int $limit
-        * @param bool $ascending See note about $asc in $this->reallyDoQuery
-        * @return FakeResultWrapper $res1 and $res2 combined
-        */
-       protected function combineResult( $res1, $res2, $limit, $ascending ) {
-               $res1->rewind();
-               $res2->rewind();
-               $topRes1 = $res1->next();
-               $topRes2 = $res2->next();
-               $resultArray = [];
-               for ( $i = 0; $i < $limit && $topRes1 && $topRes2; $i++ ) {
-                       if ( strcmp( $topRes1->{$this->mIndexField}, $topRes2->{$this->mIndexField} ) > 0 ) {
-                               if ( !$ascending ) {
-                                       $resultArray[] = $topRes1;
-                                       $topRes1 = $res1->next();
-                               } else {
-                                       $resultArray[] = $topRes2;
-                                       $topRes2 = $res2->next();
-                               }
-                       } else {
-                               if ( !$ascending ) {
-                                       $resultArray[] = $topRes2;
-                                       $topRes2 = $res2->next();
-                               } else {
-                                       $resultArray[] = $topRes1;
-                                       $topRes1 = $res1->next();
-                               }
-                       }
-               }
-
-               // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
-               for ( ; $i < $limit && $topRes1; $i++ ) {
-                       // @codingStandardsIgnoreEnd
-                       $resultArray[] = $topRes1;
-                       $topRes1 = $res1->next();
-               }
-
-               // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
-               for ( ; $i < $limit && $topRes2; $i++ ) {
-                       // @codingStandardsIgnoreEnd
-                       $resultArray[] = $topRes2;
-                       $topRes2 = $res2->next();
-               }
-
-               return new FakeResultWrapper( $resultArray );
-       }
-
-       function getDefaultSort() {
-               if ( $this->mShowAll && $this->getConfig()->get( 'MiserMode' ) && is_null( $this->mUserName ) ) {
-                       // Unfortunately no index on oi_timestamp.
-                       return 'img_name';
-               } else {
-                       return 'img_timestamp';
-               }
-       }
-
-       function doBatchLookups() {
-               $userIds = [];
-               $this->mResult->seek( 0 );
-               foreach ( $this->mResult as $row ) {
-                       $userIds[] = $row->img_user;
-               }
-               # Do a link batch query for names and userpages
-               UserCache::singleton()->doQuery( $userIds, [ 'userpage' ], __METHOD__ );
-       }
-
-       /**
-        * @param string $field
-        * @param string $value
-        * @return Message|string|int The return type depends on the value of $field:
-        *   - thumb: string
-        *   - img_timestamp: string
-        *   - img_name: string
-        *   - img_user_text: string
-        *   - img_size: string
-        *   - img_description: string
-        *   - count: int
-        *   - top: Message
-        * @throws MWException
-        */
-       function formatValue( $field, $value ) {
-               switch ( $field ) {
-                       case 'thumb':
-                               $opt = [ 'time' => wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
-                               $file = RepoGroup::singleton()->getLocalRepo()->findFile( $value, $opt );
-                               // If statement for paranoia
-                               if ( $file ) {
-                                       $thumb = $file->transform( [ 'width' => 180, 'height' => 360 ] );
-
-                                       return $thumb->toHtml( [ 'desc-link' => true ] );
-                               } else {
-                                       return htmlspecialchars( $value );
-                               }
-                       case 'img_timestamp':
-                               // We may want to make this a link to the "old" version when displaying old files
-                               return htmlspecialchars( $this->getLanguage()->userTimeAndDate( $value, $this->getUser() ) );
-                       case 'img_name':
-                               static $imgfile = null;
-                               if ( $imgfile === null ) {
-                                       $imgfile = $this->msg( 'imgfile' )->text();
-                               }
-
-                               // Weird files can maybe exist? Bug 22227
-                               $filePage = Title::makeTitleSafe( NS_FILE, $value );
-                               if ( $filePage ) {
-                                       $link = Linker::linkKnown(
-                                               $filePage,
-                                               htmlspecialchars( $filePage->getText() )
-                                       );
-                                       $download = Xml::element( 'a',
-                                               [ 'href' => wfLocalFile( $filePage )->getURL() ],
-                                               $imgfile
-                                       );
-                                       $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped();
-
-                                       // Add delete links if allowed
-                                       // From https://github.com/Wikia/app/pull/3859
-                                       if ( $filePage->userCan( 'delete', $this->getUser() ) ) {
-                                               $deleteMsg = $this->msg( 'listfiles-delete' )->escaped();
-
-                                               $delete = Linker::linkKnown(
-                                                       $filePage, $deleteMsg, [], [ 'action' => 'delete' ]
-                                               );
-                                               $delete = $this->msg( 'parentheses' )->rawParams( $delete )->escaped();
-
-                                               return "$link $download $delete";
-                                       }
-
-                                       return "$link $download";
-                               } else {
-                                       return htmlspecialchars( $value );
-                               }
-                       case 'img_user_text':
-                               if ( $this->mCurrentRow->img_user ) {
-                                       $name = User::whoIs( $this->mCurrentRow->img_user );
-                                       $link = Linker::link(
-                                               Title::makeTitle( NS_USER, $name ),
-                                               htmlspecialchars( $name )
-                                       );
-                               } else {
-                                       $link = htmlspecialchars( $value );
-                               }
-
-                               return $link;
-                       case 'img_size':
-                               return htmlspecialchars( $this->getLanguage()->formatSize( $value ) );
-                       case 'img_description':
-                               return Linker::formatComment( $value );
-                       case 'count':
-                               return intval( $value ) + 1;
-                       case 'top':
-                               // Messages: listfiles-latestversion-yes, listfiles-latestversion-no
-                               return $this->msg( 'listfiles-latestversion-' . $value );
-                       default:
-                               throw new MWException( "Unknown field '$field'" );
-               }
-       }
-
-       function getForm() {
-               $fields = [];
-               $fields['limit'] = [
-                       'type' => 'select',
-                       'name' => 'limit',
-                       'label-message' => 'table_pager_limit_label',
-                       'options' => $this->getLimitSelectList(),
-                       'default' => $this->mLimit,
-               ];
-
-               if ( !$this->getConfig()->get( 'MiserMode' ) ) {
-                       $fields['ilsearch'] = [
-                               'type' => 'text',
-                               'name' => 'ilsearch',
-                               'id' => 'mw-ilsearch',
-                               'label-message' => 'listfiles_search_for',
-                               'default' => $this->mSearch,
-                               'size' => '40',
-                               'maxlength' => '255',
-                       ];
-               }
-
-               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
-               $fields['user'] = [
-                       'type' => 'text',
-                       'name' => 'user',
-                       'id' => 'mw-listfiles-user',
-                       'label-message' => 'username',
-                       'default' => $this->mUserName,
-                       'size' => '40',
-                       'maxlength' => '255',
-                       'cssclass' => 'mw-autocomplete-user', // used by mediawiki.userSuggest
-               ];
-
-               $fields['ilshowall'] = [
-                       'type' => 'check',
-                       'name' => 'ilshowall',
-                       'id' => 'mw-listfiles-show-all',
-                       'label-message' => 'listfiles-show-all',
-                       'default' => $this->mShowAll,
-               ];
-
-               $query = $this->getRequest()->getQueryValues();
-               unset( $query['title'] );
-               unset( $query['limit'] );
-               unset( $query['ilsearch'] );
-               unset( $query['ilshowall'] );
-               unset( $query['user'] );
-
-               $form = new HTMLForm( $fields, $this->getContext() );
-
-               $form->setMethod( 'get' );
-               $form->setTitle( $this->getTitle() );
-               $form->setId( 'mw-listfiles-form' );
-               $form->setWrapperLegendMsg( 'listfiles' );
-               $form->setSubmitTextMsg( 'table_pager_limit_submit' );
-               $form->addHiddenFields( $query );
-
-               $form->prepareForm();
-               $form->displayForm( '' );
-       }
-
-       function getTableClass() {
-               return parent::getTableClass() . ' listfiles';
-       }
-
-       function getNavClass() {
-               return parent::getNavClass() . ' listfiles_nav';
-       }
-
-       function getSortHeaderClass() {
-               return parent::getSortHeaderClass() . ' listfiles_sort';
-       }
-
-       function getPagingQueries() {
-               $queries = parent::getPagingQueries();
-               if ( !is_null( $this->mUserName ) ) {
-                       # Append the username to the query string
-                       foreach ( $queries as &$query ) {
-                               if ( $query !== false ) {
-                                       $query['user'] = $this->mUserName;
-                               }
-                       }
-               }
-
-               return $queries;
-       }
-
-       function getDefaultQuery() {
-               $queries = parent::getDefaultQuery();
-               if ( !isset( $queries['user'] ) && !is_null( $this->mUserName ) ) {
-                       $queries['user'] = $this->mUserName;
-               }
-
-               return $queries;
-       }
-
-       function getTitle() {
-               return SpecialPage::getTitleFor( 'Listfiles' );
-       }
-}
index da31f00..1a8dccf 100644 (file)
  * @ingroup SpecialPage
  */
 
-/**
- * This class is used to get a list of user. The ones with specials
- * rights (sysop, bureaucrat, developer) will have them displayed
- * next to their names.
- *
- * @ingroup SpecialPage
- */
-class UsersPager extends AlphabeticPager {
-
-       /**
-        * @var array A array with user ids as key and a array of groups as value
-        */
-       protected $userGroupCache;
-
-       /**
-        * @param IContextSource $context
-        * @param array $par (Default null)
-        * @param bool $including Whether this page is being transcluded in
-        * another page
-        */
-       function __construct( IContextSource $context = null, $par = null, $including = null ) {
-               if ( $context ) {
-                       $this->setContext( $context );
-               }
-
-               $request = $this->getRequest();
-               $par = ( $par !== null ) ? $par : '';
-               $parms = explode( '/', $par );
-               $symsForAll = [ '*', 'user' ];
-
-               if ( $parms[0] != '' &&
-                       ( in_array( $par, User::getAllGroups() ) || in_array( $par, $symsForAll ) )
-               ) {
-                       $this->requestedGroup = $par;
-                       $un = $request->getText( 'username' );
-               } elseif ( count( $parms ) == 2 ) {
-                       $this->requestedGroup = $parms[0];
-                       $un = $parms[1];
-               } else {
-                       $this->requestedGroup = $request->getVal( 'group' );
-                       $un = ( $par != '' ) ? $par : $request->getText( 'username' );
-               }
-
-               if ( in_array( $this->requestedGroup, $symsForAll ) ) {
-                       $this->requestedGroup = '';
-               }
-               $this->editsOnly = $request->getBool( 'editsOnly' );
-               $this->creationSort = $request->getBool( 'creationSort' );
-               $this->including = $including;
-               $this->mDefaultDirection = $request->getBool( 'desc' )
-                       ? IndexPager::DIR_DESCENDING
-                       : IndexPager::DIR_ASCENDING;
-
-               $this->requestedUser = '';
-
-               if ( $un != '' ) {
-                       $username = Title::makeTitleSafe( NS_USER, $un );
-
-                       if ( !is_null( $username ) ) {
-                               $this->requestedUser = $username->getText();
-                       }
-               }
-
-               parent::__construct();
-       }
-
-       /**
-        * @return string
-        */
-       function getIndexField() {
-               return $this->creationSort ? 'user_id' : 'user_name';
-       }
-
-       /**
-        * @return array
-        */
-       function getQueryInfo() {
-               $dbr = wfGetDB( DB_SLAVE );
-               $conds = [];
-
-               // Don't show hidden names
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
-                       $conds[] = 'ipb_deleted IS NULL OR ipb_deleted = 0';
-               }
-
-               $options = [];
-
-               if ( $this->requestedGroup != '' ) {
-                       $conds['ug_group'] = $this->requestedGroup;
-               }
-
-               if ( $this->requestedUser != '' ) {
-                       # Sorted either by account creation or name
-                       if ( $this->creationSort ) {
-                               $conds[] = 'user_id >= ' . intval( User::idFromName( $this->requestedUser ) );
-                       } else {
-                               $conds[] = 'user_name >= ' . $dbr->addQuotes( $this->requestedUser );
-                       }
-               }
-
-               if ( $this->editsOnly ) {
-                       $conds[] = 'user_editcount > 0';
-               }
-
-               $options['GROUP BY'] = $this->creationSort ? 'user_id' : 'user_name';
-
-               $query = [
-                       'tables' => [ 'user', 'user_groups', 'ipblocks' ],
-                       'fields' => [
-                               'user_name' => $this->creationSort ? 'MAX(user_name)' : 'user_name',
-                               'user_id' => $this->creationSort ? 'user_id' : 'MAX(user_id)',
-                               'edits' => 'MAX(user_editcount)',
-                               'creation' => 'MIN(user_registration)',
-                               'ipb_deleted' => 'MAX(ipb_deleted)' // block/hide status
-                       ],
-                       'options' => $options,
-                       'join_conds' => [
-                               'user_groups' => [ 'LEFT JOIN', 'user_id=ug_user' ],
-                               'ipblocks' => [
-                                       'LEFT JOIN', [
-                                               'user_id=ipb_user',
-                                               'ipb_auto' => 0
-                                       ]
-                               ],
-                       ],
-                       'conds' => $conds
-               ];
-
-               Hooks::run( 'SpecialListusersQueryInfo', [ $this, &$query ] );
-
-               return $query;
-       }
-
-       /**
-        * @param stdClass $row
-        * @return string
-        */
-       function formatRow( $row ) {
-               if ( $row->user_id == 0 ) { # Bug 16487
-                       return '';
-               }
-
-               $userName = $row->user_name;
-
-               $ulinks = Linker::userLink( $row->user_id, $userName );
-               $ulinks .= Linker::userToolLinksRedContribs(
-                       $row->user_id,
-                       $userName,
-                       (int)$row->edits
-               );
-
-               $lang = $this->getLanguage();
-
-               $groups = '';
-               $groups_list = self::getGroups( intval( $row->user_id ), $this->userGroupCache );
-
-               if ( !$this->including && count( $groups_list ) > 0 ) {
-                       $list = [];
-                       foreach ( $groups_list as $group ) {
-                               $list[] = self::buildGroupLink( $group, $userName );
-                       }
-                       $groups = $lang->commaList( $list );
-               }
-
-               $item = $lang->specialList( $ulinks, $groups );
-
-               if ( $row->ipb_deleted ) {
-                       $item = "<span class=\"deleted\">$item</span>";
-               }
-
-               $edits = '';
-               if ( !$this->including && $this->getConfig()->get( 'Edititis' ) ) {
-                       $count = $this->msg( 'usereditcount' )->numParams( $row->edits )->escaped();
-                       $edits = $this->msg( 'word-separator' )->escaped() . $this->msg( 'brackets', $count )->escaped();
-               }
-
-               $created = '';
-               # Some rows may be null
-               if ( !$this->including && $row->creation ) {
-                       $user = $this->getUser();
-                       $d = $lang->userDate( $row->creation, $user );
-                       $t = $lang->userTime( $row->creation, $user );
-                       $created = $this->msg( 'usercreated', $d, $t, $row->user_name )->escaped();
-                       $created = ' ' . $this->msg( 'parentheses' )->rawParams( $created )->escaped();
-               }
-               $blocked = !is_null( $row->ipb_deleted ) ?
-                       ' ' . $this->msg( 'listusers-blocked', $userName )->escaped() :
-                       '';
-
-               Hooks::run( 'SpecialListusersFormatRow', [ &$item, $row ] );
-
-               return Html::rawElement( 'li', [], "{$item}{$edits}{$created}{$blocked}" );
-       }
-
-       function doBatchLookups() {
-               $batch = new LinkBatch();
-               $userIds = [];
-               # Give some pointers to make user links
-               foreach ( $this->mResult as $row ) {
-                       $batch->add( NS_USER, $row->user_name );
-                       $batch->add( NS_USER_TALK, $row->user_name );
-                       $userIds[] = $row->user_id;
-               }
-
-               // Lookup groups for all the users
-               $dbr = wfGetDB( DB_SLAVE );
-               $groupRes = $dbr->select(
-                       'user_groups',
-                       [ 'ug_user', 'ug_group' ],
-                       [ 'ug_user' => $userIds ],
-                       __METHOD__
-               );
-               $cache = [];
-               $groups = [];
-               foreach ( $groupRes as $row ) {
-                       $cache[intval( $row->ug_user )][] = $row->ug_group;
-                       $groups[$row->ug_group] = true;
-               }
-               $this->userGroupCache = $cache;
-
-               // Add page of groups to link batch
-               foreach ( $groups as $group => $unused ) {
-                       $groupPage = User::getGroupPage( $group );
-                       if ( $groupPage ) {
-                               $batch->addObj( $groupPage );
-                       }
-               }
-
-               $batch->execute();
-               $this->mResult->rewind();
-       }
-
-       /**
-        * @return string
-        */
-       function getPageHeader() {
-               list( $self ) = explode( '/', $this->getTitle()->getPrefixedDBkey() );
-
-               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
-
-               # Form tag
-               $out = Xml::openElement(
-                       'form',
-                       [ 'method' => 'get', 'action' => wfScript(), 'id' => 'mw-listusers-form' ]
-               ) .
-                       Xml::fieldset( $this->msg( 'listusers' )->text() ) .
-                       Html::hidden( 'title', $self );
-
-               # Username field (with autocompletion support)
-               $out .= Xml::label( $this->msg( 'listusersfrom' )->text(), 'offset' ) . ' ' .
-                       Html::input(
-                               'username',
-                               $this->requestedUser,
-                               'text',
-                               [
-                                       'class' => 'mw-autocomplete-user',
-                                       'id' => 'offset',
-                                       'size' => 20,
-                                       'autofocus' => $this->requestedUser === ''
-                               ]
-                       ) . ' ';
-
-               # Group drop-down list
-               $sel = new XmlSelect( 'group', 'group', $this->requestedGroup );
-               $sel->addOption( $this->msg( 'group-all' )->text(), '' );
-               foreach ( $this->getAllGroups() as $group => $groupText ) {
-                       $sel->addOption( $groupText, $group );
-               }
-
-               $out .= Xml::label( $this->msg( 'group' )->text(), 'group' ) . ' ';
-               $out .= $sel->getHTML() . '<br />';
-               $out .= Xml::checkLabel(
-                       $this->msg( 'listusers-editsonly' )->text(),
-                       'editsOnly',
-                       'editsOnly',
-                       $this->editsOnly
-               );
-               $out .= '&#160;';
-               $out .= Xml::checkLabel(
-                       $this->msg( 'listusers-creationsort' )->text(),
-                       'creationSort',
-                       'creationSort',
-                       $this->creationSort
-               );
-               $out .= '&#160;';
-               $out .= Xml::checkLabel(
-                       $this->msg( 'listusers-desc' )->text(),
-                       'desc',
-                       'desc',
-                       $this->mDefaultDirection
-               );
-               $out .= '<br />';
-
-               Hooks::run( 'SpecialListusersHeaderForm', [ $this, &$out ] );
-
-               # Submit button and form bottom
-               $out .= Html::hidden( 'limit', $this->mLimit );
-               $out .= Xml::submitButton( $this->msg( 'listusers-submit' )->text() );
-               Hooks::run( 'SpecialListusersHeader', [ $this, &$out ] );
-               $out .= Xml::closeElement( 'fieldset' ) .
-                       Xml::closeElement( 'form' );
-
-               return $out;
-       }
-
-       /**
-        * Get a list of all explicit groups
-        * @return array
-        */
-       function getAllGroups() {
-               $result = [];
-               foreach ( User::getAllGroups() as $group ) {
-                       $result[$group] = User::getGroupName( $group );
-               }
-               asort( $result );
-
-               return $result;
-       }
-
-       /**
-        * Preserve group and username offset parameters when paging
-        * @return array
-        */
-       function getDefaultQuery() {
-               $query = parent::getDefaultQuery();
-               if ( $this->requestedGroup != '' ) {
-                       $query['group'] = $this->requestedGroup;
-               }
-               if ( $this->requestedUser != '' ) {
-                       $query['username'] = $this->requestedUser;
-               }
-               Hooks::run( 'SpecialListusersDefaultQuery', [ $this, &$query ] );
-
-               return $query;
-       }
-
-       /**
-        * Get a list of groups the specified user belongs to
-        *
-        * @param int $uid User id
-        * @param array|null $cache
-        * @return array
-        */
-       protected static function getGroups( $uid, $cache = null ) {
-               if ( $cache === null ) {
-                       $user = User::newFromId( $uid );
-                       $effectiveGroups = $user->getEffectiveGroups();
-               } else {
-                       $effectiveGroups = isset( $cache[$uid] ) ? $cache[$uid] : [];
-               }
-               $groups = array_diff( $effectiveGroups, User::getImplicitGroups() );
-
-               return $groups;
-       }
-
-       /**
-        * Format a link to a group description page
-        *
-        * @param string $group Group name
-        * @param string $username Username
-        * @return string
-        */
-       protected static function buildGroupLink( $group, $username ) {
-               return User::makeGroupLinkHtml(
-                       $group,
-                       User::getGroupMember( $group, $username )
-               );
-       }
-}
-
 /**
  * @ingroup SpecialPage
  */
index d4c7c6a..bbe0e0d 100644 (file)
@@ -49,6 +49,7 @@ class SpecialLog extends SpecialPage {
                $opts->add( 'offset', '' );
                $opts->add( 'dir', '' );
                $opts->add( 'offender', '' );
+               $opts->add( 'subtype', '' );
 
                // Set values
                $opts->fetchValuesFromRequest( $this->getRequest() );
@@ -146,7 +147,8 @@ class SpecialLog extends SpecialPage {
 
        private function parseParams( FormOptions $opts, $par ) {
                # Get parameters
-               $parms = explode( '/', ( $par = ( $par !== null ) ? $par : '' ) );
+               $par = $par !== null ? $par : '';
+               $parms = explode( '/', $par );
                $symsForAll = [ '*', 'all' ];
                if ( $parms[0] != '' &&
                        ( in_array( $par, $this->getConfig()->get( 'LogTypes' ) ) || in_array( $par, $symsForAll ) )
@@ -167,6 +169,7 @@ class SpecialLog extends SpecialPage {
                        null,
                        LogEventsList::USE_CHECKBOXES
                );
+
                $pager = new LogPager(
                        $loglist,
                        $opts->getValue( 'type' ),
@@ -176,7 +179,8 @@ class SpecialLog extends SpecialPage {
                        $extraConds,
                        $opts->getValue( 'year' ),
                        $opts->getValue( 'month' ),
-                       $opts->getValue( 'tagfilter' )
+                       $opts->getValue( 'tagfilter' ),
+                       $opts->getValue( 'subtype' )
                );
 
                $this->addHeader( $opts->getValue( 'type' ) );
@@ -189,13 +193,14 @@ class SpecialLog extends SpecialPage {
                # Show form options
                $loglist->showOptions(
                        $pager->getType(),
-                       $opts->getValue( 'user' ),
+                       $pager->getPerformer(),
                        $pager->getPage(),
                        $pager->getPattern(),
                        $pager->getYear(),
                        $pager->getMonth(),
                        $pager->getFilterParams(),
-                       $opts->getValue( 'tagfilter' )
+                       $pager->getTagFilter(),
+                       $pager->getAction()
                );
 
                # Insert list
index ed12e04..8ba90a6 100644 (file)
@@ -154,7 +154,7 @@ class MediaStatisticsPage extends QueryPage {
         * Output closing </table>
         */
        protected function outputTableEnd() {
-               $this->getOutput()->addHtml( Html::closeElement( 'table' ) );
+               $this->getOutput()->addHTML( Html::closeElement( 'table' ) );
                $this->getOutput()->addWikiText(
                                $this->msg( 'mediastatistics-bytespertype' )
                                        ->numParams( $this->totalPerType )
index 3310538..b916c1f 100644 (file)
@@ -379,78 +379,3 @@ class SpecialMergeHistory extends SpecialPage {
                return 'pagetools';
        }
 }
-
-class MergeHistoryPager extends ReverseChronologicalPager {
-       /** @var SpecialMergeHistory */
-       public $mForm;
-
-       /** @var array */
-       public $mConds;
-
-       function __construct( SpecialMergeHistory $form, $conds, Title $source, Title $dest ) {
-               $this->mForm = $form;
-               $this->mConds = $conds;
-               $this->title = $source;
-               $this->articleID = $source->getArticleID();
-
-               $dbr = wfGetDB( DB_SLAVE );
-               $maxtimestamp = $dbr->selectField(
-                       'revision',
-                       'MIN(rev_timestamp)',
-                       [ 'rev_page' => $dest->getArticleID() ],
-                       __METHOD__
-               );
-               $this->maxTimestamp = $maxtimestamp;
-
-               parent::__construct( $form->getContext() );
-       }
-
-       function getStartBody() {
-               # Do a link batch query
-               $this->mResult->seek( 0 );
-               $batch = new LinkBatch();
-               # Give some pointers to make (last) links
-               $this->mForm->prevId = [];
-               foreach ( $this->mResult as $row ) {
-                       $batch->addObj( Title::makeTitleSafe( NS_USER, $row->user_name ) );
-                       $batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->user_name ) );
-
-                       $rev_id = isset( $rev_id ) ? $rev_id : $row->rev_id;
-                       if ( $rev_id > $row->rev_id ) {
-                               $this->mForm->prevId[$rev_id] = $row->rev_id;
-                       } elseif ( $rev_id < $row->rev_id ) {
-                               $this->mForm->prevId[$row->rev_id] = $rev_id;
-                       }
-
-                       $rev_id = $row->rev_id;
-               }
-
-               $batch->execute();
-               $this->mResult->seek( 0 );
-
-               return '';
-       }
-
-       function formatRow( $row ) {
-               return $this->mForm->formatRevisionRow( $row );
-       }
-
-       function getQueryInfo() {
-               $conds = $this->mConds;
-               $conds['rev_page'] = $this->articleID;
-               $conds[] = "rev_timestamp < " . $this->mDb->addQuotes( $this->maxTimestamp );
-
-               return [
-                       'tables' => [ 'revision', 'page', 'user' ],
-                       'fields' => array_merge( Revision::selectFields(), Revision::selectUserFields() ),
-                       'conds' => $conds,
-                       'join_conds' => [
-                               'page' => Revision::pageJoinCond(),
-                               'user' => Revision::userJoinCond() ]
-               ];
-       }
-
-       function getIndexField() {
-               return 'rev_timestamp';
-       }
-}
index 9e28908..14391d2 100644 (file)
@@ -71,189 +71,3 @@ class SpecialNewFiles extends IncludableSpecialPage {
                }
        }
 }
-
-/**
- * @ingroup SpecialPage Pager
- */
-class NewFilesPager extends ReverseChronologicalPager {
-       /**
-        * @var ImageGallery
-        */
-       protected $gallery;
-
-       /**
-        * @var bool
-        */
-       protected $showBots;
-
-       /**
-        * @var bool
-        */
-       protected $hidePatrolled;
-
-       function __construct( IContextSource $context, $par = null ) {
-               $this->like = $context->getRequest()->getText( 'like' );
-               $this->showBots = $context->getRequest()->getBool( 'showbots', 0 );
-               $this->hidePatrolled = $context->getRequest()->getBool( 'hidepatrolled', 0 );
-               if ( is_numeric( $par ) ) {
-                       $this->setLimit( $par );
-               }
-
-               parent::__construct( $context );
-       }
-
-       function getQueryInfo() {
-               $conds = $jconds = [];
-               $tables = [ 'image' ];
-               $fields = [ 'img_name', 'img_user', 'img_timestamp' ];
-               $options = [];
-
-               if ( !$this->showBots ) {
-                       $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' );
-
-                       if ( count( $groupsWithBotPermission ) ) {
-                               $tables[] = 'user_groups';
-                               $conds[] = 'ug_group IS NULL';
-                               $jconds['user_groups'] = [
-                                       'LEFT JOIN',
-                                       [
-                                               'ug_group' => $groupsWithBotPermission,
-                                               'ug_user = img_user'
-                                       ]
-                               ];
-                       }
-               }
-
-               if ( $this->hidePatrolled ) {
-                       $tables[] = 'recentchanges';
-                       $conds['rc_type'] = RC_LOG;
-                       $conds['rc_log_type'] = 'upload';
-                       $conds['rc_patrolled'] = 0;
-                       $conds['rc_namespace'] = NS_FILE;
-                       $jconds['recentchanges'] = [
-                               'INNER JOIN',
-                               [
-                                       'rc_title = img_name',
-                                       'rc_user = img_user',
-                                       'rc_timestamp = img_timestamp'
-                               ]
-                       ];
-                       // We're ordering by img_timestamp, so we have to make sure MariaDB queries `image` first.
-                       // It sometimes decides to query `recentchanges` first and filesort the result set later
-                       // to get the right ordering. T124205 / https://mariadb.atlassian.net/browse/MDEV-8880
-                       $options[] = 'STRAIGHT_JOIN';
-               }
-
-               if ( !$this->getConfig()->get( 'MiserMode' ) && $this->like !== null ) {
-                       $dbr = wfGetDB( DB_SLAVE );
-                       $likeObj = Title::newFromText( $this->like );
-                       if ( $likeObj instanceof Title ) {
-                               $like = $dbr->buildLike(
-                                       $dbr->anyString(),
-                                       strtolower( $likeObj->getDBkey() ),
-                                       $dbr->anyString()
-                               );
-                               $conds[] = "LOWER(img_name) $like";
-                       }
-               }
-
-               $query = [
-                       'tables' => $tables,
-                       'fields' => $fields,
-                       'join_conds' => $jconds,
-                       'conds' => $conds,
-                       'options' => $options,
-               ];
-
-               return $query;
-       }
-
-       function getIndexField() {
-               return 'img_timestamp';
-       }
-
-       function getStartBody() {
-               if ( !$this->gallery ) {
-                       // Note that null for mode is taken to mean use default.
-                       $mode = $this->getRequest()->getVal( 'gallerymode', null );
-                       try {
-                               $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
-                       } catch ( Exception $e ) {
-                               // User specified something invalid, fallback to default.
-                               $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
-                       }
-               }
-
-               return '';
-       }
-
-       function getEndBody() {
-               return $this->gallery->toHTML();
-       }
-
-       function formatRow( $row ) {
-               $name = $row->img_name;
-               $user = User::newFromId( $row->img_user );
-
-               $title = Title::makeTitle( NS_FILE, $name );
-               $ul = Linker::link( $user->getUserpage(), $user->getName() );
-               $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() );
-
-               $this->gallery->add(
-                       $title,
-                       "$ul<br />\n<i>"
-                               . htmlspecialchars( $time )
-                               . "</i><br />\n"
-               );
-       }
-
-       function getForm() {
-               $fields = [
-                       'like' => [
-                               'type' => 'text',
-                               'label-message' => 'newimages-label',
-                               'name' => 'like',
-                       ],
-                       'showbots' => [
-                               'type' => 'check',
-                               'label-message' => 'newimages-showbots',
-                               'name' => 'showbots',
-                       ],
-                       'hidepatrolled' => [
-                               'type' => 'check',
-                               'label-message' => 'newimages-hidepatrolled',
-                               'name' => 'hidepatrolled',
-                       ],
-                       'limit' => [
-                               'type' => 'hidden',
-                               'default' => $this->mLimit,
-                               'name' => 'limit',
-                       ],
-                       'offset' => [
-                               'type' => 'hidden',
-                               'default' => $this->getRequest()->getText( 'offset' ),
-                               'name' => 'offset',
-                       ],
-               ];
-
-               if ( $this->getConfig()->get( 'MiserMode' ) ) {
-                       unset( $fields['like'] );
-               }
-
-               if ( !$this->getUser()->useFilePatrol() ) {
-                       unset( $fields['hidepatrolled'] );
-               }
-
-               $context = new DerivativeContext( $this->getContext() );
-               $context->setTitle( $this->getTitle() ); // Remove subpage
-               $form = new HTMLForm( $fields, $context );
-
-               $form->setSubmitTextMsg( 'ilsubmit' );
-               $form->setSubmitProgressive();
-
-               $form->setMethod( 'get' );
-               $form->setWrapperLegendMsg( 'newimages-legend' );
-
-               return $form;
-       }
-}
index f1b231d..c24b054 100644 (file)
@@ -265,11 +265,11 @@ class SpecialNewpages extends IncludableSpecialPage {
                );
                $htmlForm->setMethod( 'get' );
 
-               $out->addHtml( Xml::fieldset( $this->msg( 'newpages' )->text() ) );
+               $out->addHTML( Xml::fieldset( $this->msg( 'newpages' )->text() ) );
 
                $htmlForm->show();
 
-               $out->addHtml(
+               $out->addHTML(
                        Html::rawElement(
                                'div',
                                null,
@@ -479,130 +479,3 @@ class SpecialNewpages extends IncludableSpecialPage {
                return 'changes';
        }
 }
-
-/**
- * @ingroup SpecialPage Pager
- */
-class NewPagesPager extends ReverseChronologicalPager {
-       // Stored opts
-       protected $opts;
-
-       /**
-        * @var HtmlForm
-        */
-       protected $mForm;
-
-       function __construct( $form, FormOptions $opts ) {
-               parent::__construct( $form->getContext() );
-               $this->mForm = $form;
-               $this->opts = $opts;
-       }
-
-       function getQueryInfo() {
-               $conds = [];
-               $conds['rc_new'] = 1;
-
-               $namespace = $this->opts->getValue( 'namespace' );
-               $namespace = ( $namespace === 'all' ) ? false : intval( $namespace );
-
-               $username = $this->opts->getValue( 'username' );
-               $user = Title::makeTitleSafe( NS_USER, $username );
-
-               $rcIndexes = [];
-
-               if ( $namespace !== false ) {
-                       if ( $this->opts->getValue( 'invert' ) ) {
-                               $conds[] = 'rc_namespace != ' . $this->mDb->addQuotes( $namespace );
-                       } else {
-                               $conds['rc_namespace'] = $namespace;
-                       }
-               }
-
-               if ( $user ) {
-                       $conds['rc_user_text'] = $user->getText();
-                       $rcIndexes = 'rc_user_text';
-               } elseif ( User::groupHasPermission( '*', 'createpage' ) &&
-                       $this->opts->getValue( 'hideliu' )
-               ) {
-                       # If anons cannot make new pages, don't "exclude logged in users"!
-                       $conds['rc_user'] = 0;
-               }
-
-               # If this user cannot see patrolled edits or they are off, don't do dumb queries!
-               if ( $this->opts->getValue( 'hidepatrolled' ) && $this->getUser()->useNPPatrol() ) {
-                       $conds['rc_patrolled'] = 0;
-               }
-
-               if ( $this->opts->getValue( 'hidebots' ) ) {
-                       $conds['rc_bot'] = 0;
-               }
-
-               if ( $this->opts->getValue( 'hideredirs' ) ) {
-                       $conds['page_is_redirect'] = 0;
-               }
-
-               // Allow changes to the New Pages query
-               $tables = [ 'recentchanges', 'page' ];
-               $fields = [
-                       'rc_namespace', 'rc_title', 'rc_cur_id', 'rc_user', 'rc_user_text',
-                       'rc_comment', 'rc_timestamp', 'rc_patrolled', 'rc_id', 'rc_deleted',
-                       'length' => 'page_len', 'rev_id' => 'page_latest', 'rc_this_oldid',
-                       'page_namespace', 'page_title'
-               ];
-               $join_conds = [ 'page' => [ 'INNER JOIN', 'page_id=rc_cur_id' ] ];
-
-               Hooks::run( 'SpecialNewpagesConditions',
-                       [ &$this, $this->opts, &$conds, &$tables, &$fields, &$join_conds ] );
-
-               $options = [];
-
-               if ( $rcIndexes ) {
-                       $options = [ 'USE INDEX' => [ 'recentchanges' => $rcIndexes ] ];
-               }
-
-               $info = [
-                       'tables' => $tables,
-                       'fields' => $fields,
-                       'conds' => $conds,
-                       'options' => $options,
-                       'join_conds' => $join_conds
-               ];
-
-               // Modify query for tags
-               ChangeTags::modifyDisplayQuery(
-                       $info['tables'],
-                       $info['fields'],
-                       $info['conds'],
-                       $info['join_conds'],
-                       $info['options'],
-                       $this->opts['tagfilter']
-               );
-
-               return $info;
-       }
-
-       function getIndexField() {
-               return 'rc_timestamp';
-       }
-
-       function formatRow( $row ) {
-               return $this->mForm->formatRow( $row );
-       }
-
-       function getStartBody() {
-               # Do a batch existence check on pages
-               $linkBatch = new LinkBatch();
-               foreach ( $this->mResult as $row ) {
-                       $linkBatch->add( NS_USER, $row->rc_user_text );
-                       $linkBatch->add( NS_USER_TALK, $row->rc_user_text );
-                       $linkBatch->add( $row->page_namespace, $row->page_title );
-               }
-               $linkBatch->execute();
-
-               return '<ul>';
-       }
-
-       function getEndBody() {
-               return '</ul>';
-       }
-}
index 44f31a5..c3ed91f 100644 (file)
@@ -218,7 +218,7 @@ class SpecialPasswordReset extends FormSpecialPage {
 
                $firstUser = $users[0];
 
-               if ( !$firstUser instanceof User || !$firstUser->getID() ) {
+               if ( !$firstUser instanceof User || !$firstUser->getId() ) {
                        // Don't parse username as wikitext (bug 65501)
                        return [ [ 'nosuchuser', wfEscapeWikiText( $data['Username'] ) ] ];
                }
index 8e9636e..54b471e 100644 (file)
@@ -549,7 +549,7 @@ class ProtectedPagesPager extends TablePager {
                ];
        }
 
-       public function getTableClass() {
+       protected function getTableClass() {
                return parent::getTableClass() . ' mw-protectedpages';
        }
 
index 5df425a..c800d96 100644 (file)
@@ -190,74 +190,3 @@ class SpecialProtectedtitles extends SpecialPage {
                return 'maintenance';
        }
 }
-
-/**
- * @todo document
- * @ingroup Pager
- */
-class ProtectedTitlesPager extends AlphabeticPager {
-       public $mForm, $mConds;
-
-       function __construct( $form, $conds = [], $type, $level, $namespace,
-               $sizetype = '', $size = 0
-       ) {
-               $this->mForm = $form;
-               $this->mConds = $conds;
-               $this->level = $level;
-               $this->namespace = $namespace;
-               $this->size = intval( $size );
-               parent::__construct( $form->getContext() );
-       }
-
-       function getStartBody() {
-               # Do a link batch query
-               $this->mResult->seek( 0 );
-               $lb = new LinkBatch;
-
-               foreach ( $this->mResult as $row ) {
-                       $lb->add( $row->pt_namespace, $row->pt_title );
-               }
-
-               $lb->execute();
-
-               return '';
-       }
-
-       /**
-        * @return Title
-        */
-       function getTitle() {
-               return $this->mForm->getTitle();
-       }
-
-       function formatRow( $row ) {
-               return $this->mForm->formatRow( $row );
-       }
-
-       /**
-        * @return array
-        */
-       function getQueryInfo() {
-               $conds = $this->mConds;
-               $conds[] = 'pt_expiry > ' . $this->mDb->addQuotes( $this->mDb->timestamp() ) .
-                       ' OR pt_expiry IS NULL';
-               if ( $this->level ) {
-                       $conds['pt_create_perm'] = $this->level;
-               }
-
-               if ( !is_null( $this->namespace ) ) {
-                       $conds[] = 'pt_namespace=' . $this->mDb->addQuotes( $this->namespace );
-               }
-
-               return [
-                       'tables' => 'protected_titles',
-                       'fields' => [ 'pt_namespace', 'pt_title', 'pt_create_perm',
-                               'pt_expiry', 'pt_timestamp' ],
-                       'conds' => $conds
-               ];
-       }
-
-       function getIndexField() {
-               return 'pt_timestamp';
-       }
-}
index d4c1004..efb1748 100644 (file)
@@ -206,7 +206,7 @@ class SpecialRandomInCategory extends FormSpecialPage {
                        'tables' => [ 'categorylinks', 'page' ],
                        'fields' => [ 'page_title', 'page_namespace' ],
                        'conds' => array_merge( [
-                               'cl_to' => $this->category->getDBKey(),
+                               'cl_to' => $this->category->getDBkey(),
                        ], $this->extra ),
                        'options' => [
                                'ORDER BY' => 'cl_timestamp ' . $dir,
index 7be95fa..de77380 100644 (file)
@@ -366,7 +366,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $rclistOutput .= $list->endRecentChangesList();
 
                if ( $rows->numRows() === 0 ) {
-                       $this->getOutput()->addHtml(
+                       $this->getOutput()->addHTML(
                                '<div class="mw-changeslist-empty">' .
                                $this->msg( 'recentchanges-noresult' )->parse() .
                                '</div>'
@@ -399,7 +399,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $extraOpts = $this->getExtraOptions( $opts );
                $extraOptsCount = count( $extraOpts );
                $count = 0;
-               $submit = ' ' . Xml::submitbutton( $this->msg( 'recentchanges-submit' )->text() );
+               $submit = ' ' . Xml::submitButton( $this->msg( 'recentchanges-submit' )->text() );
 
                $out = Xml::openElement( 'table', [ 'class' => 'mw-recentchanges-table' ] );
                foreach ( $extraOpts as $name => $optionRow ) {
index a259ac2..57a3d92 100644 (file)
@@ -57,7 +57,7 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges {
                $outputPage = $this->getOutput();
                $title = Title::newFromText( $target );
                if ( !$title || $title->isExternal() ) {
-                       $outputPage->addHtml( '<div class="errorbox">' . $this->msg( 'allpagesbadtitle' )
+                       $outputPage->addHTML( '<div class="errorbox">' . $this->msg( 'allpagesbadtitle' )
                                        ->parse() . '</div>' );
 
                        return false;
index 206e400..80dc797 100644 (file)
@@ -99,7 +99,7 @@ class SpecialRedirect extends FormSpecialPage {
                        return null;
                }
                // Default behavior: Use the direct link to the file.
-               $url = $file->getURL();
+               $url = $file->getUrl();
                $request = $this->getRequest();
                $width = $request->getInt( 'width', -1 );
                $height = $request->getInt( 'height', -1 );
@@ -110,7 +110,7 @@ class SpecialRedirect extends FormSpecialPage {
                        // ... and we can
                        if ( $mto && !$mto->isError() ) {
                                // ... change the URL to point to a thumbnail.
-                               $url = $mto->getURL();
+                               $url = $mto->getUrl();
                        }
                }
 
@@ -272,7 +272,6 @@ class SpecialRedirect extends FormSpecialPage {
                                $url = $this->dispatchLog();
                                break;
                        default:
-                               $this->getOutput()->setStatusCode( 404 );
                                $url = null;
                                break;
                }
@@ -353,6 +352,10 @@ class SpecialRedirect extends FormSpecialPage {
                $form->setMethod( 'get' );
        }
 
+       protected function getDisplayFormat() {
+               return 'ooui';
+       }
+
        /**
         * Return an array of subpages that this special page will accept.
         *
index 9bb5d95..dfab8d4 100644 (file)
@@ -299,7 +299,7 @@ class SpecialSearch extends SpecialPage {
                }
 
                // start rendering the page
-               $out->addHtml(
+               $out->addHTML(
                        Xml::openElement(
                                'form',
                                [
@@ -323,7 +323,7 @@ class SpecialSearch extends SpecialPage {
                $num = $titleMatchesNum + $textMatchesNum;
                $totalRes = $numTitleMatches + $numTextMatches;
 
-               $out->addHtml(
+               $out->addHTML(
                        # 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
@@ -342,7 +342,7 @@ class SpecialSearch extends SpecialPage {
                        return;
                }
 
-               $out->addHtml( "<div class='searchresults'>" );
+               $out->addHTML( "<div class='searchresults'>" );
 
                // prev/next links
                $prevnext = null;
@@ -429,7 +429,7 @@ class SpecialSearch extends SpecialPage {
                        $out->addHTML( "<p class='mw-search-pager-bottom'>{$prevnext}</p>\n" );
                }
 
-               $out->addHtml( "</div>" );
+               $out->addHTML( "</div>" );
 
                Hooks::run( 'SpecialSearchResultsAppend', [ $this, $out, $term ] );
 
@@ -551,7 +551,7 @@ class SpecialSearch extends SpecialPage {
                ) {
                        // invalid title
                        // preserve the paragraph for margins etc...
-                       $this->getOutput()->addHtml( '<p></p>' );
+                       $this->getOutput()->addHTML( '<p></p>' );
 
                        return;
                }
@@ -580,7 +580,7 @@ class SpecialSearch extends SpecialPage {
                        $this->getOutput()->wrapWikiMsg( "<p class=\"$linkClass\">\n$1</p>", $params );
                } else {
                        // preserve the paragraph for margins etc...
-                       $this->getOutput()->addHtml( '<p></p>' );
+                       $this->getOutput()->addHTML( '<p></p>' );
                }
        }
 
index c352927..86f1e20 100644 (file)
@@ -36,8 +36,6 @@ class SpecialStatistics extends SpecialPage {
        }
 
        public function execute( $par ) {
-               $miserMode = $this->getConfig()->get( 'MiserMode' );
-
                $this->setHeaders();
                $this->getOutput()->addModuleStyles( 'mediawiki.special' );
 
index 2ff2122..e79fd6e 100644 (file)
@@ -297,7 +297,7 @@ class SpecialTags extends SpecialPage {
 
                        $headerText = $this->msg( 'tags-create-warnings-above', $tag,
                                count( $status->getWarningsArray() ) )->parseAsBlock() .
-                               $out->parse( $status->getWikitext() ) .
+                               $out->parse( $status->getWikiText() ) .
                                $this->msg( 'tags-create-warnings-below' )->parseAsBlock();
 
                        $subform = new HTMLForm( $fields, $this->getContext() );
@@ -311,7 +311,7 @@ class SpecialTags extends SpecialPage {
                        $out->addBacklinkSubtitle( $this->getPageTitle() );
                        return true;
                } else {
-                       $out->addWikiText( "<div class=\"error\">\n" . $status->getWikitext() .
+                       $out->addWikiText( "<div class=\"error\">\n" . $status->getWikiText() .
                                "\n</div>" );
                        return false;
                }
index d14e02f..cff8bf4 100644 (file)
@@ -218,7 +218,7 @@ class SpecialUnblock extends SpecialPage {
                if ( $block->mHideName ) {
                        # Something is deeply FUBAR if this is not a User object, but who knows?
                        $id = $block->getTarget() instanceof User
-                               ? $block->getTarget()->getID()
+                               ? $block->getTarget()->getId()
                                : User::idFromName( $block->getTarget() );
 
                        RevisionDeleteUser::unsuppressUserName( $block->getTarget(), $id );
@@ -229,7 +229,7 @@ class SpecialUnblock extends SpecialPage {
                        $page = Title::makeTitle( NS_USER, '#' . $block->getId() );
                } else {
                        $page = $block->getTarget() instanceof User
-                               ? $block->getTarget()->getUserpage()
+                               ? $block->getTarget()->getUserPage()
                                : Title::makeTitle( NS_USER, $block->getTarget() );
                }
 
@@ -238,7 +238,9 @@ class SpecialUnblock extends SpecialPage {
                $logEntry->setTarget( $page );
                $logEntry->setComment( $data['Reason'] );
                $logEntry->setPerformer( $performer );
-               $logEntry->setTags( $data['Tags'] );
+               if ( isset( $data['Tags'] ) ) {
+                       $logEntry->setTags( $data['Tags'] );
+               }
                $logId = $logEntry->insert();
                $logEntry->publish( $logId );
 
index 52a3d17..c6d3f6e 100644 (file)
@@ -698,6 +698,10 @@ class SpecialUndelete extends SpecialPage {
                parent::__construct( 'Undelete', 'deletedhistory' );
        }
 
+       public function doesWrites() {
+               return true;
+       }
+
        function loadRequest( $par ) {
                $request = $this->getRequest();
                $user = $this->getUser();
index f2da81f..555fe5c 100644 (file)
@@ -306,6 +306,8 @@ class SpecialUploadStash extends UnlistedSpecialPage {
                if ( $size > self::MAX_SERVE_BYTES ) {
                        throw new SpecialUploadStashTooLargeException();
                }
+               // Cancel output buffering and gzipping if set
+               wfResetOutputBuffers();
                self::outputFileHeaders( $contentType, $size );
                print $content;
 
@@ -367,13 +369,14 @@ class SpecialUploadStash extends UnlistedSpecialPage {
 
                $context = new DerivativeContext( $this->getContext() );
                $context->setTitle( $this->getPageTitle() ); // Remove subpage
-               $form = new HTMLForm( [
+               $form = HTMLForm::factory( 'ooui', [
                        'Clear' => [
                                'type' => 'hidden',
                                'default' => true,
                                'name' => 'clear',
                        ]
                ], $context, 'clearStashedUploads' );
+               $form->setSubmitDestructive();
                $form->setSubmitCallback( [ __CLASS__, 'tryClearStashedUploads' ] );
                $form->setSubmitTextMsg( 'uploadstash-clear' );
 
@@ -389,17 +392,27 @@ class SpecialUploadStash extends UnlistedSpecialPage {
                        sort( $files );
                        $fileListItemsHtml = '';
                        foreach ( $files as $file ) {
-                               // TODO: Use Linker::link or even construct the list in plain wikitext
-                               $fileListItemsHtml .= Html::rawElement( 'li', [],
-                                       Html::element( 'a', [ 'href' =>
-                                               $this->getPageTitle( "file/$file" )->getLocalURL() ], $file )
-                               );
+                               $itemHtml = Linker::linkKnown( $this->getPageTitle( "file/$file" ), htmlspecialchars( $file ) );
+                               try {
+                                       $fileObj = $this->stash->getFile( $file );
+                                       $thumb = $fileObj->generateThumbName( $file, [ 'width' => 220 ] );
+                                       $itemHtml .=
+                                               $this->msg( 'word-separator' )->escaped() .
+                                               $this->msg( 'parentheses' )->rawParams(
+                                                       Linker::linkKnown(
+                                                               $this->getPageTitle( "thumb/$file/$thumb" ),
+                                                               $this->msg( 'uploadstash-thumbnail' )->escaped()
+                                                       )
+                                               )->escaped();
+                               } catch ( Exception $e ) {
+                               }
+                               $fileListItemsHtml .= Html::rawElement( 'li', [], $itemHtml );
                        }
-                       $this->getOutput()->addHtml( Html::rawElement( 'ul', [], $fileListItemsHtml ) );
+                       $this->getOutput()->addHTML( Html::rawElement( 'ul', [], $fileListItemsHtml ) );
                        $form->displayForm( $formResult );
-                       $this->getOutput()->addHtml( Html::rawElement( 'p', [], $refreshHtml ) );
+                       $this->getOutput()->addHTML( Html::rawElement( 'p', [], $refreshHtml ) );
                } else {
-                       $this->getOutput()->addHtml( Html::rawElement( 'p', [],
+                       $this->getOutput()->addHTML( Html::rawElement( 'p', [],
                                Html::element( 'span', [], $this->msg( 'uploadstash-nofiles' )->text() )
                                . ' '
                                . $refreshHtml
index 8d45468..9901d36 100644 (file)
@@ -275,7 +275,7 @@ class LoginForm extends SpecialPage {
         */
        public function execute( $subPage ) {
                // Make sure session is persisted
-               $session = MediaWiki\Session\SessionManager::getGlobalSession();
+               $session = SessionManager::getGlobalSession();
                $session->persist();
 
                $this->load();
@@ -792,7 +792,7 @@ class LoginForm extends SpecialPage {
                }
 
                $isAutoCreated = false;
-               if ( $u->getID() == 0 ) {
+               if ( $u->getId() == 0 ) {
                        $status = $this->attemptAutoCreate( $u );
                        if ( $status !== self::SUCCESS ) {
                                return $status;
@@ -1647,8 +1647,8 @@ class LoginForm extends SpecialPage {
 
        /**
         * Get the login token from the current session
-        * @since 1.27 returns a MediaWiki\\Session\\Token instead of a string
-        * @return MediaWiki\\Session\\Token
+        * @since 1.27 returns a MediaWiki\Session\Token instead of a string
+        * @return MediaWiki\Session\Token
         */
        public static function getLoginToken() {
                global $wgRequest;
@@ -1678,8 +1678,8 @@ class LoginForm extends SpecialPage {
 
        /**
         * Get the createaccount token from the current session
-        * @since 1.27 returns a MediaWiki\\Session\\Token instead of a string
-        * @return MediaWiki\\Session\\Token
+        * @since 1.27 returns a MediaWiki\Session\Token instead of a string
+        * @return MediaWiki\Session\Token
         */
        public static function getCreateaccountToken() {
                global $wgRequest;
@@ -1716,7 +1716,7 @@ class LoginForm extends SpecialPage {
                        $wgCookieSecure = false;
                }
 
-               MediaWiki\Session\SessionManager::getGlobalSession()->resetId();
+               SessionManager::getGlobalSession()->resetId();
        }
 
        /**
index 29261f3..be110aa 100644 (file)
@@ -119,7 +119,7 @@ class UserrightsPage extends SpecialPage {
                }
 
                $fetchedStatus = $this->fetchUser( $this->mTarget );
-               if ( $fetchedStatus->isOk() ) {
+               if ( $fetchedStatus->isOK() ) {
                        $this->mFetchedUser = $fetchedStatus->value;
                        if ( $this->mFetchedUser instanceof User ) {
                                // Set the 'relevant user' in the skin, so it displays links like Contributions,
@@ -417,28 +417,18 @@ class UserrightsPage extends SpecialPage {
                return Status::newGood( $user );
        }
 
-       function makeGroupNameList( $ids ) {
-               if ( empty( $ids ) ) {
-                       return $this->msg( 'rightsnone' )->inContentLanguage()->text();
-               } else {
-                       return implode( ', ', $ids );
-               }
-       }
-
        /**
-        * Make a list of group names to be stored as parameter for log entries
+        * @since 1.15
         *
-        * @deprecated since 1.21; use LogFormatter instead.
         * @param array $ids
+        *
         * @return string
         */
-       function makeGroupNameListForLog( $ids ) {
-               wfDeprecated( __METHOD__, '1.21' );
-
+       public function makeGroupNameList( $ids ) {
                if ( empty( $ids ) ) {
-                       return '';
+                       return $this->msg( 'rightsnone' )->inContentLanguage()->text();
                } else {
-                       return $this->makeGroupNameList( $ids );
+                       return implode( ', ', $ids );
                }
        }
 
@@ -627,7 +617,7 @@ class UserrightsPage extends SpecialPage {
         * @return string
         */
        private static function buildGroupLink( $group ) {
-               return User::makeGroupLinkHtml( $group, User::getGroupName( $group ) );
+               return User::makeGroupLinkHTML( $group, User::getGroupName( $group ) );
        }
 
        /**
@@ -637,7 +627,7 @@ class UserrightsPage extends SpecialPage {
         * @return string
         */
        private static function buildGroupMemberLink( $group ) {
-               return User::makeGroupLinkHtml( $group, User::getGroupMember( $group ) );
+               return User::makeGroupLinkHTML( $group, User::getGroupMember( $group ) );
        }
 
        /**
index c0f9590..ce5cbeb 100644 (file)
@@ -132,7 +132,7 @@ class SpecialVersion extends SpecialPage {
                                        $this->softwareInformation() .
                                        $this->getEntryPointInfo()
                                );
-                               $out->addHtml(
+                               $out->addHTML(
                                        $this->getSkinCredits() .
                                        $this->getExtensionCredits() .
                                        $this->getExternalLibraries() .
@@ -177,7 +177,7 @@ class SpecialVersion extends SpecialPage {
                global $wgLang;
 
                if ( defined( 'MEDIAWIKI_INSTALL' ) ) {
-                       $othersLink = '[//www.mediawiki.org/wiki/Special:Version/Credits ' .
+                       $othersLink = '[https://www.mediawiki.org/wiki/Special:Version/Credits ' .
                                wfMessage( 'version-poweredby-others' )->text() . ']';
                } else {
                        $othersLink = '[[Special:Version/Credits|' .
@@ -555,7 +555,7 @@ class SpecialVersion extends SpecialPage {
                                        'id' => 'mw-version-parser-extensiontags',
                                ],
                                Linker::makeExternalLink(
-                                       '//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Tag_extensions',
+                                       'https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Tag_extensions',
                                        $this->msg( 'version-parser-extensiontags' )->parse(),
                                        false /* msg()->parse() already escapes */
                                )
@@ -598,7 +598,7 @@ class SpecialVersion extends SpecialPage {
                                        'id' => 'mw-version-parser-function-hooks',
                                ],
                                Linker::makeExternalLink(
-                                       '//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Parser_functions',
+                                       'https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Parser_functions',
                                        $this->msg( 'version-parser-function-hooks' )->parse(),
                                        false /* msg()->parse() already escapes */
                                )
index dffc9d9..27e5829 100644 (file)
@@ -362,6 +362,12 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                $list->initChangesListRows( $rows );
                $dbr->dataSeek( $rows, 0 );
 
+               if ( $this->getConfig()->get( 'RCShowWatchingUsers' )
+                       && $user->getOption( 'shownumberswatching' )
+               ) {
+                       $watchedItemStore = WatchedItemStore::getDefaultInstance();
+               }
+
                $s = $list->beginRecentChangesList();
                $counter = 1;
                foreach ( $rows as $obj ) {
@@ -375,16 +381,9 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                                $updated = false;
                        }
 
-                       if ( $this->getConfig()->get( 'RCShowWatchingUsers' )
-                               && $user->getOption( 'shownumberswatching' )
-                       ) {
-                               $rc->numberofWatchingusers = $dbr->selectField( 'watchlist',
-                                       'COUNT(*)',
-                                       [
-                                               'wl_namespace' => $obj->rc_namespace,
-                                               'wl_title' => $obj->rc_title,
-                                       ],
-                                       __METHOD__ );
+                       if ( isset( $watchedItemStore ) ) {
+                               $rcTitleValue = new TitleValue( (int)$obj->rc_namespace, $obj->rc_title );
+                               $rc->numberofWatchingusers = $watchedItemStore->countWatchers( $rcTitleValue );
                        } else {
                                $rc->numberofWatchingusers = 0;
                        }
@@ -569,8 +568,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                $form = "";
                $user = $this->getUser();
 
-               $dbr = $this->getDB();
-               $numItems = $this->countItems( $dbr );
+               $numItems = $this->countItems();
                $showUpdatedMarker = $this->getConfig()->get( 'ShowUpdatedMarker' );
 
                // Show watchlist header
@@ -630,18 +628,14 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        }
 
        /**
-        * Count the number of items on a user's watchlist
+        * Count the number of paired items on a user's watchlist.
+        * The assumption made here is that when a subject page is watched a talk page is also watched.
+        * Hence the number of individual items is halved.
         *
-        * @param IDatabase $dbr A database connection
         * @return int
         */
-       protected function countItems( $dbr ) {
-               # Fetch the raw count
-               $rows = $dbr->select( 'watchlist', [ 'count' => 'COUNT(*)' ],
-                       [ 'wl_user' => $this->getUser()->getId() ], __METHOD__ );
-               $row = $dbr->fetchObject( $rows );
-               $count = $row->count;
-
+       protected function countItems() {
+               $count = WatchedItemStore::getDefaultInstance()->countWatchedItems( $this->getUser() );
                return floor( $count / 2 );
        }
 }
index b1c3f16..baa55f0 100644 (file)
@@ -160,7 +160,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                        ];
                        $on['rd_namespace'] = $target->getNamespace();
                        // Inner LIMIT is 2X in case of stale backlinks with wrong namespaces
-                       $subQuery = $dbr->selectSqlText(
+                       $subQuery = $dbr->selectSQLText(
                                [ $table, 'redirect', 'page' ],
                                [ $fromCol, 'rd_from' ],
                                $conds[$table],
diff --git a/includes/specials/pagers/ActiveUsersPager.php b/includes/specials/pagers/ActiveUsersPager.php
new file mode 100644 (file)
index 0000000..0d3bc9a
--- /dev/null
@@ -0,0 +1,254 @@
+<?php
+/**
+ * Copyright © 2008 Aaron Schulz
+ *
+ * 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 Pager
+ */
+
+/**
+ * This class is used to get a list of active users. The ones with specials
+ * rights (sysop, bureaucrat, developer) will have them displayed
+ * next to their names.
+ *
+ * @ingroup Pager
+ */
+class ActiveUsersPager extends UsersPager {
+
+       /**
+        * @var FormOptions
+        */
+       protected $opts;
+
+       /**
+        * @var array
+        */
+       protected $hideGroups = [];
+
+       /**
+        * @var array
+        */
+       protected $hideRights = [];
+
+       /**
+        * @var array
+        */
+       private $blockStatusByUid;
+
+       /**
+        * @param IContextSource $context
+        * @param null $group Unused
+        * @param string $par Parameter passed to the page
+        */
+       function __construct( IContextSource $context = null, $group = null, $par = null ) {
+               parent::__construct( $context );
+
+               $this->RCMaxAge = $this->getConfig()->get( 'ActiveUserDays' );
+               $un = $this->getRequest()->getText( 'username', $par );
+               $this->requestedUser = '';
+               if ( $un != '' ) {
+                       $username = Title::makeTitleSafe( NS_USER, $un );
+                       if ( !is_null( $username ) ) {
+                               $this->requestedUser = $username->getText();
+                       }
+               }
+
+               $this->setupOptions();
+       }
+
+       public function setupOptions() {
+               $this->opts = new FormOptions();
+
+               $this->opts->add( 'hidebots', false, FormOptions::BOOL );
+               $this->opts->add( 'hidesysops', false, FormOptions::BOOL );
+
+               $this->opts->fetchValuesFromRequest( $this->getRequest() );
+
+               if ( $this->opts->getValue( 'hidebots' ) == 1 ) {
+                       $this->hideRights[] = 'bot';
+               }
+               if ( $this->opts->getValue( 'hidesysops' ) == 1 ) {
+                       $this->hideGroups[] = 'sysop';
+               }
+       }
+
+       function getIndexField() {
+               return 'qcc_title';
+       }
+
+       function getQueryInfo() {
+               $dbr = $this->getDatabase();
+
+               $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
+               $timestamp = $dbr->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
+               $conds = [
+                       'qcc_type' => 'activeusers',
+                       'qcc_namespace' => NS_USER,
+                       'user_name = qcc_title',
+                       'rc_user_text = qcc_title',
+                       'rc_type != ' . $dbr->addQuotes( RC_EXTERNAL ), // Don't count wikidata.
+                       'rc_type != ' . $dbr->addQuotes( RC_CATEGORIZE ), // Don't count categorization changes.
+                       'rc_log_type IS NULL OR rc_log_type != ' . $dbr->addQuotes( 'newusers' ),
+                       'rc_timestamp >= ' . $dbr->addQuotes( $timestamp ),
+               ];
+               if ( $this->requestedUser != '' ) {
+                       $conds[] = 'qcc_title >= ' . $dbr->addQuotes( $this->requestedUser );
+               }
+               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+                       $conds[] = 'NOT EXISTS (' . $dbr->selectSQLText(
+                                       'ipblocks', '1', [ 'ipb_user=user_id', 'ipb_deleted' => 1 ]
+                               ) . ')';
+               }
+
+               if ( $dbr->implicitGroupby() ) {
+                       $options = [ 'GROUP BY' => [ 'qcc_title' ] ];
+               } else {
+                       $options = [ 'GROUP BY' => [ 'user_name', 'user_id', 'qcc_title' ] ];
+               }
+
+               return [
+                       'tables' => [ 'querycachetwo', 'user', 'recentchanges' ],
+                       'fields' => [ 'user_name', 'user_id', 'recentedits' => 'COUNT(*)', 'qcc_title' ],
+                       'options' => $options,
+                       'conds' => $conds
+               ];
+       }
+
+       function doBatchLookups() {
+               parent::doBatchLookups();
+
+               $uids = [];
+               foreach ( $this->mResult as $row ) {
+                       $uids[] = $row->user_id;
+               }
+               // Fetch the block status of the user for showing "(blocked)" text and for
+               // striking out names of suppressed users when privileged user views the list.
+               // Although the first query already hits the block table for un-privileged, this
+               // is done in two queries to avoid huge quicksorts and to make COUNT(*) correct.
+               $dbr = $this->getDatabase();
+               $res = $dbr->select( 'ipblocks',
+                       [ 'ipb_user', 'MAX(ipb_deleted) AS block_status' ],
+                       [ 'ipb_user' => $uids ],
+                       __METHOD__,
+                       [ 'GROUP BY' => [ 'ipb_user' ] ]
+               );
+               $this->blockStatusByUid = [];
+               foreach ( $res as $row ) {
+                       $this->blockStatusByUid[$row->ipb_user] = $row->block_status; // 0 or 1
+               }
+               $this->mResult->seek( 0 );
+       }
+
+       function formatRow( $row ) {
+               $userName = $row->user_name;
+
+               $ulinks = Linker::userLink( $row->user_id, $userName );
+               $ulinks .= Linker::userToolLinks( $row->user_id, $userName );
+
+               $lang = $this->getLanguage();
+
+               $list = [];
+               $user = User::newFromId( $row->user_id );
+
+               // User right filter
+               foreach ( $this->hideRights as $right ) {
+                       // Calling User::getRights() within the loop so that
+                       // if the hideRights() filter is empty, we don't have to
+                       // trigger the lazy-init of the big userrights array in the
+                       // User object
+                       if ( in_array( $right, $user->getRights() ) ) {
+                               return '';
+                       }
+               }
+
+               // User group filter
+               // Note: This is a different loop than for user rights,
+               // because we're reusing it to build the group links
+               // at the same time
+               $groups_list = self::getGroups( intval( $row->user_id ), $this->userGroupCache );
+               foreach ( $groups_list as $group ) {
+                       if ( in_array( $group, $this->hideGroups ) ) {
+                               return '';
+                       }
+                       $list[] = self::buildGroupLink( $group, $userName );
+               }
+
+               $groups = $lang->commaList( $list );
+
+               $item = $lang->specialList( $ulinks, $groups );
+
+               $isBlocked = isset( $this->blockStatusByUid[$row->user_id] );
+               if ( $isBlocked && $this->blockStatusByUid[$row->user_id] == 1 ) {
+                       $item = "<span class=\"deleted\">$item</span>";
+               }
+               $count = $this->msg( 'activeusers-count' )->numParams( $row->recentedits )
+                       ->params( $userName )->numParams( $this->RCMaxAge )->escaped();
+               $blocked = $isBlocked ? ' ' . $this->msg( 'listusers-blocked', $userName )->escaped() : '';
+
+               return Html::rawElement( 'li', [], "{$item} [{$count}]{$blocked}" );
+       }
+
+       function getPageHeader() {
+               $self = $this->getTitle();
+               $limit = $this->mLimit ? Html::hidden( 'limit', $this->mLimit ) : '';
+
+               # Form tag
+               $out = Xml::openElement( 'form', [ 'method' => 'get', 'action' => wfScript() ] );
+               $out .= Xml::fieldset( $this->msg( 'activeusers' )->text() ) . "\n";
+               $out .= Html::hidden( 'title', $self->getPrefixedDBkey() ) . $limit . "\n";
+
+               # Username field (with autocompletion support)
+               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
+               $out .= Xml::inputLabel(
+                               $this->msg( 'activeusers-from' )->text(),
+                               'username',
+                               'offset',
+                               20,
+                               $this->requestedUser,
+                               [
+                                       'class' => 'mw-ui-input-inline mw-autocomplete-user',
+                                       'tabindex' => 1,
+                               ] + (
+                                       // Set autofocus on blank input
+                               $this->requestedUser === '' ? [ 'autofocus' => '' ] : []
+                               )
+                       ) . '<br />';
+
+               $out .= Xml::checkLabel( $this->msg( 'activeusers-hidebots' )->text(),
+                       'hidebots', 'hidebots', $this->opts->getValue( 'hidebots' ), [ 'tabindex' => 2 ] );
+
+               $out .= Xml::checkLabel(
+                               $this->msg( 'activeusers-hidesysops' )->text(),
+                               'hidesysops',
+                               'hidesysops',
+                               $this->opts->getValue( 'hidesysops' ),
+                               [ 'tabindex' => 3 ]
+                       ) . '<br />';
+
+               # Submit button and form bottom
+               $out .= Xml::submitButton(
+                               $this->msg( 'activeusers-submit' )->text(),
+                               [ 'tabindex' => 4 ]
+                       ) . "\n";
+               $out .= Xml::closeElement( 'fieldset' );
+               $out .= Xml::closeElement( 'form' );
+
+               return $out;
+       }
+
+}
diff --git a/includes/specials/pagers/AllMessagesTablePager.php b/includes/specials/pagers/AllMessagesTablePager.php
new file mode 100644 (file)
index 0000000..2f2cbc2
--- /dev/null
@@ -0,0 +1,424 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * Use TablePager for prettified output. We have to pretend that we're
+ * getting data from a table when in fact not all of it comes from the database.
+ *
+ * @ingroup Pager
+ */
+class AllMessagesTablePager extends TablePager {
+
+       protected $filter, $prefix, $langcode, $displayPrefix;
+
+       public $mLimitsShown;
+
+       /**
+        * @var Language
+        */
+       public $lang;
+
+       /**
+        * @var null|bool
+        */
+       public $custom;
+
+       function __construct( $page, $conds, $langObj = null ) {
+               parent::__construct( $page->getContext() );
+               $this->mIndexField = 'am_title';
+               $this->mPage = $page;
+               $this->mConds = $conds;
+               // FIXME: Why does this need to be set to DIR_DESCENDING to produce ascending ordering?
+               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
+               $this->mLimitsShown = [ 20, 50, 100, 250, 500, 5000 ];
+
+               global $wgContLang;
+
+               $this->talk = $this->msg( 'talkpagelinktext' )->escaped();
+
+               $this->lang = ( $langObj ? $langObj : $wgContLang );
+               $this->langcode = $this->lang->getCode();
+               $this->foreign = $this->langcode !== $wgContLang->getCode();
+
+               $request = $this->getRequest();
+
+               $this->filter = $request->getVal( 'filter', 'all' );
+               if ( $this->filter === 'all' ) {
+                       $this->custom = null; // So won't match in either case
+               } else {
+                       $this->custom = ( $this->filter === 'unmodified' );
+               }
+
+               $prefix = $this->getLanguage()->ucfirst( $request->getVal( 'prefix', '' ) );
+               $prefix = $prefix !== '' ?
+                       Title::makeTitleSafe( NS_MEDIAWIKI, $request->getVal( 'prefix', null ) ) :
+                       null;
+
+               if ( $prefix !== null ) {
+                       $this->displayPrefix = $prefix->getDBkey();
+                       $this->prefix = '/^' . preg_quote( $this->displayPrefix, '/' ) . '/i';
+               } else {
+                       $this->displayPrefix = false;
+                       $this->prefix = false;
+               }
+
+               // The suffix that may be needed for message names if we're in a
+               // different language (eg [[MediaWiki:Foo/fr]]: $suffix = '/fr'
+               if ( $this->foreign ) {
+                       $this->suffix = '/' . $this->langcode;
+               } else {
+                       $this->suffix = '';
+               }
+       }
+
+       function buildForm() {
+               $attrs = [ 'id' => 'mw-allmessages-form-lang', 'name' => 'lang' ];
+               $msg = wfMessage( 'allmessages-language' );
+               $langSelect = Xml::languageSelector( $this->langcode, false, null, $attrs, $msg );
+
+               $out = Xml::openElement( 'form', [
+                               'method' => 'get',
+                               'action' => $this->getConfig()->get( 'Script' ),
+                               'id' => 'mw-allmessages-form'
+                       ] ) .
+                       Xml::fieldset( $this->msg( 'allmessages-filter-legend' )->text() ) .
+                       Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
+                       Xml::openElement( 'table', [ 'class' => 'mw-allmessages-table' ] ) . "\n" .
+                       '<tr>
+                               <td class="mw-label">' .
+                       Xml::label( $this->msg( 'allmessages-prefix' )->text(), 'mw-allmessages-form-prefix' ) .
+                       "</td>\n
+                       <td class=\"mw-input\">" .
+                       Xml::input(
+                               'prefix',
+                               20,
+                               str_replace( '_', ' ', $this->displayPrefix ),
+                               [ 'id' => 'mw-allmessages-form-prefix' ]
+                       ) .
+                       "</td>\n
+                       </tr>
+                       <tr>\n
+                       <td class='mw-label'>" .
+                       $this->msg( 'allmessages-filter' )->escaped() .
+                       "</td>\n
+                               <td class='mw-input'>" .
+                       Xml::radioLabel( $this->msg( 'allmessages-filter-unmodified' )->text(),
+                               'filter',
+                               'unmodified',
+                               'mw-allmessages-form-filter-unmodified',
+                               ( $this->filter === 'unmodified' )
+                       ) .
+                       Xml::radioLabel( $this->msg( 'allmessages-filter-all' )->text(),
+                               'filter',
+                               'all',
+                               'mw-allmessages-form-filter-all',
+                               ( $this->filter === 'all' )
+                       ) .
+                       Xml::radioLabel( $this->msg( 'allmessages-filter-modified' )->text(),
+                               'filter',
+                               'modified',
+                               'mw-allmessages-form-filter-modified',
+                               ( $this->filter === 'modified' )
+                       ) .
+                       "</td>\n
+                       </tr>
+                       <tr>\n
+                               <td class=\"mw-label\">" . $langSelect[0] . "</td>\n
+                               <td class=\"mw-input\">" . $langSelect[1] . "</td>\n
+                       </tr>" .
+
+                       '<tr>
+                               <td class="mw-label">' .
+                       Xml::label( $this->msg( 'table_pager_limit_label' )->text(), 'mw-table_pager_limit_label' ) .
+                       '</td>
+                       <td class="mw-input">' .
+                       $this->getLimitSelect( [ 'id' => 'mw-table_pager_limit_label' ] ) .
+                       '</td>
+                       <tr>
+                               <td></td>
+                               <td>' .
+                       Xml::submitButton( $this->msg( 'allmessages-filter-submit' )->text() ) .
+                       "</td>\n
+                       </tr>" .
+
+                       Xml::closeElement( 'table' ) .
+                       $this->getHiddenFields( [ 'title', 'prefix', 'filter', 'lang', 'limit' ] ) .
+                       Xml::closeElement( 'fieldset' ) .
+                       Xml::closeElement( 'form' );
+
+               return $out;
+       }
+
+       function getAllMessages( $descending ) {
+               $messageNames = Language::getLocalisationCache()->getSubitemList( 'en', 'messages' );
+
+               // Normalise message names so they look like page titles and sort correctly - T86139
+               $messageNames = array_map( [ $this->lang, 'ucfirst' ], $messageNames );
+
+               if ( $descending ) {
+                       rsort( $messageNames );
+               } else {
+                       asort( $messageNames );
+               }
+
+               return $messageNames;
+       }
+
+       /**
+        * Determine which of the MediaWiki and MediaWiki_talk namespace pages exist.
+        * Returns array( 'pages' => ..., 'talks' => ... ), where the subarrays have
+        * an entry for each existing page, with the key being the message name and
+        * value arbitrary.
+        *
+        * @param array $messageNames
+        * @param string $langcode What language code
+        * @param bool $foreign Whether the $langcode is not the content language
+        * @return array A 'pages' and 'talks' array with the keys of existing pages
+        */
+       public static function getCustomisedStatuses( $messageNames, $langcode = 'en', $foreign = false ) {
+               // FIXME: This function should be moved to Language:: or something.
+
+               $dbr = wfGetDB( DB_SLAVE );
+               $res = $dbr->select( 'page',
+                       [ 'page_namespace', 'page_title' ],
+                       [ 'page_namespace' => [ NS_MEDIAWIKI, NS_MEDIAWIKI_TALK ] ],
+                       __METHOD__,
+                       [ 'USE INDEX' => 'name_title' ]
+               );
+               $xNames = array_flip( $messageNames );
+
+               $pageFlags = $talkFlags = [];
+
+               foreach ( $res as $s ) {
+                       $exists = false;
+
+                       if ( $foreign ) {
+                               $titleParts = explode( '/', $s->page_title );
+                               if ( count( $titleParts ) === 2 &&
+                                       $langcode === $titleParts[1] &&
+                                       isset( $xNames[$titleParts[0]] )
+                               ) {
+                                       $exists = $titleParts[0];
+                               }
+                       } elseif ( isset( $xNames[$s->page_title] ) ) {
+                               $exists = $s->page_title;
+                       }
+
+                       $title = Title::newFromRow( $s );
+                       if ( $exists && $title->inNamespace( NS_MEDIAWIKI ) ) {
+                               $pageFlags[$exists] = true;
+                       } elseif ( $exists && $title->inNamespace( NS_MEDIAWIKI_TALK ) ) {
+                               $talkFlags[$exists] = true;
+                       }
+               }
+
+               return [ 'pages' => $pageFlags, 'talks' => $talkFlags ];
+       }
+
+       /**
+        *  This function normally does a database query to get the results; we need
+        * to make a pretend result using a FakeResultWrapper.
+        * @param string $offset
+        * @param int $limit
+        * @param bool $descending
+        * @return FakeResultWrapper
+        */
+       function reallyDoQuery( $offset, $limit, $descending ) {
+               $result = new FakeResultWrapper( [] );
+
+               $messageNames = $this->getAllMessages( $descending );
+               $statuses = self::getCustomisedStatuses( $messageNames, $this->langcode, $this->foreign );
+
+               $count = 0;
+               foreach ( $messageNames as $key ) {
+                       $customised = isset( $statuses['pages'][$key] );
+                       if ( $customised !== $this->custom &&
+                               ( $descending && ( $key < $offset || !$offset ) || !$descending && $key > $offset ) &&
+                               ( ( $this->prefix && preg_match( $this->prefix, $key ) ) || $this->prefix === false )
+                       ) {
+                               $actual = wfMessage( $key )->inLanguage( $this->langcode )->plain();
+                               $default = wfMessage( $key )->inLanguage( $this->langcode )->useDatabase( false )->plain();
+                               $result->result[] = [
+                                       'am_title' => $key,
+                                       'am_actual' => $actual,
+                                       'am_default' => $default,
+                                       'am_customised' => $customised,
+                                       'am_talk_exists' => isset( $statuses['talks'][$key] )
+                               ];
+                               $count++;
+                       }
+
+                       if ( $count === $limit ) {
+                               break;
+                       }
+               }
+
+               return $result;
+       }
+
+       function getStartBody() {
+               $tableClass = $this->getTableClass();
+               return Xml::openElement( 'table', [
+                       'class' => "mw-datatable $tableClass",
+                       'id' => 'mw-allmessagestable'
+               ] ) .
+               "\n" .
+               "<thead><tr>
+                               <th rowspan=\"2\">" .
+               $this->msg( 'allmessagesname' )->escaped() . "
+                               </th>
+                               <th>" .
+               $this->msg( 'allmessagesdefault' )->escaped() .
+               "</th>
+                       </tr>\n
+                       <tr>
+                               <th>" .
+               $this->msg( 'allmessagescurrent' )->escaped() .
+               "</th>
+                       </tr></thead><tbody>\n";
+       }
+
+       function formatValue( $field, $value ) {
+               switch ( $field ) {
+                       case 'am_title' :
+                               $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
+                               $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
+                               $translation = Linker::makeExternalLink(
+                                       'https://translatewiki.net/w/i.php?' . wfArrayToCgi( [
+                                               'title' => 'Special:SearchTranslations',
+                                               'group' => 'mediawiki',
+                                               'grouppath' => 'mediawiki',
+                                               'query' => 'language:' . $this->getLanguage()->getCode() . '^25 ' .
+                                                       'messageid:"MediaWiki:' . $value . '"^10 "' .
+                                                       $this->msg( $value )->inLanguage( 'en' )->plain() . '"'
+                                       ] ),
+                                       $this->msg( 'allmessages-filter-translate' )->text()
+                               );
+
+                               if ( $this->mCurrentRow->am_customised ) {
+                                       $title = Linker::linkKnown( $title, $this->getLanguage()->lcfirst( $value ) );
+                               } else {
+                                       $title = Linker::link(
+                                               $title,
+                                               $this->getLanguage()->lcfirst( $value ),
+                                               [],
+                                               [],
+                                               [ 'broken' ]
+                                       );
+                               }
+                               if ( $this->mCurrentRow->am_talk_exists ) {
+                                       $talk = Linker::linkKnown( $talk, $this->talk );
+                               } else {
+                                       $talk = Linker::link(
+                                               $talk,
+                                               $this->talk,
+                                               [],
+                                               [],
+                                               [ 'broken' ]
+                                       );
+                               }
+
+                               return $title . ' ' .
+                               $this->msg( 'parentheses' )->rawParams( $talk )->escaped() .
+                               ' ' .
+                               $this->msg( 'parentheses' )->rawParams( $translation )->escaped();
+
+                       case 'am_default' :
+                       case 'am_actual' :
+                               return Sanitizer::escapeHtmlAllowEntities( $value );
+               }
+
+               return '';
+       }
+
+       function formatRow( $row ) {
+               // Do all the normal stuff
+               $s = parent::formatRow( $row );
+
+               // But if there's a customised message, add that too.
+               if ( $row->am_customised ) {
+                       $s .= Xml::openElement( 'tr', $this->getRowAttrs( $row, true ) );
+                       $formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) );
+
+                       if ( $formatted === '' ) {
+                               $formatted = '&#160;';
+                       }
+
+                       $s .= Xml::tags( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted )
+                               . "</tr>\n";
+               }
+
+               return $s;
+       }
+
+       function getRowAttrs( $row, $isSecond = false ) {
+               $arr = [];
+
+               if ( $row->am_customised ) {
+                       $arr['class'] = 'allmessages-customised';
+               }
+
+               if ( !$isSecond ) {
+                       $arr['id'] = Sanitizer::escapeId( 'msg_' . $this->getLanguage()->lcfirst( $row->am_title ) );
+               }
+
+               return $arr;
+       }
+
+       function getCellAttrs( $field, $value ) {
+               if ( $this->mCurrentRow->am_customised && $field === 'am_title' ) {
+                       return [ 'rowspan' => '2', 'class' => $field ];
+               } elseif ( $field === 'am_title' ) {
+                       return [ 'class' => $field ];
+               } else {
+                       return [
+                               'lang' => $this->lang->getHtmlCode(),
+                               'dir' => $this->lang->getDir(),
+                               'class' => $field
+                       ];
+               }
+       }
+
+       // This is not actually used, as getStartBody is overridden above
+       function getFieldNames() {
+               return [
+                       'am_title' => $this->msg( 'allmessagesname' )->text(),
+                       'am_default' => $this->msg( 'allmessagesdefault' )->text()
+               ];
+       }
+
+       function getTitle() {
+               return SpecialPage::getTitleFor( 'Allmessages', false );
+       }
+
+       function isFieldSortable( $x ) {
+               return false;
+       }
+
+       function getDefaultSort() {
+               return '';
+       }
+
+       function getQueryInfo() {
+               return '';
+       }
+
+}
diff --git a/includes/specials/pagers/BlockListPager.php b/includes/specials/pagers/BlockListPager.php
new file mode 100644 (file)
index 0000000..d822976
--- /dev/null
@@ -0,0 +1,282 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * @ingroup Pager
+ */
+class BlockListPager extends TablePager {
+
+       protected $conds;
+       protected $page;
+
+       /**
+        * @param SpecialPage $page
+        * @param array $conds
+        */
+       function __construct( $page, $conds ) {
+               $this->page = $page;
+               $this->conds = $conds;
+               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
+               parent::__construct( $page->getContext() );
+       }
+
+       function getFieldNames() {
+               static $headers = null;
+
+               if ( $headers === null ) {
+                       $headers = [
+                               'ipb_timestamp' => 'blocklist-timestamp',
+                               'ipb_target' => 'blocklist-target',
+                               'ipb_expiry' => 'blocklist-expiry',
+                               'ipb_by' => 'blocklist-by',
+                               'ipb_params' => 'blocklist-params',
+                               'ipb_reason' => 'blocklist-reason',
+                       ];
+                       foreach ( $headers as $key => $val ) {
+                               $headers[$key] = $this->msg( $val )->text();
+                       }
+               }
+
+               return $headers;
+       }
+
+       function formatValue( $name, $value ) {
+               static $msg = null;
+               if ( $msg === null ) {
+                       $keys = [
+                               'anononlyblock',
+                               'createaccountblock',
+                               'noautoblockblock',
+                               'emailblock',
+                               'blocklist-nousertalk',
+                               'unblocklink',
+                               'change-blocklink',
+                       ];
+
+                       foreach ( $keys as $key ) {
+                               $msg[$key] = $this->msg( $key )->escaped();
+                       }
+               }
+
+               /** @var $row object */
+               $row = $this->mCurrentRow;
+
+               $language = $this->getLanguage();
+
+               $formatted = '';
+
+               switch ( $name ) {
+                       case 'ipb_timestamp':
+                               $formatted = htmlspecialchars( $language->userTimeAndDate( $value, $this->getUser() ) );
+                               break;
+
+                       case 'ipb_target':
+                               if ( $row->ipb_auto ) {
+                                       $formatted = $this->msg( 'autoblockid', $row->ipb_id )->parse();
+                               } else {
+                                       list( $target, $type ) = Block::parseTarget( $row->ipb_address );
+                                       switch ( $type ) {
+                                               case Block::TYPE_USER:
+                                               case Block::TYPE_IP:
+                                                       $formatted = Linker::userLink( $target->getId(), $target );
+                                                       $formatted .= Linker::userToolLinks(
+                                                               $target->getId(),
+                                                               $target,
+                                                               false,
+                                                               Linker::TOOL_LINKS_NOBLOCK
+                                                       );
+                                                       break;
+                                               case Block::TYPE_RANGE:
+                                                       $formatted = htmlspecialchars( $target );
+                                       }
+                               }
+                               break;
+
+                       case 'ipb_expiry':
+                               $formatted = htmlspecialchars( $language->formatExpiry(
+                                       $value,
+                                       /* User preference timezone */true
+                               ) );
+                               if ( $this->getUser()->isAllowed( 'block' ) ) {
+                                       if ( $row->ipb_auto ) {
+                                               $links[] = Linker::linkKnown(
+                                                       SpecialPage::getTitleFor( 'Unblock' ),
+                                                       $msg['unblocklink'],
+                                                       [],
+                                                       [ 'wpTarget' => "#{$row->ipb_id}" ]
+                                               );
+                                       } else {
+                                               $links[] = Linker::linkKnown(
+                                                       SpecialPage::getTitleFor( 'Unblock', $row->ipb_address ),
+                                                       $msg['unblocklink']
+                                               );
+                                               $links[] = Linker::linkKnown(
+                                                       SpecialPage::getTitleFor( 'Block', $row->ipb_address ),
+                                                       $msg['change-blocklink']
+                                               );
+                                       }
+                                       $formatted .= ' ' . Html::rawElement(
+                                                       'span',
+                                                       [ 'class' => 'mw-blocklist-actions' ],
+                                                       $this->msg( 'parentheses' )->rawParams(
+                                                               $language->pipeList( $links ) )->escaped()
+                                               );
+                               }
+                               if ( $value !== 'infinity' ) {
+                                       $timestamp = new MWTimestamp( $value );
+                                       $formatted .= '<br />' . $this->msg(
+                                               'ipb-blocklist-duration-left',
+                                               $language->formatDuration(
+                                                       $timestamp->getTimestamp() - time(),
+                                                       // reasonable output
+                                                       [
+                                                               'minutes',
+                                                               'hours',
+                                                               'days',
+                                                               'years',
+                                                       ]
+                                               )
+                                       )->escaped();
+                               }
+                               break;
+
+                       case 'ipb_by':
+                               if ( isset( $row->by_user_name ) ) {
+                                       $formatted = Linker::userLink( $value, $row->by_user_name );
+                                       $formatted .= Linker::userToolLinks( $value, $row->by_user_name );
+                               } else {
+                                       $formatted = htmlspecialchars( $row->ipb_by_text ); // foreign user?
+                               }
+                               break;
+
+                       case 'ipb_reason':
+                               $formatted = Linker::formatComment( $value );
+                               break;
+
+                       case 'ipb_params':
+                               $properties = [];
+                               if ( $row->ipb_anon_only ) {
+                                       $properties[] = $msg['anononlyblock'];
+                               }
+                               if ( $row->ipb_create_account ) {
+                                       $properties[] = $msg['createaccountblock'];
+                               }
+                               if ( $row->ipb_user && !$row->ipb_enable_autoblock ) {
+                                       $properties[] = $msg['noautoblockblock'];
+                               }
+
+                               if ( $row->ipb_block_email ) {
+                                       $properties[] = $msg['emailblock'];
+                               }
+
+                               if ( !$row->ipb_allow_usertalk ) {
+                                       $properties[] = $msg['blocklist-nousertalk'];
+                               }
+
+                               $formatted = $language->commaList( $properties );
+                               break;
+
+                       default:
+                               $formatted = "Unable to format $name";
+                               break;
+               }
+
+               return $formatted;
+       }
+
+       function getQueryInfo() {
+               $info = [
+                       'tables' => [ 'ipblocks', 'user' ],
+                       'fields' => [
+                               'ipb_id',
+                               'ipb_address',
+                               'ipb_user',
+                               'ipb_by',
+                               'ipb_by_text',
+                               'by_user_name' => 'user_name',
+                               'ipb_reason',
+                               'ipb_timestamp',
+                               'ipb_auto',
+                               'ipb_anon_only',
+                               'ipb_create_account',
+                               'ipb_enable_autoblock',
+                               'ipb_expiry',
+                               'ipb_range_start',
+                               'ipb_range_end',
+                               'ipb_deleted',
+                               'ipb_block_email',
+                               'ipb_allow_usertalk',
+                       ],
+                       'conds' => $this->conds,
+                       'join_conds' => [ 'user' => [ 'LEFT JOIN', 'user_id = ipb_by' ] ]
+               ];
+
+               # Filter out any expired blocks
+               $db = $this->getDatabase();
+               $info['conds'][] = 'ipb_expiry > ' . $db->addQuotes( $db->timestamp() );
+
+               # Is the user allowed to see hidden blocks?
+               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+                       $info['conds']['ipb_deleted'] = 0;
+               }
+
+               return $info;
+       }
+
+       protected function getTableClass() {
+               return parent::getTableClass() . ' mw-blocklist';
+       }
+
+       function getIndexField() {
+               return 'ipb_timestamp';
+       }
+
+       function getDefaultSort() {
+               return 'ipb_timestamp';
+       }
+
+       function isFieldSortable( $name ) {
+               return false;
+       }
+
+       /**
+        * Do a LinkBatch query to minimise database load when generating all these links
+        * @param ResultWrapper $result
+        */
+       function preprocessResults( $result ) {
+               # Do a link batch query
+               $lb = new LinkBatch;
+               $lb->setCaller( __METHOD__ );
+
+               foreach ( $result as $row ) {
+                       $lb->add( NS_USER, $row->ipb_address );
+                       $lb->add( NS_USER_TALK, $row->ipb_address );
+
+                       if ( isset( $row->by_user_name ) ) {
+                               $lb->add( NS_USER, $row->by_user_name );
+                               $lb->add( NS_USER_TALK, $row->by_user_name );
+                       }
+               }
+
+               $lb->execute();
+       }
+
+}
diff --git a/includes/specials/pagers/CategoryPager.php b/includes/specials/pagers/CategoryPager.php
new file mode 100644 (file)
index 0000000..fd2ac1f
--- /dev/null
@@ -0,0 +1,126 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * TODO: Allow sorting by count.  We need to have a unique index to do this
+ * properly.
+ *
+ * @ingroup Pager
+ */
+class CategoryPager extends AlphabeticPager {
+
+       /**
+        * @var PageLinkRenderer
+        */
+       protected $linkRenderer;
+
+       /**
+        * @param IContextSource $context
+        * @param string $from
+        * @param PageLinkRenderer $linkRenderer
+        */
+       public function __construct( IContextSource $context, $from, PageLinkRenderer $linkRenderer
+       ) {
+               parent::__construct( $context );
+               $from = str_replace( ' ', '_', $from );
+               if ( $from !== '' ) {
+                       $from = Title::capitalize( $from, NS_CATEGORY );
+                       $this->setOffset( $from );
+                       $this->setIncludeOffset( true );
+               }
+
+               $this->linkRenderer = $linkRenderer;
+       }
+
+       function getQueryInfo() {
+               return [
+                       'tables' => [ 'category' ],
+                       'fields' => [ 'cat_title', 'cat_pages' ],
+                       'conds' => [ 'cat_pages > 0' ],
+                       'options' => [ 'USE INDEX' => 'cat_title' ],
+               ];
+       }
+
+       function getIndexField() {
+#              return array( 'abc' => 'cat_title', 'count' => 'cat_pages' );
+               return 'cat_title';
+       }
+
+       function getDefaultQuery() {
+               parent::getDefaultQuery();
+               unset( $this->mDefaultQuery['from'] );
+
+               return $this->mDefaultQuery;
+       }
+
+#      protected function getOrderTypeMessages() {
+#              return array( 'abc' => 'special-categories-sort-abc',
+#                      'count' => 'special-categories-sort-count' );
+#      }
+
+       protected function getDefaultDirections() {
+#              return array( 'abc' => false, 'count' => true );
+               return false;
+       }
+
+       /* Override getBody to apply LinksBatch on resultset before actually outputting anything. */
+       public function getBody() {
+               $batch = new LinkBatch;
+
+               $this->mResult->rewind();
+
+               foreach ( $this->mResult as $row ) {
+                       $batch->addObj( Title::makeTitleSafe( NS_CATEGORY, $row->cat_title ) );
+               }
+               $batch->execute();
+               $this->mResult->rewind();
+
+               return parent::getBody();
+       }
+
+       function formatRow( $result ) {
+               $title = new TitleValue( NS_CATEGORY, $result->cat_title );
+               $text = $title->getText();
+               $link = $this->linkRenderer->renderHtmlLink( $title, $text );
+
+               $count = $this->msg( 'nmembers' )->numParams( $result->cat_pages )->escaped();
+               return Html::rawElement( 'li', null, $this->getLanguage()->specialList( $link, $count ) ) . "\n";
+       }
+
+       public function getStartForm( $from ) {
+               return Xml::tags(
+                       'form',
+                       [ 'method' => 'get', 'action' => wfScript() ],
+                       Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) .
+                       Xml::fieldset(
+                               $this->msg( 'categories' )->text(),
+                               Xml::inputLabel(
+                                       $this->msg( 'categoriesfrom' )->text(),
+                                       'from', 'from', 20, $from, [ 'class' => 'mw-ui-input-inline' ] ) .
+                               ' ' .
+                               Html::submitButton(
+                                       $this->msg( 'categories-submit' )->text(),
+                                       [], [ 'mw-ui-progressive' ]
+                               )
+                       )
+               );
+       }
+}
diff --git a/includes/specials/pagers/ContribsPager.php b/includes/specials/pagers/ContribsPager.php
new file mode 100644 (file)
index 0000000..d90c37b
--- /dev/null
@@ -0,0 +1,526 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * Pager for Special:Contributions
+ * @ingroup Pager
+ */
+class ContribsPager extends ReverseChronologicalPager {
+
+       public $mDefaultDirection = IndexPager::DIR_DESCENDING;
+       public $messages;
+       public $target;
+       public $namespace = '';
+       public $mDb;
+       public $preventClickjacking = false;
+
+       /** @var IDatabase */
+       public $mDbSecondary;
+
+       /**
+        * @var array
+        */
+       protected $mParentLens;
+
+       function __construct( IContextSource $context, array $options ) {
+               parent::__construct( $context );
+
+               $msgs = [
+                       'diff',
+                       'hist',
+                       'pipe-separator',
+                       'uctop'
+               ];
+
+               foreach ( $msgs as $msg ) {
+                       $this->messages[$msg] = $this->msg( $msg )->escaped();
+               }
+
+               $this->target = isset( $options['target'] ) ? $options['target'] : '';
+               $this->contribs = isset( $options['contribs'] ) ? $options['contribs'] : 'users';
+               $this->namespace = isset( $options['namespace'] ) ? $options['namespace'] : '';
+               $this->tagFilter = isset( $options['tagfilter'] ) ? $options['tagfilter'] : false;
+               $this->nsInvert = isset( $options['nsInvert'] ) ? $options['nsInvert'] : false;
+               $this->associated = isset( $options['associated'] ) ? $options['associated'] : false;
+
+               $this->deletedOnly = !empty( $options['deletedOnly'] );
+               $this->topOnly = !empty( $options['topOnly'] );
+               $this->newOnly = !empty( $options['newOnly'] );
+
+               $year = isset( $options['year'] ) ? $options['year'] : false;
+               $month = isset( $options['month'] ) ? $options['month'] : false;
+               $this->getDateCond( $year, $month );
+
+               // Most of this code will use the 'contributions' group DB, which can map to slaves
+               // with extra user based indexes or partioning by user. The additional metadata
+               // queries should use a regular slave since the lookup pattern is not all by user.
+               $this->mDbSecondary = wfGetDB( DB_SLAVE ); // any random slave
+               $this->mDb = wfGetDB( DB_SLAVE, 'contributions' );
+       }
+
+       function getDefaultQuery() {
+               $query = parent::getDefaultQuery();
+               $query['target'] = $this->target;
+
+               return $query;
+       }
+
+       /**
+        * This method basically executes the exact same code as the parent class, though with
+        * a hook added, to allow extensions to add additional queries.
+        *
+        * @param string $offset Index offset, inclusive
+        * @param int $limit Exact query limit
+        * @param bool $descending Query direction, false for ascending, true for descending
+        * @return ResultWrapper
+        */
+       function reallyDoQuery( $offset, $limit, $descending ) {
+               list( $tables, $fields, $conds, $fname, $options, $join_conds ) = $this->buildQueryInfo(
+                       $offset,
+                       $limit,
+                       $descending
+               );
+
+               /*
+                * This hook will allow extensions to add in additional queries, so they can get their data
+                * in My Contributions as well. Extensions should append their results to the $data array.
+                *
+                * Extension queries have to implement the navbar requirement as well. They should
+                * - have a column aliased as $pager->getIndexField()
+                * - have LIMIT set
+                * - have a WHERE-clause that compares the $pager->getIndexField()-equivalent column to the offset
+                * - have the ORDER BY specified based upon the details provided by the navbar
+                *
+                * See includes/Pager.php buildQueryInfo() method on how to build LIMIT, WHERE & ORDER BY
+                *
+                * &$data: an array of results of all contribs queries
+                * $pager: the ContribsPager object hooked into
+                * $offset: see phpdoc above
+                * $limit: see phpdoc above
+                * $descending: see phpdoc above
+                */
+               $data = [ $this->mDb->select(
+                       $tables, $fields, $conds, $fname, $options, $join_conds
+               ) ];
+               Hooks::run(
+                       'ContribsPager::reallyDoQuery',
+                       [ &$data, $this, $offset, $limit, $descending ]
+               );
+
+               $result = [];
+
+               // loop all results and collect them in an array
+               foreach ( $data as $query ) {
+                       foreach ( $query as $i => $row ) {
+                               // use index column as key, allowing us to easily sort in PHP
+                               $result[$row->{$this->getIndexField()} . "-$i"] = $row;
+                       }
+               }
+
+               // sort results
+               if ( $descending ) {
+                       ksort( $result );
+               } else {
+                       krsort( $result );
+               }
+
+               // enforce limit
+               $result = array_slice( $result, 0, $limit );
+
+               // get rid of array keys
+               $result = array_values( $result );
+
+               return new FakeResultWrapper( $result );
+       }
+
+       function getQueryInfo() {
+               list( $tables, $index, $userCond, $join_cond ) = $this->getUserCond();
+
+               $user = $this->getUser();
+               $conds = array_merge( $userCond, $this->getNamespaceCond() );
+
+               // Paranoia: avoid brute force searches (bug 17342)
+               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+                       $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0';
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
+                       $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::SUPPRESSED_USER ) .
+                               ' != ' . Revision::SUPPRESSED_USER;
+               }
+
+               # Don't include orphaned revisions
+               $join_cond['page'] = Revision::pageJoinCond();
+               # Get the current user name for accounts
+               $join_cond['user'] = Revision::userJoinCond();
+
+               $options = [];
+               if ( $index ) {
+                       $options['USE INDEX'] = [ 'revision' => $index ];
+               }
+
+               $queryInfo = [
+                       'tables' => $tables,
+                       'fields' => array_merge(
+                               Revision::selectFields(),
+                               Revision::selectUserFields(),
+                               [ 'page_namespace', 'page_title', 'page_is_new',
+                                       'page_latest', 'page_is_redirect', 'page_len' ]
+                       ),
+                       'conds' => $conds,
+                       'options' => $options,
+                       'join_conds' => $join_cond
+               ];
+
+               ChangeTags::modifyDisplayQuery(
+                       $queryInfo['tables'],
+                       $queryInfo['fields'],
+                       $queryInfo['conds'],
+                       $queryInfo['join_conds'],
+                       $queryInfo['options'],
+                       $this->tagFilter
+               );
+
+               Hooks::run( 'ContribsPager::getQueryInfo', [ &$this, &$queryInfo ] );
+
+               return $queryInfo;
+       }
+
+       function getUserCond() {
+               $condition = [];
+               $join_conds = [];
+               $tables = [ 'revision', 'page', 'user' ];
+               $index = false;
+               if ( $this->contribs == 'newbie' ) {
+                       $max = $this->mDb->selectField( 'user', 'max(user_id)', false, __METHOD__ );
+                       $condition[] = 'rev_user >' . (int)( $max - $max / 100 );
+                       # ignore local groups with the bot right
+                       # @todo FIXME: Global groups may have 'bot' rights
+                       $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' );
+                       if ( count( $groupsWithBotPermission ) ) {
+                               $tables[] = 'user_groups';
+                               $condition[] = 'ug_group IS NULL';
+                               $join_conds['user_groups'] = [
+                                       'LEFT JOIN', [
+                                               'ug_user = rev_user',
+                                               'ug_group' => $groupsWithBotPermission
+                                       ]
+                               ];
+                       }
+               } else {
+                       $uid = User::idFromName( $this->target );
+                       if ( $uid ) {
+                               $condition['rev_user'] = $uid;
+                               $index = 'user_timestamp';
+                       } else {
+                               $condition['rev_user_text'] = $this->target;
+                               $index = 'usertext_timestamp';
+                       }
+               }
+
+               if ( $this->deletedOnly ) {
+                       $condition[] = 'rev_deleted != 0';
+               }
+
+               if ( $this->topOnly ) {
+                       $condition[] = 'rev_id = page_latest';
+               }
+
+               if ( $this->newOnly ) {
+                       $condition[] = 'rev_parent_id = 0';
+               }
+
+               return [ $tables, $index, $condition, $join_conds ];
+       }
+
+       function getNamespaceCond() {
+               if ( $this->namespace !== '' ) {
+                       $selectedNS = $this->mDb->addQuotes( $this->namespace );
+                       $eq_op = $this->nsInvert ? '!=' : '=';
+                       $bool_op = $this->nsInvert ? 'AND' : 'OR';
+
+                       if ( !$this->associated ) {
+                               return [ "page_namespace $eq_op $selectedNS" ];
+                       }
+
+                       $associatedNS = $this->mDb->addQuotes(
+                               MWNamespace::getAssociated( $this->namespace )
+                       );
+
+                       return [
+                               "page_namespace $eq_op $selectedNS " .
+                               $bool_op .
+                               " page_namespace $eq_op $associatedNS"
+                       ];
+               }
+
+               return [];
+       }
+
+       function getIndexField() {
+               return 'rev_timestamp';
+       }
+
+       function doBatchLookups() {
+               # Do a link batch query
+               $this->mResult->seek( 0 );
+               $parentRevIds = [];
+               $this->mParentLens = [];
+               $batch = new LinkBatch();
+               # Give some pointers to make (last) links
+               foreach ( $this->mResult as $row ) {
+                       if ( isset( $row->rev_parent_id ) && $row->rev_parent_id ) {
+                               $parentRevIds[] = $row->rev_parent_id;
+                       }
+                       if ( isset( $row->rev_id ) ) {
+                               $this->mParentLens[$row->rev_id] = $row->rev_len;
+                               if ( $this->contribs === 'newbie' ) { // multiple users
+                                       $batch->add( NS_USER, $row->user_name );
+                                       $batch->add( NS_USER_TALK, $row->user_name );
+                               }
+                               $batch->add( $row->page_namespace, $row->page_title );
+                       }
+               }
+               # Fetch rev_len for revisions not already scanned above
+               $this->mParentLens += Revision::getParentLengths(
+                       $this->mDbSecondary,
+                       array_diff( $parentRevIds, array_keys( $this->mParentLens ) )
+               );
+               $batch->execute();
+               $this->mResult->seek( 0 );
+       }
+
+       /**
+        * @return string
+        */
+       function getStartBody() {
+               return "<ul class=\"mw-contributions-list\">\n";
+       }
+
+       /**
+        * @return string
+        */
+       function getEndBody() {
+               return "</ul>\n";
+       }
+
+       /**
+        * Generates each row in the contributions list.
+        *
+        * Contributions which are marked "top" are currently on top of the history.
+        * For these contributions, a [rollback] link is shown for users with roll-
+        * back privileges. The rollback link restores the most recent version that
+        * was not written by the target user.
+        *
+        * @todo This would probably look a lot nicer in a table.
+        * @param object $row
+        * @return string
+        */
+       function formatRow( $row ) {
+
+               $ret = '';
+               $classes = [];
+
+               /*
+                * There may be more than just revision rows. To make sure that we'll only be processing
+                * revisions here, let's _try_ to build a revision out of our row (without displaying
+                * notices though) and then trying to grab data from the built object. If we succeed,
+                * we're definitely dealing with revision data and we may proceed, if not, we'll leave it
+                * to extensions to subscribe to the hook to parse the row.
+                */
+               MediaWiki\suppressWarnings();
+               try {
+                       $rev = new Revision( $row );
+                       $validRevision = (bool)$rev->getId();
+               } catch ( Exception $e ) {
+                       $validRevision = false;
+               }
+               MediaWiki\restoreWarnings();
+
+               if ( $validRevision ) {
+                       $classes = [];
+
+                       $page = Title::newFromRow( $row );
+                       $link = Linker::link(
+                               $page,
+                               htmlspecialchars( $page->getPrefixedText() ),
+                               [ 'class' => 'mw-contributions-title' ],
+                               $page->isRedirect() ? [ 'redirect' => 'no' ] : []
+                       );
+                       # Mark current revisions
+                       $topmarktext = '';
+                       $user = $this->getUser();
+                       if ( $row->rev_id == $row->page_latest ) {
+                               $topmarktext .= '<span class="mw-uctop">' . $this->messages['uctop'] . '</span>';
+                               # Add rollback link
+                               if ( !$row->page_is_new && $page->quickUserCan( 'rollback', $user )
+                                       && $page->quickUserCan( 'edit', $user )
+                               ) {
+                                       $this->preventClickjacking();
+                                       $topmarktext .= ' ' . Linker::generateRollback( $rev, $this->getContext() );
+                               }
+                       }
+                       # Is there a visible previous revision?
+                       if ( $rev->userCan( Revision::DELETED_TEXT, $user ) && $rev->getParentId() !== 0 ) {
+                               $difftext = Linker::linkKnown(
+                                       $page,
+                                       $this->messages['diff'],
+                                       [],
+                                       [
+                                               'diff' => 'prev',
+                                               'oldid' => $row->rev_id
+                                       ]
+                               );
+                       } else {
+                               $difftext = $this->messages['diff'];
+                       }
+                       $histlink = Linker::linkKnown(
+                               $page,
+                               $this->messages['hist'],
+                               [],
+                               [ 'action' => 'history' ]
+                       );
+
+                       if ( $row->rev_parent_id === null ) {
+                               // For some reason rev_parent_id isn't populated for this row.
+                               // Its rumoured this is true on wikipedia for some revisions (bug 34922).
+                               // Next best thing is to have the total number of bytes.
+                               $chardiff = ' <span class="mw-changeslist-separator">. .</span> ';
+                               $chardiff .= Linker::formatRevisionSize( $row->rev_len );
+                               $chardiff .= ' <span class="mw-changeslist-separator">. .</span> ';
+                       } else {
+                               $parentLen = 0;
+                               if ( isset( $this->mParentLens[$row->rev_parent_id] ) ) {
+                                       $parentLen = $this->mParentLens[$row->rev_parent_id];
+                               }
+
+                               $chardiff = ' <span class="mw-changeslist-separator">. .</span> ';
+                               $chardiff .= ChangesList::showCharacterDifference(
+                                       $parentLen,
+                                       $row->rev_len,
+                                       $this->getContext()
+                               );
+                               $chardiff .= ' <span class="mw-changeslist-separator">. .</span> ';
+                       }
+
+                       $lang = $this->getLanguage();
+                       $comment = $lang->getDirMark() . Linker::revComment( $rev, false, true );
+                       $date = $lang->userTimeAndDate( $row->rev_timestamp, $user );
+                       if ( $rev->userCan( Revision::DELETED_TEXT, $user ) ) {
+                               $d = Linker::linkKnown(
+                                       $page,
+                                       htmlspecialchars( $date ),
+                                       [ 'class' => 'mw-changeslist-date' ],
+                                       [ 'oldid' => intval( $row->rev_id ) ]
+                               );
+                       } else {
+                               $d = htmlspecialchars( $date );
+                       }
+                       if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
+                               $d = '<span class="history-deleted">' . $d . '</span>';
+                       }
+
+                       # Show user names for /newbies as there may be different users.
+                       # Note that we already excluded rows with hidden user names.
+                       if ( $this->contribs == 'newbie' ) {
+                               $userlink = ' . . ' . $lang->getDirMark()
+                                       . Linker::userLink( $rev->getUser(), $rev->getUserText() );
+                               $userlink .= ' ' . $this->msg( 'parentheses' )->rawParams(
+                                               Linker::userTalkLink( $rev->getUser(), $rev->getUserText() ) )->escaped() . ' ';
+                       } else {
+                               $userlink = '';
+                       }
+
+                       if ( $rev->getParentId() === 0 ) {
+                               $nflag = ChangesList::flag( 'newpage' );
+                       } else {
+                               $nflag = '';
+                       }
+
+                       if ( $rev->isMinor() ) {
+                               $mflag = ChangesList::flag( 'minor' );
+                       } else {
+                               $mflag = '';
+                       }
+
+                       $del = Linker::getRevDeleteLink( $user, $rev, $page );
+                       if ( $del !== '' ) {
+                               $del .= ' ';
+                       }
+
+                       $diffHistLinks = $this->msg( 'parentheses' )
+                               ->rawParams( $difftext . $this->messages['pipe-separator'] . $histlink )
+                               ->escaped();
+                       $ret = "{$del}{$d} {$diffHistLinks}{$chardiff}{$nflag}{$mflag} ";
+                       $ret .= "{$link}{$userlink} {$comment} {$topmarktext}";
+
+                       # Denote if username is redacted for this edit
+                       if ( $rev->isDeleted( Revision::DELETED_USER ) ) {
+                               $ret .= " <strong>" .
+                                       $this->msg( 'rev-deleted-user-contribs' )->escaped() .
+                                       "</strong>";
+                       }
+
+                       # Tags, if any.
+                       list( $tagSummary, $newClasses ) = ChangeTags::formatSummaryRow(
+                               $row->ts_tags,
+                               'contributions',
+                               $this->getContext()
+                       );
+                       $classes = array_merge( $classes, $newClasses );
+                       $ret .= " $tagSummary";
+               }
+
+               // Let extensions add data
+               Hooks::run( 'ContributionsLineEnding', [ $this, &$ret, $row, &$classes ] );
+
+               if ( $classes === [] && $ret === '' ) {
+                       wfDebug( "Dropping Special:Contribution row that could not be formatted\n" );
+                       $ret = "<!-- Could not format Special:Contribution row. -->\n";
+               } else {
+                       $ret = Html::rawElement( 'li', [ 'class' => $classes ], $ret ) . "\n";
+               }
+
+               return $ret;
+       }
+
+       /**
+        * Overwrite Pager function and return a helpful comment
+        * @return string
+        */
+       function getSqlComment() {
+               if ( $this->namespace || $this->deletedOnly ) {
+                       // potentially slow, see CR r58153
+                       return 'contributions page filtered for namespace or RevisionDeleted edits';
+               } else {
+                       return 'contributions page unfiltered';
+               }
+       }
+
+       protected function preventClickjacking() {
+               $this->preventClickjacking = true;
+       }
+
+       /**
+        * @return bool
+        */
+       public function getPreventClickjacking() {
+               return $this->preventClickjacking;
+       }
+}
diff --git a/includes/specials/pagers/DeletedContribsPager.php b/includes/specials/pagers/DeletedContribsPager.php
new file mode 100644 (file)
index 0000000..f2421f8
--- /dev/null
@@ -0,0 +1,355 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * @ingroup Pager
+ */
+class DeletedContribsPager extends IndexPager {
+
+       public $mDefaultDirection = IndexPager::DIR_DESCENDING;
+       public $messages;
+       public $target;
+       public $namespace = '';
+       public $mDb;
+
+       /**
+        * @var string Navigation bar with paging links.
+        */
+       protected $mNavigationBar;
+
+       function __construct( IContextSource $context, $target, $namespace = false ) {
+               parent::__construct( $context );
+               $msgs = [ 'deletionlog', 'undeleteviewlink', 'diff' ];
+               foreach ( $msgs as $msg ) {
+                       $this->messages[$msg] = $this->msg( $msg )->escaped();
+               }
+               $this->target = $target;
+               $this->namespace = $namespace;
+               $this->mDb = wfGetDB( DB_SLAVE, 'contributions' );
+       }
+
+       function getDefaultQuery() {
+               $query = parent::getDefaultQuery();
+               $query['target'] = $this->target;
+
+               return $query;
+       }
+
+       function getQueryInfo() {
+               list( $index, $userCond ) = $this->getUserCond();
+               $conds = array_merge( $userCond, $this->getNamespaceCond() );
+               $user = $this->getUser();
+               // Paranoia: avoid brute force searches (bug 17792)
+               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+                       $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::DELETED_USER ) . ' = 0';
+               } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
+                       $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::SUPPRESSED_USER ) .
+                               ' != ' . Revision::SUPPRESSED_USER;
+               }
+
+               return [
+                       'tables' => [ 'archive' ],
+                       'fields' => [
+                               'ar_rev_id', 'ar_namespace', 'ar_title', 'ar_timestamp', 'ar_comment',
+                               'ar_minor_edit', 'ar_user', 'ar_user_text', 'ar_deleted'
+                       ],
+                       'conds' => $conds,
+                       'options' => [ 'USE INDEX' => $index ]
+               ];
+       }
+
+       /**
+        * This method basically executes the exact same code as the parent class, though with
+        * a hook added, to allow extensions to add additional queries.
+        *
+        * @param string $offset Index offset, inclusive
+        * @param int $limit Exact query limit
+        * @param bool $descending Query direction, false for ascending, true for descending
+        * @return ResultWrapper
+        */
+       function reallyDoQuery( $offset, $limit, $descending ) {
+               $data = [ parent::reallyDoQuery( $offset, $limit, $descending ) ];
+
+               // This hook will allow extensions to add in additional queries, nearly
+               // identical to ContribsPager::reallyDoQuery.
+               Hooks::run(
+                       'DeletedContribsPager::reallyDoQuery',
+                       [ &$data, $this, $offset, $limit, $descending ]
+               );
+
+               $result = [];
+
+               // loop all results and collect them in an array
+               foreach ( $data as $query ) {
+                       foreach ( $query as $i => $row ) {
+                               // use index column as key, allowing us to easily sort in PHP
+                               $result[$row->{$this->getIndexField()} . "-$i"] = $row;
+                       }
+               }
+
+               // sort results
+               if ( $descending ) {
+                       ksort( $result );
+               } else {
+                       krsort( $result );
+               }
+
+               // enforce limit
+               $result = array_slice( $result, 0, $limit );
+
+               // get rid of array keys
+               $result = array_values( $result );
+
+               return new FakeResultWrapper( $result );
+       }
+
+       function getUserCond() {
+               $condition = [];
+
+               $condition['ar_user_text'] = $this->target;
+               $index = 'usertext_timestamp';
+
+               return [ $index, $condition ];
+       }
+
+       function getIndexField() {
+               return 'ar_timestamp';
+       }
+
+       function getStartBody() {
+               return "<ul>\n";
+       }
+
+       function getEndBody() {
+               return "</ul>\n";
+       }
+
+       function getNavigationBar() {
+               if ( isset( $this->mNavigationBar ) ) {
+                       return $this->mNavigationBar;
+               }
+
+               $linkTexts = [
+                       'prev' => $this->msg( 'pager-newer-n' )->numParams( $this->mLimit )->escaped(),
+                       'next' => $this->msg( 'pager-older-n' )->numParams( $this->mLimit )->escaped(),
+                       'first' => $this->msg( 'histlast' )->escaped(),
+                       'last' => $this->msg( 'histfirst' )->escaped()
+               ];
+
+               $pagingLinks = $this->getPagingLinks( $linkTexts );
+               $limitLinks = $this->getLimitLinks();
+               $lang = $this->getLanguage();
+               $limits = $lang->pipeList( $limitLinks );
+
+               $firstLast = $lang->pipeList( [ $pagingLinks['first'], $pagingLinks['last'] ] );
+               $firstLast = $this->msg( 'parentheses' )->rawParams( $firstLast )->escaped();
+               $prevNext = $this->msg( 'viewprevnext' )
+                       ->rawParams(
+                               $pagingLinks['prev'],
+                               $pagingLinks['next'],
+                               $limits
+                       )->escaped();
+               $separator = $this->msg( 'word-separator' )->escaped();
+               $this->mNavigationBar = $firstLast . $separator . $prevNext;
+
+               return $this->mNavigationBar;
+       }
+
+       function getNamespaceCond() {
+               if ( $this->namespace !== '' ) {
+                       return [ 'ar_namespace' => (int)$this->namespace ];
+               } else {
+                       return [];
+               }
+       }
+
+       /**
+        * Generates each row in the contributions list.
+        *
+        * @todo This would probably look a lot nicer in a table.
+        * @param stdClass $row
+        * @return string
+        */
+       function formatRow( $row ) {
+               $ret = '';
+               $classes = [];
+
+               /*
+                * There may be more than just revision rows. To make sure that we'll only be processing
+                * revisions here, let's _try_ to build a revision out of our row (without displaying
+                * notices though) and then trying to grab data from the built object. If we succeed,
+                * we're definitely dealing with revision data and we may proceed, if not, we'll leave it
+                * to extensions to subscribe to the hook to parse the row.
+                */
+               MediaWiki\suppressWarnings();
+               try {
+                       $rev = Revision::newFromArchiveRow( $row );
+                       $validRevision = (bool)$rev->getId();
+               } catch ( Exception $e ) {
+                       $validRevision = false;
+               }
+               MediaWiki\restoreWarnings();
+
+               if ( $validRevision ) {
+                       $ret = $this->formatRevisionRow( $row );
+               }
+
+               // Let extensions add data
+               Hooks::run( 'DeletedContributionsLineEnding', [ $this, &$ret, $row, &$classes ] );
+
+               if ( $classes === [] && $ret === '' ) {
+                       wfDebug( "Dropping Special:DeletedContribution row that could not be formatted\n" );
+                       $ret = "<!-- Could not format Special:DeletedContribution row. -->\n";
+               } else {
+                       $ret = Html::rawElement( 'li', [ 'class' => $classes ], $ret ) . "\n";
+               }
+
+               return $ret;
+       }
+
+       /**
+        * Generates each row in the contributions list for archive entries.
+        *
+        * Contributions which are marked "top" are currently on top of the history.
+        * For these contributions, a [rollback] link is shown for users with sysop
+        * privileges. The rollback link restores the most recent version that was not
+        * written by the target user.
+        *
+        * @todo This would probably look a lot nicer in a table.
+        * @param stdClass $row
+        * @return string
+        */
+       function formatRevisionRow( $row ) {
+               $page = Title::makeTitle( $row->ar_namespace, $row->ar_title );
+
+               $rev = new Revision( [
+                       'title' => $page,
+                       'id' => $row->ar_rev_id,
+                       'comment' => $row->ar_comment,
+                       'user' => $row->ar_user,
+                       'user_text' => $row->ar_user_text,
+                       'timestamp' => $row->ar_timestamp,
+                       'minor_edit' => $row->ar_minor_edit,
+                       'deleted' => $row->ar_deleted,
+               ] );
+
+               $undelete = SpecialPage::getTitleFor( 'Undelete' );
+
+               $logs = SpecialPage::getTitleFor( 'Log' );
+               $dellog = Linker::linkKnown(
+                       $logs,
+                       $this->messages['deletionlog'],
+                       [],
+                       [
+                               'type' => 'delete',
+                               'page' => $page->getPrefixedText()
+                       ]
+               );
+
+               $reviewlink = Linker::linkKnown(
+                       SpecialPage::getTitleFor( 'Undelete', $page->getPrefixedDBkey() ),
+                       $this->messages['undeleteviewlink']
+               );
+
+               $user = $this->getUser();
+
+               if ( $user->isAllowed( 'deletedtext' ) ) {
+                       $last = Linker::linkKnown(
+                               $undelete,
+                               $this->messages['diff'],
+                               [],
+                               [
+                                       'target' => $page->getPrefixedText(),
+                                       'timestamp' => $rev->getTimestamp(),
+                                       'diff' => 'prev'
+                               ]
+                       );
+               } else {
+                       $last = $this->messages['diff'];
+               }
+
+               $comment = Linker::revComment( $rev );
+               $date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user );
+               $date = htmlspecialchars( $date );
+
+               if ( !$user->isAllowed( 'undelete' ) || !$rev->userCan( Revision::DELETED_TEXT, $user ) ) {
+                       $link = $date; // unusable link
+               } else {
+                       $link = Linker::linkKnown(
+                               $undelete,
+                               $date,
+                               [ 'class' => 'mw-changeslist-date' ],
+                               [
+                                       'target' => $page->getPrefixedText(),
+                                       'timestamp' => $rev->getTimestamp()
+                               ]
+                       );
+               }
+               // Style deleted items
+               if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
+                       $link = '<span class="history-deleted">' . $link . '</span>';
+               }
+
+               $pagelink = Linker::link(
+                       $page,
+                       null,
+                       [ 'class' => 'mw-changeslist-title' ]
+               );
+
+               if ( $rev->isMinor() ) {
+                       $mflag = ChangesList::flag( 'minor' );
+               } else {
+                       $mflag = '';
+               }
+
+               // Revision delete link
+               $del = Linker::getRevDeleteLink( $user, $rev, $page );
+               if ( $del ) {
+                       $del .= ' ';
+               }
+
+               $tools = Html::rawElement(
+                       'span',
+                       [ 'class' => 'mw-deletedcontribs-tools' ],
+                       $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList(
+                               [ $last, $dellog, $reviewlink ] ) )->escaped()
+               );
+
+               $separator = '<span class="mw-changeslist-separator">. .</span>';
+               $ret = "{$del}{$link} {$tools} {$separator} {$mflag} {$pagelink} {$comment}";
+
+               # Denote if username is redacted for this edit
+               if ( $rev->isDeleted( Revision::DELETED_USER ) ) {
+                       $ret .= " <strong>" . $this->msg( 'rev-deleted-user-contribs' )->escaped() . "</strong>";
+               }
+
+               return $ret;
+       }
+
+       /**
+        * Get the Database object in use
+        *
+        * @return IDatabase
+        */
+       public function getDatabase() {
+               return $this->mDb;
+       }
+}
diff --git a/includes/specials/pagers/ImageListPager.php b/includes/specials/pagers/ImageListPager.php
new file mode 100644 (file)
index 0000000..45fe5c4
--- /dev/null
@@ -0,0 +1,602 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * @ingroup Pager
+ */
+class ImageListPager extends TablePager {
+
+       protected $mFieldNames = null;
+
+       // Subclasses should override buildQueryConds instead of using $mQueryConds variable.
+       protected $mQueryConds = [];
+
+       protected $mUserName = null;
+
+       /**
+        * The relevant user
+        *
+        * @var User|null
+        */
+       protected $mUser = null;
+
+       protected $mSearch = '';
+
+       protected $mIncluding = false;
+
+       protected $mShowAll = false;
+
+       protected $mTableName = 'image';
+
+       function __construct( IContextSource $context, $userName = null, $search = '',
+               $including = false, $showAll = false
+       ) {
+               $this->setContext( $context );
+               $this->mIncluding = $including;
+               $this->mShowAll = $showAll;
+
+               if ( $userName !== null && $userName !== '' ) {
+                       $nt = Title::makeTitleSafe( NS_USER, $userName );
+                       if ( is_null( $nt ) ) {
+                               $this->outputUserDoesNotExist( $userName );
+                       } else {
+                               $this->mUserName = $nt->getText();
+                               $user = User::newFromName( $this->mUserName, false );
+                               if ( $user ) {
+                                       $this->mUser = $user;
+                               }
+                               if ( !$user || ( $user->isAnon() && !User::isIP( $user->getName() ) ) ) {
+                                       $this->outputUserDoesNotExist( $userName );
+                               }
+                       }
+               }
+
+               if ( $search !== '' && !$this->getConfig()->get( 'MiserMode' ) ) {
+                       $this->mSearch = $search;
+                       $nt = Title::newFromText( $this->mSearch );
+
+                       if ( $nt ) {
+                               $dbr = wfGetDB( DB_SLAVE );
+                               $this->mQueryConds[] = 'LOWER(img_name)' .
+                                       $dbr->buildLike( $dbr->anyString(),
+                                               strtolower( $nt->getDBkey() ), $dbr->anyString() );
+                       }
+               }
+
+               if ( !$including ) {
+                       if ( $this->getRequest()->getText( 'sort', 'img_date' ) == 'img_date' ) {
+                               $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
+                       } else {
+                               $this->mDefaultDirection = IndexPager::DIR_ASCENDING;
+                       }
+               } else {
+                       $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
+               }
+
+               parent::__construct( $context );
+       }
+
+       /**
+        * Get the user relevant to the ImageList
+        *
+        * @return User|null
+        */
+       function getRelevantUser() {
+               return $this->mUser;
+       }
+
+       /**
+        * Add a message to the output stating that the user doesn't exist
+        *
+        * @param string $userName Unescaped user name
+        */
+       protected function outputUserDoesNotExist( $userName ) {
+               $this->getOutput()->wrapWikiMsg(
+                       "<div class=\"mw-userpage-userdoesnotexist error\">\n$1\n</div>",
+                       [
+                               'listfiles-userdoesnotexist',
+                               wfEscapeWikiText( $userName ),
+                       ]
+               );
+       }
+
+       /**
+        * Build the where clause of the query.
+        *
+        * Replaces the older mQueryConds member variable.
+        * @param string $table Either "image" or "oldimage"
+        * @return array The query conditions.
+        */
+       protected function buildQueryConds( $table ) {
+               $prefix = $table === 'image' ? 'img' : 'oi';
+               $conds = [];
+
+               if ( !is_null( $this->mUserName ) ) {
+                       $conds[$prefix . '_user_text'] = $this->mUserName;
+               }
+
+               if ( $this->mSearch !== '' ) {
+                       $nt = Title::newFromText( $this->mSearch );
+                       if ( $nt ) {
+                               $dbr = wfGetDB( DB_SLAVE );
+                               $conds[] = 'LOWER(' . $prefix . '_name)' .
+                                       $dbr->buildLike( $dbr->anyString(),
+                                               strtolower( $nt->getDBkey() ), $dbr->anyString() );
+                       }
+               }
+
+               if ( $table === 'oldimage' ) {
+                       // Don't want to deal with revdel.
+                       // Future fixme: Show partial information as appropriate.
+                       // Would have to be careful about filtering by username when username is deleted.
+                       $conds['oi_deleted'] = 0;
+               }
+
+               // Add mQueryConds in case anyone was subclassing and using the old variable.
+               return $conds + $this->mQueryConds;
+       }
+
+       /**
+        * @return array
+        */
+       function getFieldNames() {
+               if ( !$this->mFieldNames ) {
+                       $this->mFieldNames = [
+                               'img_timestamp' => $this->msg( 'listfiles_date' )->text(),
+                               'img_name' => $this->msg( 'listfiles_name' )->text(),
+                               'thumb' => $this->msg( 'listfiles_thumb' )->text(),
+                               'img_size' => $this->msg( 'listfiles_size' )->text(),
+                       ];
+                       if ( is_null( $this->mUserName ) ) {
+                               // Do not show username if filtering by username
+                               $this->mFieldNames['img_user_text'] = $this->msg( 'listfiles_user' )->text();
+                       }
+                       // img_description down here, in order so that its still after the username field.
+                       $this->mFieldNames['img_description'] = $this->msg( 'listfiles_description' )->text();
+
+                       if ( !$this->getConfig()->get( 'MiserMode' ) && !$this->mShowAll ) {
+                               $this->mFieldNames['count'] = $this->msg( 'listfiles_count' )->text();
+                       }
+                       if ( $this->mShowAll ) {
+                               $this->mFieldNames['top'] = $this->msg( 'listfiles-latestversion' )->text();
+                       }
+               }
+
+               return $this->mFieldNames;
+       }
+
+       function isFieldSortable( $field ) {
+               if ( $this->mIncluding ) {
+                       return false;
+               }
+               $sortable = [ 'img_timestamp', 'img_name', 'img_size' ];
+               /* For reference, the indicies we can use for sorting are:
+                * On the image table: img_usertext_timestamp, img_size, img_timestamp
+                * On oldimage: oi_usertext_timestamp, oi_name_timestamp
+                *
+                * In particular that means we cannot sort by timestamp when not filtering
+                * by user and including old images in the results. Which is sad.
+                */
+               if ( $this->getConfig()->get( 'MiserMode' ) && !is_null( $this->mUserName ) ) {
+                       // If we're sorting by user, the index only supports sorting by time.
+                       if ( $field === 'img_timestamp' ) {
+                               return true;
+                       } else {
+                               return false;
+                       }
+               } elseif ( $this->getConfig()->get( 'MiserMode' )
+                       && $this->mShowAll /* && mUserName === null */
+               ) {
+                       // no oi_timestamp index, so only alphabetical sorting in this case.
+                       if ( $field === 'img_name' ) {
+                               return true;
+                       } else {
+                               return false;
+                       }
+               }
+
+               return in_array( $field, $sortable );
+       }
+
+       function getQueryInfo() {
+               // Hacky Hacky Hacky - I want to get query info
+               // for two different tables, without reimplementing
+               // the pager class.
+               $qi = $this->getQueryInfoReal( $this->mTableName );
+
+               return $qi;
+       }
+
+       /**
+        * Actually get the query info.
+        *
+        * This is to allow displaying both stuff from image and oldimage table.
+        *
+        * This is a bit hacky.
+        *
+        * @param string $table Either 'image' or 'oldimage'
+        * @return array Query info
+        */
+       protected function getQueryInfoReal( $table ) {
+               $prefix = $table === 'oldimage' ? 'oi' : 'img';
+
+               $tables = [ $table ];
+               $fields = array_keys( $this->getFieldNames() );
+
+               if ( $table === 'oldimage' ) {
+                       foreach ( $fields as $id => &$field ) {
+                               if ( substr( $field, 0, 4 ) !== 'img_' ) {
+                                       continue;
+                               }
+                               $field = $prefix . substr( $field, 3 ) . ' AS ' . $field;
+                       }
+                       $fields[array_search( 'top', $fields )] = "'no' AS top";
+               } else {
+                       if ( $this->mShowAll ) {
+                               $fields[array_search( 'top', $fields )] = "'yes' AS top";
+                       }
+               }
+               $fields[] = $prefix . '_user AS img_user';
+               $fields[array_search( 'thumb', $fields )] = $prefix . '_name AS thumb';
+
+               $options = $join_conds = [];
+
+               # Depends on $wgMiserMode
+               # Will also not happen if mShowAll is true.
+               if ( isset( $this->mFieldNames['count'] ) ) {
+                       $tables[] = 'oldimage';
+
+                       # Need to rewrite this one
+                       foreach ( $fields as &$field ) {
+                               if ( $field == 'count' ) {
+                                       $field = 'COUNT(oi_archive_name) AS count';
+                               }
+                       }
+                       unset( $field );
+
+                       $dbr = wfGetDB( DB_SLAVE );
+                       if ( $dbr->implicitGroupby() ) {
+                               $options = [ 'GROUP BY' => 'img_name' ];
+                       } else {
+                               $columnlist = preg_grep( '/^img/', array_keys( $this->getFieldNames() ) );
+                               $options = [ 'GROUP BY' => array_merge( [ 'img_user' ], $columnlist ) ];
+                       }
+                       $join_conds = [ 'oldimage' => [ 'LEFT JOIN', 'oi_name = img_name' ] ];
+               }
+
+               return [
+                       'tables' => $tables,
+                       'fields' => $fields,
+                       'conds' => $this->buildQueryConds( $table ),
+                       'options' => $options,
+                       'join_conds' => $join_conds
+               ];
+       }
+
+       /**
+        * Override reallyDoQuery to mix together two queries.
+        *
+        * @note $asc is named $descending in IndexPager base class. However
+        *   it is true when the order is ascending, and false when the order
+        *   is descending, so I renamed it to $asc here.
+        * @param int $offset
+        * @param int $limit
+        * @param bool $asc
+        * @return array
+        * @throws MWException
+        */
+       function reallyDoQuery( $offset, $limit, $asc ) {
+               $prevTableName = $this->mTableName;
+               $this->mTableName = 'image';
+               list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
+                       $this->buildQueryInfo( $offset, $limit, $asc );
+               $imageRes = $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
+               $this->mTableName = $prevTableName;
+
+               if ( !$this->mShowAll ) {
+                       return $imageRes;
+               }
+
+               $this->mTableName = 'oldimage';
+
+               # Hacky...
+               $oldIndex = $this->mIndexField;
+               if ( substr( $this->mIndexField, 0, 4 ) !== 'img_' ) {
+                       throw new MWException( "Expected to be sorting on an image table field" );
+               }
+               $this->mIndexField = 'oi_' . substr( $this->mIndexField, 4 );
+
+               list( $tables, $fields, $conds, $fname, $options, $join_conds ) =
+                       $this->buildQueryInfo( $offset, $limit, $asc );
+               $oldimageRes = $this->mDb->select( $tables, $fields, $conds, $fname, $options, $join_conds );
+
+               $this->mTableName = $prevTableName;
+               $this->mIndexField = $oldIndex;
+
+               return $this->combineResult( $imageRes, $oldimageRes, $limit, $asc );
+       }
+
+       /**
+        * Combine results from 2 tables.
+        *
+        * Note: This will throw away some results
+        *
+        * @param ResultWrapper $res1
+        * @param ResultWrapper $res2
+        * @param int $limit
+        * @param bool $ascending See note about $asc in $this->reallyDoQuery
+        * @return FakeResultWrapper $res1 and $res2 combined
+        */
+       protected function combineResult( $res1, $res2, $limit, $ascending ) {
+               $res1->rewind();
+               $res2->rewind();
+               $topRes1 = $res1->next();
+               $topRes2 = $res2->next();
+               $resultArray = [];
+               for ( $i = 0; $i < $limit && $topRes1 && $topRes2; $i++ ) {
+                       if ( strcmp( $topRes1->{$this->mIndexField}, $topRes2->{$this->mIndexField} ) > 0 ) {
+                               if ( !$ascending ) {
+                                       $resultArray[] = $topRes1;
+                                       $topRes1 = $res1->next();
+                               } else {
+                                       $resultArray[] = $topRes2;
+                                       $topRes2 = $res2->next();
+                               }
+                       } else {
+                               if ( !$ascending ) {
+                                       $resultArray[] = $topRes2;
+                                       $topRes2 = $res2->next();
+                               } else {
+                                       $resultArray[] = $topRes1;
+                                       $topRes1 = $res1->next();
+                               }
+                       }
+               }
+
+               // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
+               for ( ; $i < $limit && $topRes1; $i++ ) {
+                       // @codingStandardsIgnoreEnd
+                       $resultArray[] = $topRes1;
+                       $topRes1 = $res1->next();
+               }
+
+               // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
+               for ( ; $i < $limit && $topRes2; $i++ ) {
+                       // @codingStandardsIgnoreEnd
+                       $resultArray[] = $topRes2;
+                       $topRes2 = $res2->next();
+               }
+
+               return new FakeResultWrapper( $resultArray );
+       }
+
+       function getDefaultSort() {
+               if ( $this->mShowAll && $this->getConfig()->get( 'MiserMode' ) && is_null( $this->mUserName ) ) {
+                       // Unfortunately no index on oi_timestamp.
+                       return 'img_name';
+               } else {
+                       return 'img_timestamp';
+               }
+       }
+
+       function doBatchLookups() {
+               $userIds = [];
+               $this->mResult->seek( 0 );
+               foreach ( $this->mResult as $row ) {
+                       $userIds[] = $row->img_user;
+               }
+               # Do a link batch query for names and userpages
+               UserCache::singleton()->doQuery( $userIds, [ 'userpage' ], __METHOD__ );
+       }
+
+       /**
+        * @param string $field
+        * @param string $value
+        * @return Message|string|int The return type depends on the value of $field:
+        *   - thumb: string
+        *   - img_timestamp: string
+        *   - img_name: string
+        *   - img_user_text: string
+        *   - img_size: string
+        *   - img_description: string
+        *   - count: int
+        *   - top: Message
+        * @throws MWException
+        */
+       function formatValue( $field, $value ) {
+               switch ( $field ) {
+                       case 'thumb':
+                               $opt = [ 'time' => wfTimestamp( TS_MW, $this->mCurrentRow->img_timestamp ) ];
+                               $file = RepoGroup::singleton()->getLocalRepo()->findFile( $value, $opt );
+                               // If statement for paranoia
+                               if ( $file ) {
+                                       $thumb = $file->transform( [ 'width' => 180, 'height' => 360 ] );
+
+                                       return $thumb->toHtml( [ 'desc-link' => true ] );
+                               } else {
+                                       return htmlspecialchars( $value );
+                               }
+                       case 'img_timestamp':
+                               // We may want to make this a link to the "old" version when displaying old files
+                               return htmlspecialchars( $this->getLanguage()->userTimeAndDate( $value, $this->getUser() ) );
+                       case 'img_name':
+                               static $imgfile = null;
+                               if ( $imgfile === null ) {
+                                       $imgfile = $this->msg( 'imgfile' )->text();
+                               }
+
+                               // Weird files can maybe exist? Bug 22227
+                               $filePage = Title::makeTitleSafe( NS_FILE, $value );
+                               if ( $filePage ) {
+                                       $link = Linker::linkKnown(
+                                               $filePage,
+                                               htmlspecialchars( $filePage->getText() )
+                                       );
+                                       $download = Xml::element( 'a',
+                                               [ 'href' => wfLocalFile( $filePage )->getUrl() ],
+                                               $imgfile
+                                       );
+                                       $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped();
+
+                                       // Add delete links if allowed
+                                       // From https://github.com/Wikia/app/pull/3859
+                                       if ( $filePage->userCan( 'delete', $this->getUser() ) ) {
+                                               $deleteMsg = $this->msg( 'listfiles-delete' )->escaped();
+
+                                               $delete = Linker::linkKnown(
+                                                       $filePage, $deleteMsg, [], [ 'action' => 'delete' ]
+                                               );
+                                               $delete = $this->msg( 'parentheses' )->rawParams( $delete )->escaped();
+
+                                               return "$link $download $delete";
+                                       }
+
+                                       return "$link $download";
+                               } else {
+                                       return htmlspecialchars( $value );
+                               }
+                       case 'img_user_text':
+                               if ( $this->mCurrentRow->img_user ) {
+                                       $name = User::whoIs( $this->mCurrentRow->img_user );
+                                       $link = Linker::link(
+                                               Title::makeTitle( NS_USER, $name ),
+                                               htmlspecialchars( $name )
+                                       );
+                               } else {
+                                       $link = htmlspecialchars( $value );
+                               }
+
+                               return $link;
+                       case 'img_size':
+                               return htmlspecialchars( $this->getLanguage()->formatSize( $value ) );
+                       case 'img_description':
+                               return Linker::formatComment( $value );
+                       case 'count':
+                               return intval( $value ) + 1;
+                       case 'top':
+                               // Messages: listfiles-latestversion-yes, listfiles-latestversion-no
+                               return $this->msg( 'listfiles-latestversion-' . $value );
+                       default:
+                               throw new MWException( "Unknown field '$field'" );
+               }
+       }
+
+       function getForm() {
+               $fields = [];
+               $fields['limit'] = [
+                       'type' => 'select',
+                       'name' => 'limit',
+                       'label-message' => 'table_pager_limit_label',
+                       'options' => $this->getLimitSelectList(),
+                       'default' => $this->mLimit,
+               ];
+
+               if ( !$this->getConfig()->get( 'MiserMode' ) ) {
+                       $fields['ilsearch'] = [
+                               'type' => 'text',
+                               'name' => 'ilsearch',
+                               'id' => 'mw-ilsearch',
+                               'label-message' => 'listfiles_search_for',
+                               'default' => $this->mSearch,
+                               'size' => '40',
+                               'maxlength' => '255',
+                       ];
+               }
+
+               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
+               $fields['user'] = [
+                       'type' => 'text',
+                       'name' => 'user',
+                       'id' => 'mw-listfiles-user',
+                       'label-message' => 'username',
+                       'default' => $this->mUserName,
+                       'size' => '40',
+                       'maxlength' => '255',
+                       'cssclass' => 'mw-autocomplete-user', // used by mediawiki.userSuggest
+               ];
+
+               $fields['ilshowall'] = [
+                       'type' => 'check',
+                       'name' => 'ilshowall',
+                       'id' => 'mw-listfiles-show-all',
+                       'label-message' => 'listfiles-show-all',
+                       'default' => $this->mShowAll,
+               ];
+
+               $query = $this->getRequest()->getQueryValues();
+               unset( $query['title'] );
+               unset( $query['limit'] );
+               unset( $query['ilsearch'] );
+               unset( $query['ilshowall'] );
+               unset( $query['user'] );
+
+               $form = new HTMLForm( $fields, $this->getContext() );
+
+               $form->setMethod( 'get' );
+               $form->setTitle( $this->getTitle() );
+               $form->setId( 'mw-listfiles-form' );
+               $form->setWrapperLegendMsg( 'listfiles' );
+               $form->setSubmitTextMsg( 'table_pager_limit_submit' );
+               $form->addHiddenFields( $query );
+
+               $form->prepareForm();
+               $form->displayForm( '' );
+       }
+
+       protected function getTableClass() {
+               return parent::getTableClass() . ' listfiles';
+       }
+
+       protected function getNavClass() {
+               return parent::getNavClass() . ' listfiles_nav';
+       }
+
+       protected function getSortHeaderClass() {
+               return parent::getSortHeaderClass() . ' listfiles_sort';
+       }
+
+       function getPagingQueries() {
+               $queries = parent::getPagingQueries();
+               if ( !is_null( $this->mUserName ) ) {
+                       # Append the username to the query string
+                       foreach ( $queries as &$query ) {
+                               if ( $query !== false ) {
+                                       $query['user'] = $this->mUserName;
+                               }
+                       }
+               }
+
+               return $queries;
+       }
+
+       function getDefaultQuery() {
+               $queries = parent::getDefaultQuery();
+               if ( !isset( $queries['user'] ) && !is_null( $this->mUserName ) ) {
+                       $queries['user'] = $this->mUserName;
+               }
+
+               return $queries;
+       }
+
+       function getTitle() {
+               return SpecialPage::getTitleFor( 'Listfiles' );
+       }
+}
diff --git a/includes/specials/pagers/MergeHistoryPager.php b/includes/specials/pagers/MergeHistoryPager.php
new file mode 100644 (file)
index 0000000..0b9587c
--- /dev/null
@@ -0,0 +1,99 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * @ingroup Pager
+ */
+class MergeHistoryPager extends ReverseChronologicalPager {
+
+       /** @var SpecialMergeHistory */
+       public $mForm;
+
+       /** @var array */
+       public $mConds;
+
+       function __construct( SpecialMergeHistory $form, $conds, Title $source, Title $dest ) {
+               $this->mForm = $form;
+               $this->mConds = $conds;
+               $this->title = $source;
+               $this->articleID = $source->getArticleID();
+
+               $dbr = wfGetDB( DB_SLAVE );
+               $maxtimestamp = $dbr->selectField(
+                       'revision',
+                       'MIN(rev_timestamp)',
+                       [ 'rev_page' => $dest->getArticleID() ],
+                       __METHOD__
+               );
+               $this->maxTimestamp = $maxtimestamp;
+
+               parent::__construct( $form->getContext() );
+       }
+
+       function getStartBody() {
+               # Do a link batch query
+               $this->mResult->seek( 0 );
+               $batch = new LinkBatch();
+               # Give some pointers to make (last) links
+               $this->mForm->prevId = [];
+               foreach ( $this->mResult as $row ) {
+                       $batch->addObj( Title::makeTitleSafe( NS_USER, $row->user_name ) );
+                       $batch->addObj( Title::makeTitleSafe( NS_USER_TALK, $row->user_name ) );
+
+                       $rev_id = isset( $rev_id ) ? $rev_id : $row->rev_id;
+                       if ( $rev_id > $row->rev_id ) {
+                               $this->mForm->prevId[$rev_id] = $row->rev_id;
+                       } elseif ( $rev_id < $row->rev_id ) {
+                               $this->mForm->prevId[$row->rev_id] = $rev_id;
+                       }
+
+                       $rev_id = $row->rev_id;
+               }
+
+               $batch->execute();
+               $this->mResult->seek( 0 );
+
+               return '';
+       }
+
+       function formatRow( $row ) {
+               return $this->mForm->formatRevisionRow( $row );
+       }
+
+       function getQueryInfo() {
+               $conds = $this->mConds;
+               $conds['rev_page'] = $this->articleID;
+               $conds[] = "rev_timestamp < " . $this->mDb->addQuotes( $this->maxTimestamp );
+
+               return [
+                       'tables' => [ 'revision', 'page', 'user' ],
+                       'fields' => array_merge( Revision::selectFields(), Revision::selectUserFields() ),
+                       'conds' => $conds,
+                       'join_conds' => [
+                               'page' => Revision::pageJoinCond(),
+                               'user' => Revision::userJoinCond() ]
+               ];
+       }
+
+       function getIndexField() {
+               return 'rev_timestamp';
+       }
+}
diff --git a/includes/specials/pagers/NewFilesPager.php b/includes/specials/pagers/NewFilesPager.php
new file mode 100644 (file)
index 0000000..ae57736
--- /dev/null
@@ -0,0 +1,207 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * @ingroup Pager
+ */
+class NewFilesPager extends ReverseChronologicalPager {
+
+       /**
+        * @var ImageGallery
+        */
+       protected $gallery;
+
+       /**
+        * @var bool
+        */
+       protected $showBots;
+
+       /**
+        * @var bool
+        */
+       protected $hidePatrolled;
+
+       function __construct( IContextSource $context, $par = null ) {
+               $this->like = $context->getRequest()->getText( 'like' );
+               $this->showBots = $context->getRequest()->getBool( 'showbots', 0 );
+               $this->hidePatrolled = $context->getRequest()->getBool( 'hidepatrolled', 0 );
+               if ( is_numeric( $par ) ) {
+                       $this->setLimit( $par );
+               }
+
+               parent::__construct( $context );
+       }
+
+       function getQueryInfo() {
+               $conds = $jconds = [];
+               $tables = [ 'image' ];
+               $fields = [ 'img_name', 'img_user', 'img_timestamp' ];
+               $options = [];
+
+               if ( !$this->showBots ) {
+                       $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' );
+
+                       if ( count( $groupsWithBotPermission ) ) {
+                               $tables[] = 'user_groups';
+                               $conds[] = 'ug_group IS NULL';
+                               $jconds['user_groups'] = [
+                                       'LEFT JOIN',
+                                       [
+                                               'ug_group' => $groupsWithBotPermission,
+                                               'ug_user = img_user'
+                                       ]
+                               ];
+                       }
+               }
+
+               if ( $this->hidePatrolled ) {
+                       $tables[] = 'recentchanges';
+                       $conds['rc_type'] = RC_LOG;
+                       $conds['rc_log_type'] = 'upload';
+                       $conds['rc_patrolled'] = 0;
+                       $conds['rc_namespace'] = NS_FILE;
+                       $jconds['recentchanges'] = [
+                               'INNER JOIN',
+                               [
+                                       'rc_title = img_name',
+                                       'rc_user = img_user',
+                                       'rc_timestamp = img_timestamp'
+                               ]
+                       ];
+                       // We're ordering by img_timestamp, so we have to make sure MariaDB queries `image` first.
+                       // It sometimes decides to query `recentchanges` first and filesort the result set later
+                       // to get the right ordering. T124205 / https://mariadb.atlassian.net/browse/MDEV-8880
+                       $options[] = 'STRAIGHT_JOIN';
+               }
+
+               if ( !$this->getConfig()->get( 'MiserMode' ) && $this->like !== null ) {
+                       $dbr = wfGetDB( DB_SLAVE );
+                       $likeObj = Title::newFromText( $this->like );
+                       if ( $likeObj instanceof Title ) {
+                               $like = $dbr->buildLike(
+                                       $dbr->anyString(),
+                                       strtolower( $likeObj->getDBkey() ),
+                                       $dbr->anyString()
+                               );
+                               $conds[] = "LOWER(img_name) $like";
+                       }
+               }
+
+               $query = [
+                       'tables' => $tables,
+                       'fields' => $fields,
+                       'join_conds' => $jconds,
+                       'conds' => $conds,
+                       'options' => $options,
+               ];
+
+               return $query;
+       }
+
+       function getIndexField() {
+               return 'img_timestamp';
+       }
+
+       function getStartBody() {
+               if ( !$this->gallery ) {
+                       // Note that null for mode is taken to mean use default.
+                       $mode = $this->getRequest()->getVal( 'gallerymode', null );
+                       try {
+                               $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
+                       } catch ( Exception $e ) {
+                               // User specified something invalid, fallback to default.
+                               $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
+                       }
+               }
+
+               return '';
+       }
+
+       function getEndBody() {
+               return $this->gallery->toHTML();
+       }
+
+       function formatRow( $row ) {
+               $name = $row->img_name;
+               $user = User::newFromId( $row->img_user );
+
+               $title = Title::makeTitle( NS_FILE, $name );
+               $ul = Linker::link( $user->getUserPage(), $user->getName() );
+               $time = $this->getLanguage()->userTimeAndDate( $row->img_timestamp, $this->getUser() );
+
+               $this->gallery->add(
+                       $title,
+                       "$ul<br />\n<i>"
+                       . htmlspecialchars( $time )
+                       . "</i><br />\n"
+               );
+       }
+
+       function getForm() {
+               $fields = [
+                       'like' => [
+                               'type' => 'text',
+                               'label-message' => 'newimages-label',
+                               'name' => 'like',
+                       ],
+                       'showbots' => [
+                               'type' => 'check',
+                               'label-message' => 'newimages-showbots',
+                               'name' => 'showbots',
+                       ],
+                       'hidepatrolled' => [
+                               'type' => 'check',
+                               'label-message' => 'newimages-hidepatrolled',
+                               'name' => 'hidepatrolled',
+                       ],
+                       'limit' => [
+                               'type' => 'hidden',
+                               'default' => $this->mLimit,
+                               'name' => 'limit',
+                       ],
+                       'offset' => [
+                               'type' => 'hidden',
+                               'default' => $this->getRequest()->getText( 'offset' ),
+                               'name' => 'offset',
+                       ],
+               ];
+
+               if ( $this->getConfig()->get( 'MiserMode' ) ) {
+                       unset( $fields['like'] );
+               }
+
+               if ( !$this->getUser()->useFilePatrol() ) {
+                       unset( $fields['hidepatrolled'] );
+               }
+
+               $context = new DerivativeContext( $this->getContext() );
+               $context->setTitle( $this->getTitle() ); // Remove subpage
+               $form = new HTMLForm( $fields, $context );
+
+               $form->setSubmitTextMsg( 'ilsubmit' );
+               $form->setSubmitProgressive();
+
+               $form->setMethod( 'get' );
+               $form->setWrapperLegendMsg( 'newimages-legend' );
+
+               return $form;
+       }
+}
diff --git a/includes/specials/pagers/NewPagesPager.php b/includes/specials/pagers/NewPagesPager.php
new file mode 100644 (file)
index 0000000..2d39f99
--- /dev/null
@@ -0,0 +1,148 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * @ingroup Pager
+ */
+class NewPagesPager extends ReverseChronologicalPager {
+
+       // Stored opts
+       protected $opts;
+
+       /**
+        * @var HtmlForm
+        */
+       protected $mForm;
+
+       function __construct( $form, FormOptions $opts ) {
+               parent::__construct( $form->getContext() );
+               $this->mForm = $form;
+               $this->opts = $opts;
+       }
+
+       function getQueryInfo() {
+               $conds = [];
+               $conds['rc_new'] = 1;
+
+               $namespace = $this->opts->getValue( 'namespace' );
+               $namespace = ( $namespace === 'all' ) ? false : intval( $namespace );
+
+               $username = $this->opts->getValue( 'username' );
+               $user = Title::makeTitleSafe( NS_USER, $username );
+
+               $rcIndexes = [];
+
+               if ( $namespace !== false ) {
+                       if ( $this->opts->getValue( 'invert' ) ) {
+                               $conds[] = 'rc_namespace != ' . $this->mDb->addQuotes( $namespace );
+                       } else {
+                               $conds['rc_namespace'] = $namespace;
+                       }
+               }
+
+               if ( $user ) {
+                       $conds['rc_user_text'] = $user->getText();
+                       $rcIndexes = 'rc_user_text';
+               } elseif ( User::groupHasPermission( '*', 'createpage' ) &&
+                       $this->opts->getValue( 'hideliu' )
+               ) {
+                       # If anons cannot make new pages, don't "exclude logged in users"!
+                       $conds['rc_user'] = 0;
+               }
+
+               # If this user cannot see patrolled edits or they are off, don't do dumb queries!
+               if ( $this->opts->getValue( 'hidepatrolled' ) && $this->getUser()->useNPPatrol() ) {
+                       $conds['rc_patrolled'] = 0;
+               }
+
+               if ( $this->opts->getValue( 'hidebots' ) ) {
+                       $conds['rc_bot'] = 0;
+               }
+
+               if ( $this->opts->getValue( 'hideredirs' ) ) {
+                       $conds['page_is_redirect'] = 0;
+               }
+
+               // Allow changes to the New Pages query
+               $tables = [ 'recentchanges', 'page' ];
+               $fields = [
+                       'rc_namespace', 'rc_title', 'rc_cur_id', 'rc_user', 'rc_user_text',
+                       'rc_comment', 'rc_timestamp', 'rc_patrolled', 'rc_id', 'rc_deleted',
+                       'length' => 'page_len', 'rev_id' => 'page_latest', 'rc_this_oldid',
+                       'page_namespace', 'page_title'
+               ];
+               $join_conds = [ 'page' => [ 'INNER JOIN', 'page_id=rc_cur_id' ] ];
+
+               Hooks::run( 'SpecialNewpagesConditions',
+                       [ &$this, $this->opts, &$conds, &$tables, &$fields, &$join_conds ] );
+
+               $options = [];
+
+               if ( $rcIndexes ) {
+                       $options = [ 'USE INDEX' => [ 'recentchanges' => $rcIndexes ] ];
+               }
+
+               $info = [
+                       'tables' => $tables,
+                       'fields' => $fields,
+                       'conds' => $conds,
+                       'options' => $options,
+                       'join_conds' => $join_conds
+               ];
+
+               // Modify query for tags
+               ChangeTags::modifyDisplayQuery(
+                       $info['tables'],
+                       $info['fields'],
+                       $info['conds'],
+                       $info['join_conds'],
+                       $info['options'],
+                       $this->opts['tagfilter']
+               );
+
+               return $info;
+       }
+
+       function getIndexField() {
+               return 'rc_timestamp';
+       }
+
+       function formatRow( $row ) {
+               return $this->mForm->formatRow( $row );
+       }
+
+       function getStartBody() {
+               # Do a batch existence check on pages
+               $linkBatch = new LinkBatch();
+               foreach ( $this->mResult as $row ) {
+                       $linkBatch->add( NS_USER, $row->rc_user_text );
+                       $linkBatch->add( NS_USER_TALK, $row->rc_user_text );
+                       $linkBatch->add( $row->page_namespace, $row->page_title );
+               }
+               $linkBatch->execute();
+
+               return '<ul>';
+       }
+
+       function getEndBody() {
+               return '</ul>';
+       }
+}
diff --git a/includes/specials/pagers/ProtectedTitlesPager.php b/includes/specials/pagers/ProtectedTitlesPager.php
new file mode 100644 (file)
index 0000000..8f172f8
--- /dev/null
@@ -0,0 +1,91 @@
+<?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
+ * @ingroup Pager
+ */
+
+/**
+ * @ingroup Pager
+ */
+class ProtectedTitlesPager extends AlphabeticPager {
+
+       public $mForm, $mConds;
+
+       function __construct( $form, $conds = [], $type, $level, $namespace,
+               $sizetype = '', $size = 0
+       ) {
+               $this->mForm = $form;
+               $this->mConds = $conds;
+               $this->level = $level;
+               $this->namespace = $namespace;
+               $this->size = intval( $size );
+               parent::__construct( $form->getContext() );
+       }
+
+       function getStartBody() {
+               # Do a link batch query
+               $this->mResult->seek( 0 );
+               $lb = new LinkBatch;
+
+               foreach ( $this->mResult as $row ) {
+                       $lb->add( $row->pt_namespace, $row->pt_title );
+               }
+
+               $lb->execute();
+
+               return '';
+       }
+
+       /**
+        * @return Title
+        */
+       function getTitle() {
+               return $this->mForm->getTitle();
+       }
+
+       function formatRow( $row ) {
+               return $this->mForm->formatRow( $row );
+       }
+
+       /**
+        * @return array
+        */
+       function getQueryInfo() {
+               $conds = $this->mConds;
+               $conds[] = 'pt_expiry > ' . $this->mDb->addQuotes( $this->mDb->timestamp() ) .
+                       ' OR pt_expiry IS NULL';
+               if ( $this->level ) {
+                       $conds['pt_create_perm'] = $this->level;
+               }
+
+               if ( !is_null( $this->namespace ) ) {
+                       $conds[] = 'pt_namespace=' . $this->mDb->addQuotes( $this->namespace );
+               }
+
+               return [
+                       'tables' => 'protected_titles',
+                       'fields' => [ 'pt_namespace', 'pt_title', 'pt_create_perm',
+                               'pt_expiry', 'pt_timestamp' ],
+                       'conds' => $conds
+               ];
+       }
+
+       function getIndexField() {
+               return 'pt_timestamp';
+       }
+}
diff --git a/includes/specials/pagers/UsersPager.php b/includes/specials/pagers/UsersPager.php
new file mode 100644 (file)
index 0000000..7b058c1
--- /dev/null
@@ -0,0 +1,395 @@
+<?php
+/**
+ * Copyright © 2004 Brion Vibber, lcrocker, Tim Starling,
+ * Domas Mituzas, Antoine Musso, Jens Frank, Zhengzhu,
+ * 2006 Rob Church <robchur@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Pager
+ */
+
+/**
+ * This class is used to get a list of user. The ones with specials
+ * rights (sysop, bureaucrat, developer) will have them displayed
+ * next to their names.
+ *
+ * @ingroup Pager
+ */
+class UsersPager extends AlphabeticPager {
+
+       /**
+        * @var array A array with user ids as key and a array of groups as value
+        */
+       protected $userGroupCache;
+
+       /**
+        * @param IContextSource $context
+        * @param array $par (Default null)
+        * @param bool $including Whether this page is being transcluded in
+        * another page
+        */
+       function __construct( IContextSource $context = null, $par = null, $including = null ) {
+               if ( $context ) {
+                       $this->setContext( $context );
+               }
+
+               $request = $this->getRequest();
+               $par = ( $par !== null ) ? $par : '';
+               $parms = explode( '/', $par );
+               $symsForAll = [ '*', 'user' ];
+
+               if ( $parms[0] != '' &&
+                       ( in_array( $par, User::getAllGroups() ) || in_array( $par, $symsForAll ) )
+               ) {
+                       $this->requestedGroup = $par;
+                       $un = $request->getText( 'username' );
+               } elseif ( count( $parms ) == 2 ) {
+                       $this->requestedGroup = $parms[0];
+                       $un = $parms[1];
+               } else {
+                       $this->requestedGroup = $request->getVal( 'group' );
+                       $un = ( $par != '' ) ? $par : $request->getText( 'username' );
+               }
+
+               if ( in_array( $this->requestedGroup, $symsForAll ) ) {
+                       $this->requestedGroup = '';
+               }
+               $this->editsOnly = $request->getBool( 'editsOnly' );
+               $this->creationSort = $request->getBool( 'creationSort' );
+               $this->including = $including;
+               $this->mDefaultDirection = $request->getBool( 'desc' )
+                       ? IndexPager::DIR_DESCENDING
+                       : IndexPager::DIR_ASCENDING;
+
+               $this->requestedUser = '';
+
+               if ( $un != '' ) {
+                       $username = Title::makeTitleSafe( NS_USER, $un );
+
+                       if ( !is_null( $username ) ) {
+                               $this->requestedUser = $username->getText();
+                       }
+               }
+
+               parent::__construct();
+       }
+
+       /**
+        * @return string
+        */
+       function getIndexField() {
+               return $this->creationSort ? 'user_id' : 'user_name';
+       }
+
+       /**
+        * @return array
+        */
+       function getQueryInfo() {
+               $dbr = wfGetDB( DB_SLAVE );
+               $conds = [];
+
+               // Don't show hidden names
+               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+                       $conds[] = 'ipb_deleted IS NULL OR ipb_deleted = 0';
+               }
+
+               $options = [];
+
+               if ( $this->requestedGroup != '' ) {
+                       $conds['ug_group'] = $this->requestedGroup;
+               }
+
+               if ( $this->requestedUser != '' ) {
+                       # Sorted either by account creation or name
+                       if ( $this->creationSort ) {
+                               $conds[] = 'user_id >= ' . intval( User::idFromName( $this->requestedUser ) );
+                       } else {
+                               $conds[] = 'user_name >= ' . $dbr->addQuotes( $this->requestedUser );
+                       }
+               }
+
+               if ( $this->editsOnly ) {
+                       $conds[] = 'user_editcount > 0';
+               }
+
+               $options['GROUP BY'] = $this->creationSort ? 'user_id' : 'user_name';
+
+               $query = [
+                       'tables' => [ 'user', 'user_groups', 'ipblocks' ],
+                       'fields' => [
+                               'user_name' => $this->creationSort ? 'MAX(user_name)' : 'user_name',
+                               'user_id' => $this->creationSort ? 'user_id' : 'MAX(user_id)',
+                               'edits' => 'MAX(user_editcount)',
+                               'creation' => 'MIN(user_registration)',
+                               'ipb_deleted' => 'MAX(ipb_deleted)' // block/hide status
+                       ],
+                       'options' => $options,
+                       'join_conds' => [
+                               'user_groups' => [ 'LEFT JOIN', 'user_id=ug_user' ],
+                               'ipblocks' => [
+                                       'LEFT JOIN', [
+                                               'user_id=ipb_user',
+                                               'ipb_auto' => 0
+                                       ]
+                               ],
+                       ],
+                       'conds' => $conds
+               ];
+
+               Hooks::run( 'SpecialListusersQueryInfo', [ $this, &$query ] );
+
+               return $query;
+       }
+
+       /**
+        * @param stdClass $row
+        * @return string
+        */
+       function formatRow( $row ) {
+               if ( $row->user_id == 0 ) { # Bug 16487
+                       return '';
+               }
+
+               $userName = $row->user_name;
+
+               $ulinks = Linker::userLink( $row->user_id, $userName );
+               $ulinks .= Linker::userToolLinksRedContribs(
+                       $row->user_id,
+                       $userName,
+                       (int)$row->edits
+               );
+
+               $lang = $this->getLanguage();
+
+               $groups = '';
+               $groups_list = self::getGroups( intval( $row->user_id ), $this->userGroupCache );
+
+               if ( !$this->including && count( $groups_list ) > 0 ) {
+                       $list = [];
+                       foreach ( $groups_list as $group ) {
+                               $list[] = self::buildGroupLink( $group, $userName );
+                       }
+                       $groups = $lang->commaList( $list );
+               }
+
+               $item = $lang->specialList( $ulinks, $groups );
+
+               if ( $row->ipb_deleted ) {
+                       $item = "<span class=\"deleted\">$item</span>";
+               }
+
+               $edits = '';
+               if ( !$this->including && $this->getConfig()->get( 'Edititis' ) ) {
+                       $count = $this->msg( 'usereditcount' )->numParams( $row->edits )->escaped();
+                       $edits = $this->msg( 'word-separator' )->escaped() . $this->msg( 'brackets', $count )->escaped();
+               }
+
+               $created = '';
+               # Some rows may be null
+               if ( !$this->including && $row->creation ) {
+                       $user = $this->getUser();
+                       $d = $lang->userDate( $row->creation, $user );
+                       $t = $lang->userTime( $row->creation, $user );
+                       $created = $this->msg( 'usercreated', $d, $t, $row->user_name )->escaped();
+                       $created = ' ' . $this->msg( 'parentheses' )->rawParams( $created )->escaped();
+               }
+               $blocked = !is_null( $row->ipb_deleted ) ?
+                       ' ' . $this->msg( 'listusers-blocked', $userName )->escaped() :
+                       '';
+
+               Hooks::run( 'SpecialListusersFormatRow', [ &$item, $row ] );
+
+               return Html::rawElement( 'li', [], "{$item}{$edits}{$created}{$blocked}" );
+       }
+
+       function doBatchLookups() {
+               $batch = new LinkBatch();
+               $userIds = [];
+               # Give some pointers to make user links
+               foreach ( $this->mResult as $row ) {
+                       $batch->add( NS_USER, $row->user_name );
+                       $batch->add( NS_USER_TALK, $row->user_name );
+                       $userIds[] = $row->user_id;
+               }
+
+               // Lookup groups for all the users
+               $dbr = wfGetDB( DB_SLAVE );
+               $groupRes = $dbr->select(
+                       'user_groups',
+                       [ 'ug_user', 'ug_group' ],
+                       [ 'ug_user' => $userIds ],
+                       __METHOD__
+               );
+               $cache = [];
+               $groups = [];
+               foreach ( $groupRes as $row ) {
+                       $cache[intval( $row->ug_user )][] = $row->ug_group;
+                       $groups[$row->ug_group] = true;
+               }
+               $this->userGroupCache = $cache;
+
+               // Add page of groups to link batch
+               foreach ( $groups as $group => $unused ) {
+                       $groupPage = User::getGroupPage( $group );
+                       if ( $groupPage ) {
+                               $batch->addObj( $groupPage );
+                       }
+               }
+
+               $batch->execute();
+               $this->mResult->rewind();
+       }
+
+       /**
+        * @return string
+        */
+       function getPageHeader() {
+               list( $self ) = explode( '/', $this->getTitle()->getPrefixedDBkey() );
+
+               $this->getOutput()->addModules( 'mediawiki.userSuggest' );
+
+               # Form tag
+               $out = Xml::openElement(
+                               'form',
+                               [ 'method' => 'get', 'action' => wfScript(), 'id' => 'mw-listusers-form' ]
+                       ) .
+                       Xml::fieldset( $this->msg( 'listusers' )->text() ) .
+                       Html::hidden( 'title', $self );
+
+               # Username field (with autocompletion support)
+               $out .= Xml::label( $this->msg( 'listusersfrom' )->text(), 'offset' ) . ' ' .
+                       Html::input(
+                               'username',
+                               $this->requestedUser,
+                               'text',
+                               [
+                                       'class' => 'mw-autocomplete-user',
+                                       'id' => 'offset',
+                                       'size' => 20,
+                                       'autofocus' => $this->requestedUser === ''
+                               ]
+                       ) . ' ';
+
+               # Group drop-down list
+               $sel = new XmlSelect( 'group', 'group', $this->requestedGroup );
+               $sel->addOption( $this->msg( 'group-all' )->text(), '' );
+               foreach ( $this->getAllGroups() as $group => $groupText ) {
+                       $sel->addOption( $groupText, $group );
+               }
+
+               $out .= Xml::label( $this->msg( 'group' )->text(), 'group' ) . ' ';
+               $out .= $sel->getHTML() . '<br />';
+               $out .= Xml::checkLabel(
+                       $this->msg( 'listusers-editsonly' )->text(),
+                       'editsOnly',
+                       'editsOnly',
+                       $this->editsOnly
+               );
+               $out .= '&#160;';
+               $out .= Xml::checkLabel(
+                       $this->msg( 'listusers-creationsort' )->text(),
+                       'creationSort',
+                       'creationSort',
+                       $this->creationSort
+               );
+               $out .= '&#160;';
+               $out .= Xml::checkLabel(
+                       $this->msg( 'listusers-desc' )->text(),
+                       'desc',
+                       'desc',
+                       $this->mDefaultDirection
+               );
+               $out .= '<br />';
+
+               Hooks::run( 'SpecialListusersHeaderForm', [ $this, &$out ] );
+
+               # Submit button and form bottom
+               $out .= Html::hidden( 'limit', $this->mLimit );
+               $out .= Xml::submitButton( $this->msg( 'listusers-submit' )->text() );
+               Hooks::run( 'SpecialListusersHeader', [ $this, &$out ] );
+               $out .= Xml::closeElement( 'fieldset' ) .
+                       Xml::closeElement( 'form' );
+
+               return $out;
+       }
+
+       /**
+        * Get a list of all explicit groups
+        * @return array
+        */
+       function getAllGroups() {
+               $result = [];
+               foreach ( User::getAllGroups() as $group ) {
+                       $result[$group] = User::getGroupName( $group );
+               }
+               asort( $result );
+
+               return $result;
+       }
+
+       /**
+        * Preserve group and username offset parameters when paging
+        * @return array
+        */
+       function getDefaultQuery() {
+               $query = parent::getDefaultQuery();
+               if ( $this->requestedGroup != '' ) {
+                       $query['group'] = $this->requestedGroup;
+               }
+               if ( $this->requestedUser != '' ) {
+                       $query['username'] = $this->requestedUser;
+               }
+               Hooks::run( 'SpecialListusersDefaultQuery', [ $this, &$query ] );
+
+               return $query;
+       }
+
+       /**
+        * Get a list of groups the specified user belongs to
+        *
+        * @param int $uid User id
+        * @param array|null $cache
+        * @return array
+        */
+       protected static function getGroups( $uid, $cache = null ) {
+               if ( $cache === null ) {
+                       $user = User::newFromId( $uid );
+                       $effectiveGroups = $user->getEffectiveGroups();
+               } else {
+                       $effectiveGroups = isset( $cache[$uid] ) ? $cache[$uid] : [];
+               }
+               $groups = array_diff( $effectiveGroups, User::getImplicitGroups() );
+
+               return $groups;
+       }
+
+       /**
+        * Format a link to a group description page
+        *
+        * @param string $group Group name
+        * @param string $username Username
+        * @return string
+        */
+       protected static function buildGroupLink( $group, $username ) {
+               return User::makeGroupLinkHTML(
+                       $group,
+                       User::getGroupMember( $group, $username )
+               );
+       }
+
+}
index a39690a..3824be1 100644 (file)
@@ -28,13 +28,13 @@ class UsercreateTemplate extends BaseTemplate {
         * UserCreateForm hook to add checkboxes to the create account form.
         */
        function addInputItem( $name, $value, $type, $msg, $helptext = false ) {
-               $this->data['extraInput'][] = array(
+               $this->data['extraInput'][] = [
                        'name' => $name,
                        'value' => $value,
                        'type' => $type,
                        'msg' => $msg,
                        'helptext' => $helptext,
-               );
+               ];
        }
 
        function execute() {
@@ -84,7 +84,7 @@ class UsercreateTemplate extends BaseTemplate {
                                        <span class="mw-ui-flush-right"><?php echo $this->getMsg( 'createacct-helpusername' )->parse(); ?></span>
                                </label>
                                <?php
-                               echo Html::input( 'wpName', $this->data['name'], 'text', array(
+                               echo Html::input( 'wpName', $this->data['name'], 'text', [
                                        'class' => 'mw-ui-input loginText',
                                        'id' => 'wpName2',
                                        'tabindex' => '1',
@@ -92,7 +92,7 @@ class UsercreateTemplate extends BaseTemplate {
                                        'required',
                                        'placeholder' => $this->getMsg( $this->data['loggedin'] ?
                                                'createacct-another-username-ph' : 'userlogin-yourname-ph' )->text(),
-                               ) );
+                               ] );
                                ?>
                        </div>
 
@@ -113,14 +113,14 @@ class UsercreateTemplate extends BaseTemplate {
                        <div class="mw-ui-vform-field mw-row-password">
                                <label for='wpPassword2'><?php $this->msg( 'userlogin-yourpassword' ); ?></label>
                                <?php
-                               echo Html::input( 'wpPassword', null, 'password', array(
+                               echo Html::input( 'wpPassword', null, 'password', [
                                        'class' => 'mw-ui-input loginPassword',
                                        'id' => 'wpPassword2',
                                        'tabindex' => '3',
                                        'size' => '20',
                                        'required',
                                        'placeholder' => $this->getMsg( 'createacct-yourpassword-ph' )->text()
-                               ) + User::passwordChangeInputAttribs() );
+                               ] + User::passwordChangeInputAttribs() );
                                ?>
                        </div>
 
@@ -143,14 +143,14 @@ class UsercreateTemplate extends BaseTemplate {
                        <div class="mw-ui-vform-field mw-row-password">
                                <label for='wpRetype'><?php $this->msg( 'createacct-yourpasswordagain' ); ?></label>
                                <?php
-                               echo Html::input( 'wpRetype', null, 'password', array(
+                               echo Html::input( 'wpRetype', null, 'password', [
                                        'class' => 'mw-ui-input loginPassword',
                                        'id' => 'wpRetype',
                                        'tabindex' => '5',
                                        'size' => '20',
                                        'required',
                                        'placeholder' => $this->getMsg( 'createacct-yourpasswordagain-ph' )->text()
-                                       ) + User::passwordChangeInputAttribs() );
+                               ] + User::passwordChangeInputAttribs() );
                                ?>
                        </div>
 
@@ -165,7 +165,7 @@ class UsercreateTemplate extends BaseTemplate {
                                                ?>
                                        </label>
                                        <?php
-                                               echo Html::input( 'wpEmail', $this->data['email'], 'email', array(
+                                               echo Html::input( 'wpEmail', $this->data['email'], 'email', [
                                                        'class' => 'mw-ui-input loginText',
                                                        'id' => 'wpEmail',
                                                        'tabindex' => '6',
@@ -173,7 +173,7 @@ class UsercreateTemplate extends BaseTemplate {
                                                        'required' => $this->data['emailrequired'],
                                                        'placeholder' => $this->getMsg( $this->data['loggedin'] ?
                                                                'createacct-another-email-ph' : 'createacct-email-ph' )->text()
-                                               ) );
+                                               ] );
                                        ?>
                                <?php } ?>
                        </div>
@@ -193,13 +193,13 @@ class UsercreateTemplate extends BaseTemplate {
                        <?php if ( $this->data['usereason'] ) { ?>
                                <div class="mw-ui-vform-field">
                                        <label for='wpReason'><?php $this->msg( 'createacct-reason' ); ?></label>
-                                       <?php echo Html::input( 'wpReason', $this->data['reason'], 'text', array(
+                                       <?php echo Html::input( 'wpReason', $this->data['reason'], 'text', [
                                                'class' => 'mw-ui-input loginText',
                                                'id' => 'wpReason',
                                                'tabindex' => '8',
                                                'size' => '20',
                                                'placeholder' => $this->getMsg( 'createacct-reason-ph' )->text()
-                                       ) ); ?>
+                                       ] ); ?>
                                </div>
                        <?php } ?>
 
@@ -265,15 +265,15 @@ class UsercreateTemplate extends BaseTemplate {
                                <?php
                                echo Html::submitButton(
                                        $this->getMsg( $this->data['loggedin'] ? 'createacct-another-submit' : 'createacct-submit' ),
-                                       array(
+                                       [
                                                'id' => 'wpCreateaccount',
                                                'name' => 'wpCreateaccount',
                                                'tabindex' => $tabIndex++
-                                       ),
-                                       array(
+                                       ],
+                                       [
                                                'mw-ui-block',
                                                'mw-ui-constructive',
-                                       )
+                                       ]
                                );
                                ?>
                        </div>
index f19c0f2..c2b2df6 100644 (file)
@@ -67,15 +67,15 @@ class UserloginTemplate extends BaseTemplate {
                                        $this->msg( 'userlogin-yourname' );
 
                                        if ( $this->data['secureLoginUrl'] ) {
-                                               echo Html::element( 'a', array(
+                                               echo Html::element( 'a', [
                                                        'href' => $this->data['secureLoginUrl'],
                                                        'class' => 'mw-ui-flush-right mw-secure',
-                                               ), $this->getMsg( 'userlogin-signwithsecure' )->text() );
+                                               ], $this->getMsg( 'userlogin-signwithsecure' )->text() );
                                        }
                                        ?>
                                </label>
                                <?php
-                               echo Html::input( 'wpName', $this->data['name'], 'text', array(
+                               echo Html::input( 'wpName', $this->data['name'], 'text', [
                                        'class' => 'loginText mw-ui-input',
                                        'id' => 'wpName1',
                                        'tabindex' => '1',
@@ -85,7 +85,7 @@ class UserloginTemplate extends BaseTemplate {
                                        // Set focus to this field if it's blank.
                                        'autofocus' => !$this->data['name'],
                                        'placeholder' => $this->getMsg( 'userlogin-yourname-ph' )->text()
-                               ) );
+                               ] );
                                ?>
                        </div>
 
@@ -96,14 +96,14 @@ class UserloginTemplate extends BaseTemplate {
                                        ?>
                                </label>
                                <?php
-                               echo Html::input( 'wpPassword', null, 'password', array(
+                               echo Html::input( 'wpPassword', null, 'password', [
                                        'class' => 'loginPassword mw-ui-input',
                                        'id' => 'wpPassword1',
                                        'tabindex' => '2',
                                        // Set focus to this field if username is filled in.
                                        'autofocus' => (bool)$this->data['name'],
                                        'placeholder' => $this->getMsg( 'userlogin-yourpassword-ph' )->text()
-                               ) );
+                               ] );
                                ?>
                        </div>
 
@@ -142,14 +142,14 @@ class UserloginTemplate extends BaseTemplate {
 
                        <div class="mw-ui-vform-field">
                                <?php
-                               $attrs = array(
+                               $attrs = [
                                        'id' => 'wpLoginAttempt',
                                        'name' => 'wpLoginAttempt',
                                        'tabindex' => '6',
-                               );
-                               $modifiers = array(
+                               ];
+                               $modifiers = [
                                        'mw-ui-progressive',
-                               );
+                               ];
                                echo Html::submitButton( $this->getMsg( 'pt-login-button' )->text(), $attrs, $modifiers );
                                ?>
                        </div>
@@ -158,11 +158,11 @@ class UserloginTemplate extends BaseTemplate {
                                <?php
                                echo Html::element(
                                        'a',
-                                       array(
+                                       [
                                                'href' => Skin::makeInternalOrExternalUrl(
                                                        wfMessage( 'helplogin-url' )->inContentLanguage()->text()
                                                ),
-                                       ),
+                                       ],
                                        $this->getMsg( 'userlogin-helplink2' )->text()
                                );
                                ?>
@@ -172,9 +172,9 @@ class UserloginTemplate extends BaseTemplate {
                        if ( $this->data['useemail'] && $this->data['canreset'] && $this->data['resetlink'] === true ) {
                                echo Html::rawElement(
                                        'div',
-                                       array(
+                                       [
                                                'class' => 'mw-ui-vform-field mw-form-related-link-container',
-                                       ),
+                                       ],
                                        Linker::link(
                                                SpecialPage::getTitleFor( 'PasswordReset' ),
                                                $this->getMsg( 'userlogin-resetpassword-link' )->escaped()
index a874038..1185c4d 100644 (file)
  * @author Michael Dale
  */
 abstract class UploadBase {
+       /** @var string Local file system path to the file to upload (or a local copy) */
        protected $mTempPath;
+       /** @var TempFSFile|null Wrapper to handle deleting the temp file */
+       protected $tempFileObj;
+
        protected $mDesiredDestName, $mDestName, $mRemoveTempFile, $mSourceType;
        protected $mTitle = false, $mTitleError = 0;
        protected $mFilteredName, $mFinalExtension;
@@ -219,8 +223,8 @@ abstract class UploadBase {
                if ( FileBackend::isStoragePath( $tempPath ) ) {
                        throw new MWException( __METHOD__ . " given storage path `$tempPath`." );
                }
-               $this->mTempPath = $tempPath;
-               $this->mFileSize = $fileSize;
+
+               $this->setTempFile( $tempPath, $fileSize );
                $this->mRemoveTempFile = $removeTempFile;
        }
 
@@ -231,6 +235,23 @@ abstract class UploadBase {
         */
        abstract public function initializeFromRequest( &$request );
 
+       /**
+        * @param string $tempPath File system path to temporary file containing the upload
+        * @param integer $fileSize
+        */
+       protected function setTempFile( $tempPath, $fileSize = null ) {
+               $this->mTempPath = $tempPath;
+               $this->mFileSize = $fileSize ?: null;
+               if ( strlen( $this->mTempPath ) && file_exists( $this->mTempPath ) ) {
+                       $this->tempFileObj = new TempFSFile( $this->mTempPath );
+                       if ( !$fileSize ) {
+                               $this->mFileSize = filesize( $this->mTempPath );
+                       }
+               } else {
+                       $this->tempFileObj = null;
+               }
+       }
+
        /**
         * Fetch the file. Usually a no-op
         * @return Status
@@ -624,9 +645,6 @@ abstract class UploadBase {
 
                if ( $this->mDesiredDestName != $filename && $comparableName != $filename ) {
                        $warnings['badfilename'] = $filename;
-                       // Debugging for bug 62241
-                       wfDebugLog( 'upload', "Filename: '$filename', mDesiredDestName: "
-                               . "'$this->mDesiredDestName', comparableName: '$comparableName'" );
                }
 
                // Check whether the file extension is on the unwanted list
@@ -645,7 +663,7 @@ abstract class UploadBase {
                }
 
                if ( $this->mFileSize == 0 ) {
-                       $warnings['emptyfile'] = true;
+                       $warnings['empty-file'] = true;
                }
 
                $exists = self::getExistsWarning( $localFile );
@@ -952,9 +970,10 @@ abstract class UploadBase {
         * on exit to clean up.
         */
        public function cleanupTempFile() {
-               if ( $this->mRemoveTempFile && $this->mTempPath && file_exists( $this->mTempPath ) ) {
-                       wfDebug( __METHOD__ . ": Removing temporary file {$this->mTempPath}\n" );
-                       unlink( $this->mTempPath );
+               if ( $this->mRemoveTempFile && $this->tempFileObj ) {
+                       // Delete when all relevant TempFSFile handles go out of scope
+                       wfDebug( __METHOD__ . ": Marked temporary file '{$this->mTempPath}' for removal\n" );
+                       $this->tempFileObj->autocollect();
                }
        }
 
index 8ee0845..0323b68 100644 (file)
@@ -142,16 +142,15 @@ class UploadFromChunks extends UploadFromFile {
                $tStart = microtime( true );
                $status = $this->repo->concatenate( $fileList, $tmpPath, FileRepo::DELETE_SOURCE );
                $tAmount = microtime( true ) - $tStart;
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        return $status;
                }
 
                wfDebugLog( 'fileconcatenate', "Combined $i chunks in $tAmount seconds." );
 
-               // File system path
-               $this->mTempPath = $tmpPath;
-               // Since this was set for the last chunk previously
-               $this->mFileSize = filesize( $this->mTempPath );
+               // File system path of the actual full temp file
+               $this->setTempFile( $tmpPath );
+
                $ret = $this->verifyUpload();
                if ( $ret['status'] !== UploadBase::OK ) {
                        wfDebugLog( 'fileconcatenate', "Verification failed for chunked upload" );
@@ -235,7 +234,7 @@ class UploadFromChunks extends UploadFromFile {
                wfDebug( __METHOD__ . " update chunk status for {$this->mFileKey} offset:" .
                        $this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
 
-               $dbw = $this->repo->getMasterDb();
+               $dbw = $this->repo->getMasterDB();
                // Use a quick transaction since we will upload the full temp file into shared
                // storage, which takes time for large files. We don't want to hold locks then.
                $dbw->update(
@@ -257,7 +256,7 @@ class UploadFromChunks extends UploadFromFile {
        private function getChunkStatus() {
                // get Master db to avoid race conditions.
                // Otherwise, if chunk upload time < replag there will be spurious errors
-               $dbw = $this->repo->getMasterDb();
+               $dbw = $this->repo->getMasterDB();
                $row = $dbw->selectRow(
                        'uploadstash',
                        [
index 342bd79..6639c34 100644 (file)
@@ -286,7 +286,7 @@ class UploadFromUrl extends UploadBase {
                }
 
                wfDebugLog( 'fileupload', $status );
-               if ( $status->isOk() ) {
+               if ( $status->isOK() ) {
                        wfDebugLog( 'fileupload', 'Download by URL completed successfuly.' );
                } else {
                        wfDebugLog(
index d5e573b..c171ded 100644 (file)
@@ -276,7 +276,7 @@ class UploadStash {
 
                // insert the file metadata into the db.
                wfDebug( __METHOD__ . " inserting $stashPath under $key\n" );
-               $dbw = $this->repo->getMasterDb();
+               $dbw = $this->repo->getMasterDB();
 
                $serializedFileProps = serialize( $fileProps );
                if ( strlen( $serializedFileProps ) > self::MAX_US_PROPS_SIZE ) {
@@ -336,7 +336,7 @@ class UploadStash {
                }
 
                wfDebug( __METHOD__ . ' clearing all rows for user ' . $this->userId . "\n" );
-               $dbw = $this->repo->getMasterDb();
+               $dbw = $this->repo->getMasterDB();
                $dbw->delete(
                        'uploadstash',
                        [ 'us_user' => $this->userId ],
@@ -364,7 +364,7 @@ class UploadStash {
                                . ' No user is logged in, files must belong to users' );
                }
 
-               $dbw = $this->repo->getMasterDb();
+               $dbw = $this->repo->getMasterDB();
 
                // this is a cheap query. it runs on the master so that this function
                // still works when there's lag. It won't be called all that often.
@@ -399,7 +399,7 @@ class UploadStash {
                // Ensure we have the UploadStashFile loaded for this key
                $this->getFile( $key, true );
 
-               $dbw = $this->repo->getMasterDb();
+               $dbw = $this->repo->getMasterDB();
 
                $dbw->delete(
                        'uploadstash',
@@ -430,7 +430,7 @@ class UploadStash {
                                . ' No user is logged in, files must belong to users' );
                }
 
-               $dbr = $this->repo->getSlaveDb();
+               $dbr = $this->repo->getSlaveDB();
                $res = $dbr->select(
                        'uploadstash',
                        'us_key',
@@ -507,9 +507,9 @@ class UploadStash {
                $dbr = null;
                if ( $readFromDB === DB_MASTER ) {
                        // sometimes reading from the master is necessary, if there's replication lag.
-                       $dbr = $this->repo->getMasterDb();
+                       $dbr = $this->repo->getMasterDB();
                } else {
-                       $dbr = $this->repo->getSlaveDb();
+                       $dbr = $this->repo->getSlaveDB();
                }
 
                $row = $dbr->selectRow(
index c758f26..49a7163 100644 (file)
@@ -18,6 +18,8 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+use MediaWiki\Session\BotPasswordSessionProvider;
+
 /**
  * Utility class for bot passwords
  * @since 1.27
@@ -401,9 +403,7 @@ class BotPassword implements IDBAccessObject {
                }
 
                $manager = MediaWiki\Session\SessionManager::singleton();
-               $provider = $manager->getProvider(
-                       'MediaWiki\\Session\\BotPasswordSessionProvider'
-               );
+               $provider = $manager->getProvider( BotPasswordSessionProvider::class );
                if ( !$provider ) {
                        return Status::newFatal( 'botpasswords-no-provider' );
                }
@@ -429,7 +429,7 @@ class BotPassword implements IDBAccessObject {
 
                // Check restrictions
                $status = $bp->getRestrictions()->check( $request );
-               if ( !$status->isOk() ) {
+               if ( !$status->isOK() ) {
                        return Status::newFatal( 'botpasswords-restriction-failed' );
                }
 
index 14548f4..5444a51 100644 (file)
@@ -26,13 +26,13 @@ use MediaWiki\Session\Token;
 /**
  * Value object representing a logged-out user's edit token
  *
- * This exists so that code generically dealing with MediaWiki\\Session\\Token
+ * This exists so that code generically dealing with MediaWiki\Session\Token
  * (i.e. the API) doesn't have to have so many special cases for anon edit
  * tokens.
  *
  * @since 1.27
  */
-class LoggedOutEditToken extends MediaWiki\Session\Token {
+class LoggedOutEditToken extends Token {
        public function __construct() {
                parent::__construct( '', '', false );
        }
index 2e786bd..04eba97 100644 (file)
  */
 
 use MediaWiki\Session\SessionManager;
+use MediaWiki\Session\Token;
 
 /**
  * String Some punctuation to prevent editing from broken text-mangling proxies.
- * @deprecated since 1.27, use \\MediaWiki\\Session\\Token::SUFFIX
+ * @deprecated since 1.27, use \MediaWiki\Session\Token::SUFFIX
  * @ingroup Constants
  */
-define( 'EDIT_TOKEN_SUFFIX', MediaWiki\Session\Token::SUFFIX );
+define( 'EDIT_TOKEN_SUFFIX', Token::SUFFIX );
 
 /**
  * The User object encapsulates all of the user-specific settings (user_id,
@@ -53,7 +54,7 @@ class User implements IDBAccessObject {
        /**
         * Global constant made accessible as class constants so that autoloader
         * magic can be used.
-        * @deprecated since 1.27, use \\MediaWiki\\Session\\Token::SUFFIX
+        * @deprecated since 1.27, use \MediaWiki\Session\Token::SUFFIX
         */
        const EDIT_TOKEN_SUFFIX = EDIT_TOKEN_SUFFIX;
 
@@ -200,6 +201,7 @@ class User implements IDBAccessObject {
 
        /** Cache variables */
        // @{
+       /** @var int */
        public $mId;
        /** @var string */
        public $mName;
@@ -858,8 +860,6 @@ class User implements IDBAccessObject {
                        || strlen( $name ) > $wgMaxNameChars
                        || $name != $wgContLang->ucfirst( $name )
                ) {
-                       wfDebugLog( 'username', __METHOD__ .
-                               ": '$name' invalid due to empty, IP, slash, length, or lowercase" );
                        return false;
                }
 
@@ -869,8 +869,6 @@ class User implements IDBAccessObject {
                if ( is_null( $parsed )
                        || $parsed->getNamespace()
                        || strcmp( $name, $parsed->getPrefixedText() ) ) {
-                       wfDebugLog( 'username', __METHOD__ .
-                               ": '$name' invalid due to ambiguous prefixes" );
                        return false;
                }
 
@@ -885,8 +883,6 @@ class User implements IDBAccessObject {
                        '\x{e000}-\x{f8ff}' . # private use
                        ']/u';
                if ( preg_match( $unicodeBlacklist, $name ) ) {
-                       wfDebugLog( 'username', __METHOD__ .
-                               ": '$name' invalid due to blacklisted characters" );
                        return false;
                }
 
@@ -2058,7 +2054,8 @@ class User implements IDBAccessObject {
                        // Don't load if this was initialized from an ID
                        $this->load();
                }
-               return $this->mId;
+
+               return (int)$this->mId;
        }
 
        /**
@@ -2168,7 +2165,7 @@ class User implements IDBAccessObject {
                // Get the "last viewed rev" timestamp from the oldest message notification
                $timestamp = $dbr->selectField( 'user_newtalk',
                        'MIN(user_last_timestamp)',
-                       $this->isAnon() ? [ 'user_ip' => $this->getName() ] : [ 'user_id' => $this->getID() ],
+                       $this->isAnon() ? [ 'user_ip' => $this->getName() ] : [ 'user_id' => $this->getId() ],
                        __METHOD__ );
                $rev = $timestamp ? Revision::loadFromTimestamp( $dbr, $utp, $timestamp ) : null;
                return [ [ 'wiki' => wfWikiID(), 'link' => $utp->getLocalURL(), 'rev' => $rev ] ];
@@ -3296,7 +3293,7 @@ class User implements IDBAccessObject {
                if ( $this->getId() ) {
                        $dbw->insert( 'user_groups',
                                [
-                                       'ug_user' => $this->getID(),
+                                       'ug_user' => $this->getId(),
                                        'ug_group' => $group,
                                ],
                                __METHOD__,
@@ -3334,14 +3331,14 @@ class User implements IDBAccessObject {
                $dbw = wfGetDB( DB_MASTER );
                $dbw->delete( 'user_groups',
                        [
-                               'ug_user' => $this->getID(),
+                               'ug_user' => $this->getId(),
                                'ug_group' => $group,
                        ], __METHOD__
                );
                // Remember that the user was in this group
                $dbw->insert( 'user_former_groups',
                        [
-                               'ufg_user' => $this->getID(),
+                               'ufg_user' => $this->getId(),
                                'ufg_group' => $group,
                        ],
                        __METHOD__,
@@ -3366,7 +3363,7 @@ class User implements IDBAccessObject {
         * @return bool
         */
        public function isLoggedIn() {
-               return $this->getID() != 0;
+               return $this->getId() != 0;
        }
 
        /**
@@ -3493,10 +3490,9 @@ class User implements IDBAccessObject {
         */
        public function addWatch( $title, $checkRights = self::CHECK_USER_RIGHTS ) {
                if ( !$checkRights || $this->isAllowed( 'editmywatchlist' ) ) {
-                       WatchedItemStore::getDefaultInstance()->addWatchBatch( [
-                               [ $this, $title->getSubjectPage() ],
-                               [ $this, $title->getTalkPage() ],
-                       ]
+                       WatchedItemStore::getDefaultInstance()->addWatchBatchForUser(
+                               $this,
+                               [ $title->getSubjectPage(), $title->getTalkPage() ]
                        );
                }
                $this->invalidateCache();
@@ -4017,6 +4013,7 @@ class User implements IDBAccessObject {
                if ( $this->isLoggedIn() && $this->isBlocked() ) {
                        return $this->spreadBlock();
                }
+
                return false;
        }
 
@@ -4225,7 +4222,7 @@ class User implements IDBAccessObject {
         * @since 1.27
         * @param string|array $salt Array of Strings Optional function-specific data for hashing
         * @param WebRequest|null $request WebRequest object to use or null to use $wgRequest
-        * @return MediaWiki\\Session\\Token The new edit token
+        * @return MediaWiki\Session\Token The new edit token
         */
        public function getEditTokenObject( $salt = '', $request = null ) {
                if ( $this->isAnon() ) {
@@ -4255,7 +4252,7 @@ class User implements IDBAccessObject {
 
        /**
         * Get the embedded timestamp from a token.
-        * @deprecated since 1.27, use \\MediaWiki\\Session\\Token::getTimestamp instead.
+        * @deprecated since 1.27, use \MediaWiki\Session\Token::getTimestamp instead.
         * @param string $val Input token
         * @return int|null
         */
@@ -4291,7 +4288,7 @@ class User implements IDBAccessObject {
         * @return bool Whether the token matches
         */
        public function matchEditTokenNoSuffix( $val, $salt = '', $request = null, $maxage = null ) {
-               $val = substr( $val, 0, strspn( $val, '0123456789abcdef' ) ) . self::EDIT_TOKEN_SUFFIX;
+               $val = substr( $val, 0, strspn( $val, '0123456789abcdef' ) ) . Token::SUFFIX;
                return $this->matchEditToken( $val, $salt, $request, $maxage );
        }
 
index 002fd06..3bd3a4c 100644 (file)
@@ -166,14 +166,14 @@ class BatchRowIterator implements RecursiveIterator {
        }
 
        /**
-        * @return boolean True when the iterator is in a valid state
+        * @return bool True when the iterator is in a valid state
         */
        public function valid() {
                return (bool)$this->current;
        }
 
        /**
-        * @return boolean True when this result set has rows
+        * @return bool True when this result set has rows
         */
        public function hasChildren() {
                return $this->current && count( $this->current );
index bcc2ed3..4a2205e 100644 (file)
@@ -73,7 +73,7 @@ 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.
+        * @note canonicalize() tries to convert translated addresses to IPv4.
         *
         * @param string $ip Possible IP address
         * @return bool
@@ -84,7 +84,7 @@ class IP {
 
        /**
         * Given a string, determine if it as valid IP in IPv6 only.
-        * Note: Unlike isValid(), this looks for networks too.
+        * @note Unlike isValid(), this looks for networks too.
         *
         * @param string $ip Possible IP address
         * @return bool
@@ -95,7 +95,7 @@ class IP {
 
        /**
         * Given a string, determine if it as valid IP in IPv4 only.
-        * Note: Unlike isValid(), this looks for networks too.
+        * @note Unlike isValid(), this looks for networks too.
         *
         * @param string $ip Possible IP address
         * @return bool
@@ -107,7 +107,7 @@ class 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.
+        * @note canonicalize() tries to convert translated addresses to IPv4.
         *
         * @param string $ip
         * @return bool True if it is valid
@@ -120,7 +120,7 @@ class 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.
+        * @note canonicalize() tries to convert translated addresses to IPv4.
         *
         * @param string $ipblock
         * @return bool True if it is valid
@@ -633,6 +633,9 @@ class IP {
         * @param string $addr The address to check against the given range.
         * @param string $range The range to check the given address against.
         * @return bool Whether or not the given address is in the given range.
+        *
+        * @note This can return unexpected results for invalid arguments!
+        *       Make sure you pass a valid IP address and IP range.
         */
        public static function isInRange( $addr, $range ) {
                $hexIP = self::toHex( $addr );
index 75eaede..1117357 100644 (file)
@@ -70,7 +70,7 @@ class MWCryptHash {
         * Return the byte-length output of the hash algorithm we are
         * using in self::hash and self::hmac.
         *
-        * @param boolean $raw True to return the length for binary data, false to
+        * @param bool $raw True to return the length for binary data, false to
         *   return for hex-encoded
         * @return int Number of bytes the hash outputs
         */
@@ -88,7 +88,7 @@ class MWCryptHash {
         * making use of the best hash algorithm that we have available.
         *
         * @param string $data
-        * @param boolean $raw True to return binary data, false to return it hex-encoded
+        * @param bool $raw True to return binary data, false to return it hex-encoded
         * @return string A hash of the data
         */
        public static function hash( $data, $raw = true ) {
@@ -101,10 +101,14 @@ class MWCryptHash {
         *
         * @param string $data
         * @param string $key
-        * @param boolean $raw True to return binary data, false to return it hex-encoded
+        * @param bool $raw True to return binary data, false to return it hex-encoded
         * @return string An hmac hash of the data + key
         */
        public static function hmac( $data, $key, $raw = true ) {
+               if ( !is_string( $key ) ) {
+                       // a fatal error in HHVM; an exception will at least give us a stack trace
+                       throw new InvalidArgumentException( 'Invalid key type: ' . gettype( $key ) );
+               }
                return hash_hmac( self::hashAlgo(), $data, $key, $raw );
        }
 
index 44815b4..516e9ae 100644 (file)
@@ -215,6 +215,10 @@ class ZipDirectoryReader {
                        $startPos = 0;
                }
 
+               if ( $this->getFileLength() === 0 ) {
+                       $this->error( 'zip-wrong-format', "The file is empty." );
+               }
+
                $block = $this->getBlock( $startPos );
                $sigPos = strrpos( $block, "PK\x05\x06" );
                if ( $sigPos === false ) {
index 5855ddf..a0fa727 100644 (file)
@@ -30,9 +30,7 @@ if ( !defined( 'MEDIAWIKI' ) ) {
        exit( 1 );
 }
 
-if ( function_exists( 'mb_strtoupper' ) ) {
-       mb_internal_encoding( 'UTF-8' );
-}
+mb_internal_encoding( 'UTF-8' );
 
 use CLDRPluralRuleParser\Evaluator;
 
@@ -443,7 +441,7 @@ class Language {
         * @return array
         * @since 1.19
         */
-       function getFallbackLanguages() {
+       public function getFallbackLanguages() {
                return self::getFallbacksFor( $this->mCode );
        }
 
@@ -451,7 +449,7 @@ class Language {
         * Exports $wgBookstoreListEn
         * @return array
         */
-       function getBookstoreList() {
+       public function getBookstoreList() {
                return self::$dataCache->getItem( $this->mCode, 'bookstoreList' );
        }
 
@@ -520,7 +518,7 @@ class Language {
         *
         * @return array
         */
-       function getFormattedNamespaces() {
+       public function getFormattedNamespaces() {
                $ns = $this->getNamespaces();
                foreach ( $ns as $k => $v ) {
                        $ns[$k] = strtr( $v, '_', ' ' );
@@ -539,7 +537,7 @@ class Language {
         * @param int $index The array key of the namespace to return
         * @return string|bool String if the namespace value exists, otherwise false
         */
-       function getNsText( $index ) {
+       public function getNsText( $index ) {
                $ns = $this->getNamespaces();
                return isset( $ns[$index] ) ? $ns[$index] : false;
        }
@@ -557,7 +555,7 @@ class Language {
         * @param int $index The array key of the namespace to return
         * @return string Namespace name without underscores (empty string if namespace does not exist)
         */
-       function getFormattedNsText( $index ) {
+       public function getFormattedNsText( $index ) {
                $ns = $this->getNsText( $index );
                return strtr( $ns, '_', ' ' );
        }
@@ -570,7 +568,7 @@ class Language {
         * @return string
         * @since 1.18
         */
-       function getGenderNsText( $index, $gender ) {
+       public function getGenderNsText( $index, $gender ) {
                global $wgExtraGenderNamespaces;
 
                $ns = $wgExtraGenderNamespaces +
@@ -585,7 +583,7 @@ class Language {
         * @return bool
         * @since 1.18
         */
-       function needsGenderDistinction() {
+       public function needsGenderDistinction() {
                global $wgExtraGenderNamespaces, $wgExtraNamespaces;
                if ( count( $wgExtraGenderNamespaces ) > 0 ) {
                        // $wgExtraGenderNamespaces overrides everything
@@ -618,7 +616,7 @@ class Language {
        /**
         * @return array
         */
-       function getNamespaceAliases() {
+       public function getNamespaceAliases() {
                if ( is_null( $this->namespaceAliases ) ) {
                        $aliases = self::$dataCache->getItem( $this->mCode, 'namespaceAliases' );
                        if ( !$aliases ) {
@@ -662,7 +660,7 @@ class Language {
        /**
         * @return array
         */
-       function getNamespaceIds() {
+       public function getNamespaceIds() {
                if ( is_null( $this->mNamespaceIds ) ) {
                        global $wgNamespaceAliases;
                        # Put namespace names and aliases into a hashtable.
@@ -692,7 +690,7 @@ class Language {
         * @param string $text
         * @return int|bool An integer if $text is a valid value otherwise false
         */
-       function getNsIndex( $text ) {
+       public function getNsIndex( $text ) {
                $lctext = $this->lc( $text );
                $ns = MWNamespace::getCanonicalIndex( $lctext );
                if ( $ns !== null ) {
@@ -709,7 +707,7 @@ class Language {
         * @param bool $usemsg Use the "variantname-xyz" message if it exists
         * @return string
         */
-       function getVariantname( $code, $usemsg = true ) {
+       public function getVariantname( $code, $usemsg = true ) {
                $msg = "variantname-$code";
                if ( $usemsg && wfMessage( $msg )->exists() ) {
                        return $this->getMessageFromDB( $msg );
@@ -726,7 +724,7 @@ class Language {
        /**
         * @return array
         */
-       function getDatePreferences() {
+       public function getDatePreferences() {
                return self::$dataCache->getItem( $this->mCode, 'datePreferences' );
        }
 
@@ -740,7 +738,7 @@ class Language {
        /**
         * @return array|string
         */
-       function getDefaultDateFormat() {
+       public function getDefaultDateFormat() {
                $df = self::$dataCache->getItem( $this->mCode, 'defaultDateFormat' );
                if ( $df === 'dmy or mdy' ) {
                        global $wgAmericanDates;
@@ -753,7 +751,7 @@ class Language {
        /**
         * @return array
         */
-       function getDatePreferenceMigrationMap() {
+       public function getDatePreferenceMigrationMap() {
                return self::$dataCache->getItem( $this->mCode, 'datePreferenceMigrationMap' );
        }
 
@@ -769,14 +767,14 @@ class Language {
         * @return array
         * @since 1.24
         */
-       function getImageFiles() {
+       public function getImageFiles() {
                return self::$dataCache->getItem( $this->mCode, 'imageFiles' );
        }
 
        /**
         * @return array
         */
-       function getExtraUserToggles() {
+       public function getExtraUserToggles() {
                return (array)self::$dataCache->getItem( $this->mCode, 'extraUserToggles' );
        }
 
@@ -899,7 +897,7 @@ class Language {
         * @param string $msg Message name
         * @return string
         */
-       function getMessageFromDB( $msg ) {
+       public function getMessageFromDB( $msg ) {
                return $this->msg( $msg )->text();
        }
 
@@ -917,14 +915,14 @@ class Language {
         * @param string $key
         * @return string
         */
-       function getMonthName( $key ) {
+       public function getMonthName( $key ) {
                return $this->getMessageFromDB( self::$mMonthMsgs[$key - 1] );
        }
 
        /**
         * @return array
         */
-       function getMonthNamesArray() {
+       public function getMonthNamesArray() {
                $monthNames = [ '' ];
                for ( $i = 1; $i < 13; $i++ ) {
                        $monthNames[] = $this->getMonthName( $i );
@@ -936,7 +934,7 @@ class Language {
         * @param string $key
         * @return string
         */
-       function getMonthNameGen( $key ) {
+       public function getMonthNameGen( $key ) {
                return $this->getMessageFromDB( self::$mMonthGenMsgs[$key - 1] );
        }
 
@@ -2592,7 +2590,7 @@ class Language {
                return $text;
        }
 
-       // callback functions for uc(), lc(), ucwords(), ucwordbreaks()
+       // callback functions for ucwords(), ucwordbreaks()
 
        /**
         * @param array $matches
@@ -2610,24 +2608,6 @@ class Language {
                return mb_strtoupper( $matches[0] );
        }
 
-       /**
-        * @param array $matches
-        * @return string
-        */
-       function ucCallback( $matches ) {
-               list( $wikiUpperChars ) = self::getCaseMaps();
-               return strtr( $matches[1], $wikiUpperChars );
-       }
-
-       /**
-        * @param array $matches
-        * @return string
-        */
-       function lcCallback( $matches ) {
-               list( , $wikiLowerChars ) = self::getCaseMaps();
-               return strtr( $matches[1], $wikiLowerChars );
-       }
-
        /**
         * @param array $matches
         * @return string
@@ -2636,15 +2616,6 @@ class Language {
                return mb_strtoupper( $matches[0] );
        }
 
-       /**
-        * @param array $matches
-        * @return string
-        */
-       function ucwordsCallbackWiki( $matches ) {
-               list( $wikiUpperChars ) = self::getCaseMaps();
-               return strtr( $matches[0], $wikiUpperChars );
-       }
-
        /**
         * Make a string's first character uppercase
         *
@@ -2673,27 +2644,14 @@ class Language {
         * @return string
         */
        function uc( $str, $first = false ) {
-               if ( function_exists( 'mb_strtoupper' ) ) {
-                       if ( $first ) {
-                               if ( $this->isMultibyte( $str ) ) {
-                                       return mb_strtoupper( mb_substr( $str, 0, 1 ) ) . mb_substr( $str, 1 );
-                               } else {
-                                       return ucfirst( $str );
-                               }
-                       } else {
-                               return $this->isMultibyte( $str ) ? mb_strtoupper( $str ) : strtoupper( $str );
-                       }
-               } else {
+               if ( $first ) {
                        if ( $this->isMultibyte( $str ) ) {
-                               $x = $first ? '^' : '';
-                               return preg_replace_callback(
-                                       "/$x([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)/",
-                                       [ $this, 'ucCallback' ],
-                                       $str
-                               );
+                               return mb_strtoupper( mb_substr( $str, 0, 1 ) ) . mb_substr( $str, 1 );
                        } else {
-                               return $first ? ucfirst( $str ) : strtoupper( $str );
+                               return ucfirst( $str );
                        }
+               } else {
+                       return $this->isMultibyte( $str ) ? mb_strtoupper( $str ) : strtoupper( $str );
                }
        }
 
@@ -2721,27 +2679,14 @@ class Language {
         * @return mixed|string
         */
        function lc( $str, $first = false ) {
-               if ( function_exists( 'mb_strtolower' ) ) {
-                       if ( $first ) {
-                               if ( $this->isMultibyte( $str ) ) {
-                                       return mb_strtolower( mb_substr( $str, 0, 1 ) ) . mb_substr( $str, 1 );
-                               } else {
-                                       return strtolower( substr( $str, 0, 1 ) ) . substr( $str, 1 );
-                               }
-                       } else {
-                               return $this->isMultibyte( $str ) ? mb_strtolower( $str ) : strtolower( $str );
-                       }
-               } else {
+               if ( $first ) {
                        if ( $this->isMultibyte( $str ) ) {
-                               $x = $first ? '^' : '';
-                               return preg_replace_callback(
-                                       "/$x([A-Z]|[\\xc0-\\xff][\\x80-\\xbf]*)/",
-                                       [ $this, 'lcCallback' ],
-                                       $str
-                               );
+                               return mb_strtolower( mb_substr( $str, 0, 1 ) ) . mb_substr( $str, 1 );
                        } else {
-                               return $first ? strtolower( substr( $str, 0, 1 ) ) . substr( $str, 1 ) : strtolower( $str );
+                               return strtolower( substr( $str, 0, 1 ) ) . substr( $str, 1 );
                        }
+               } else {
+                       return $this->isMultibyte( $str ) ? mb_strtolower( $str ) : strtolower( $str );
                }
        }
 
@@ -2765,19 +2710,11 @@ class Language {
                        $replaceRegexp = "/^([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)| ([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)/";
 
                        // function to use to capitalize a single char
-                       if ( function_exists( 'mb_strtoupper' ) ) {
-                               return preg_replace_callback(
-                                       $replaceRegexp,
-                                       [ $this, 'ucwordsCallbackMB' ],
-                                       $str
-                               );
-                       } else {
-                               return preg_replace_callback(
-                                       $replaceRegexp,
-                                       [ $this, 'ucwordsCallbackWiki' ],
-                                       $str
-                               );
-                       }
+                       return preg_replace_callback(
+                               $replaceRegexp,
+                               [ $this, 'ucwordsCallbackMB' ],
+                               $str
+                       );
                } else {
                        return ucwords( strtolower( $str ) );
                }
@@ -2800,19 +2737,11 @@ class Language {
                        $replaceRegexp = "/^([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)|" .
                                "$breaks([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)/";
 
-                       if ( function_exists( 'mb_strtoupper' ) ) {
-                               return preg_replace_callback(
-                                       $replaceRegexp,
-                                       [ $this, 'ucwordbreaksCallbackMB' ],
-                                       $str
-                               );
-                       } else {
-                               return preg_replace_callback(
-                                       $replaceRegexp,
-                                       [ $this, 'ucwordsCallbackWiki' ],
-                                       $str
-                               );
-                       }
+                       return preg_replace_callback(
+                               $replaceRegexp,
+                               [ $this, 'ucwordbreaksCallbackMB' ],
+                               $str
+                       );
                } else {
                        return preg_replace_callback(
                                '/\b([\w\x80-\xff]+)\b/',
@@ -2844,6 +2773,7 @@ class Language {
        /**
         * @param string $s
         * @return string
+        * @throws MWException
         */
        function checkTitleEncoding( $s ) {
                if ( is_array( $s ) ) {
@@ -3298,7 +3228,7 @@ class Language {
         * Normally we output all numbers in plain en_US style, that is
         * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
         * point twohundredthirtyfive. However this is not suitable for all
-        * languages, some such as Punjabi want à©¨à©¯à©©,੨੯੫.੨੩੫ and others such as
+        * languages, some such as Bengali (bn) want à§¨,৯৩,২৯১.২৩৫ and others such as
         * Icelandic just want to use commas instead of dots, and dots instead
         * of commas like "293.291,235".
         *
@@ -3965,10 +3895,11 @@ class Language {
         * match up with it.
         *
         * @param string $str The validated block duration in English
+        * @param User $user User object to use timezone from or null for $wgUser
         * @return string Somehow translated block duration
         * @see LanguageFi.php for example implementation
         */
-       function translateBlockExpiry( $str ) {
+       function translateBlockExpiry( $str, User $user = null ) {
                $duration = SpecialBlock::getSuggestedDurations( $this );
                foreach ( $duration as $show => $value ) {
                        if ( strcmp( $str, $value ) == 0 ) {
@@ -3994,10 +3925,12 @@ class Language {
                } else { // It's an absolute timestamp.
                        if ( $time === 0 ) {
                                // wfTimestamp() handles 0 as current time instead of epoch.
-                               return $this->timeanddate( '19700101000000' );
-                       } else {
-                               return $this->timeanddate( $time );
+                               $time = '19700101000000';
                        }
+                       if ( $user ) {
+                               return $this->userTimeAndDate( $time, $user );
+                       }
+                       return $this->timeanddate( $time );
                }
        }
 
@@ -4183,7 +4116,7 @@ class Language {
         * Refresh the cache of conversion tables when
         * MediaWiki:Conversiontable* is updated.
         *
-        * @param Title $titleobj The Title of the page being updated
+        * @param Title $title The Title of the page being updated
         */
        public function updateConversionTable( Title $title ) {
                $this->mConverter->updateConversionTable( $title );
@@ -4355,6 +4288,7 @@ class Language {
        /**
         * @param string $code
         * @return string
+        * @throws MWException
         * @since 1.23
         */
        public static function getJsonMessagesFileName( $code ) {
@@ -4462,7 +4396,7 @@ class Language {
         * @return array Array of message keys (strings)
         */
        public static function getMessageKeysFor( $code ) {
-               return self::getLocalisationCache()->getSubItemList( $code, 'messages' );
+               return self::getLocalisationCache()->getSubitemList( $code, 'messages' );
        }
 
        /**
@@ -4494,33 +4428,13 @@ class Language {
                return $this->convertGrammar( trim( $m[2] ), trim( $m[1] ) );
        }
 
-       /**
-        * @throws MWException
-        * @return array
-        */
-       static function getCaseMaps() {
-               static $wikiUpperChars, $wikiLowerChars;
-               if ( isset( $wikiUpperChars ) ) {
-                       return [ $wikiUpperChars, $wikiLowerChars ];
-               }
-
-               $arr = wfGetPrecompiledData( 'Utf8Case.ser' );
-               if ( $arr === false ) {
-                       throw new MWException(
-                               "Utf8Case.ser is missing, please run \"make\" in the serialized directory\n" );
-               }
-               $wikiUpperChars = $arr['wikiUpperChars'];
-               $wikiLowerChars = $arr['wikiLowerChars'];
-               return [ $wikiUpperChars, $wikiLowerChars ];
-       }
-
        /**
         * Decode an expiry (block, protection, etc) which has come from the DB
         *
         * @param string $expiry Database expiry String
         * @param bool|int $format True to process using language functions, or TS_ constant
         *     to return the expiry in a given timestamp
-        * @param string $inifinity If $format is not true, use this string for infinite expiry
+        * @param string $infinity If $format is not true, use this string for infinite expiry
         * @return string
         * @since 1.18
         */
index c3c40ef..3388536 100644 (file)
@@ -73,7 +73,6 @@ class LanguageFi extends Language {
                                break;
                        case 'illative':
                                # Double the last letter and add 'n'
-                               # mb_substr has a compatibility function in GlobalFunctions.php
                                $word = $word . mb_substr( $word, -1 ) . 'n';
                                break;
                        case 'inessive':
@@ -85,10 +84,10 @@ class LanguageFi extends Language {
 
        /**
         * @param string $str
-        * @param bool $forContent
+        * @param User $user User object to use timezone from or null for $wgUser
         * @return string
         */
-       function translateBlockExpiry( $str, $forContent = false ) {
+       function translateBlockExpiry( $str, User $user = null ) {
                /*
                        'ago', 'now', 'today', 'this', 'next',
                        'first', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth',
index 7a46aac..6c49aa4 100644 (file)
@@ -180,7 +180,7 @@ class Names {
                'gv' => 'Gaelg',                # Manx
                'ha' => 'Hausa',        # Hausa
                'hak' => '客家語/Hak-kâ-ngî',      # Hakka
-               'haw' => 'Hawai`i',             # Hawaiian
+               'haw' => 'Hawaiʻi',            # Hawaiian
                'he' => 'עברית',   # Hebrew
                'hi' => 'हिन्दी',   # Hindi
                'hif' => 'Fiji Hindi',  # Fijian Hindi (multiple scripts - defaults to Latin)
index d273085..08a40b8 100644 (file)
@@ -3237,6 +3237,7 @@ public static $zh2Hant = [
 '世纪钟' => '世紀鐘',
 '世纪钟表' => '世紀鐘錶',
 '丢丑' => '丟醜',
+'并吞下' => '並吞下',
 '并曰入淀' => '並曰入澱',
 '并发动' => '並發動',
 '并发展' => '並發展',
@@ -3709,7 +3710,6 @@ public static $zh2Hant = [
 '井干' => '井幹',
 '井里' => '井裡',
 '亚于' => '亞於',
-'亚美尼亚历' => '亞美尼亞曆',
 '交托' => '交託',
 '交游' => '交遊',
 '交哄' => '交鬨',
@@ -3730,7 +3730,6 @@ public static $zh2Hant = [
 '仁贵' => '仁貴',
 '介胄' => '介冑',
 '他干的' => '他幹的',
-'他钟' => '他鐘',
 '付托' => '付託',
 '仙后' => '仙后',
 '仙后座' => '仙后座',
@@ -3802,7 +3801,7 @@ public static $zh2Hant = [
 '并到' => '併到',
 '并合' => '併合',
 '并名' => '併名',
-'并吞下' => '併吞下',
+'并吞' => '併吞',
 '并拢' => '併攏',
 '并案' => '併案',
 '并流' => '併流',
@@ -3823,7 +3822,6 @@ public static $zh2Hant = [
 '使其斗' => '使其鬥',
 '来于' => '來於',
 '侍仆' => '侍僕',
-'供制' => '供製',
 '依依不舍' => '依依不捨',
 '依托' => '依託',
 '侵并' => '侵併',
@@ -4374,6 +4372,8 @@ public static $zh2Hant = [
 '后稷' => '后稷',
 '后綜' => '后綜',
 '后羿' => '后羿',
+'后苍' => '后蒼',
+'后蒼' => '后蒼',
 '后街' => '后街',
 '后角' => '后角',
 '后丰' => '后豐',
@@ -4404,6 +4404,7 @@ public static $zh2Hant = [
 '呆致致' => '呆緻緻',
 '呆里呆气' => '呆裡呆氣',
 '告札' => '告劄',
+'告里' => '告裡',
 '呦喂' => '呦喂',
 '周后' => '周后',
 '周惠后' => '周惠后',
@@ -4662,12 +4663,10 @@ public static $zh2Hant = [
 '大明历史' => '大明歷史',
 '大历' => '大曆',
 '大本钟' => '大本鐘',
-'大本钟敲' => '大本鐘敲',
 '大历史' => '大歷史',
 '大病初愈' => '大病初癒',
 '大目干连' => '大目乾連',
 '大笨钟' => '大笨鐘',
-'大笨钟敲' => '大笨鐘敲',
 '大蜡' => '大蜡',
 '大衍历' => '大衍曆',
 '大衍历史' => '大衍歷史',
@@ -4973,7 +4972,6 @@ public static $zh2Hant = [
 '年里' => '年裡',
 '年鉴' => '年鑑',
 '并力' => '并力',
-'并吞' => '并吞',
 '并州' => '并州',
 '并日而食' => '并日而食',
 '并迭' => '并迭',
@@ -5090,7 +5088,6 @@ public static $zh2Hant = [
 '吊慰' => '弔慰',
 '吊扣' => '弔扣',
 '吊拷' => '弔拷',
-'吊挂' => '弔掛',
 '吊撒' => '弔撒',
 '吊文' => '弔文',
 '吊旗' => '弔旗',
@@ -5118,7 +5115,9 @@ public static $zh2Hant = [
 '张勋' => '張勳',
 '张杰' => '張杰',
 '張杰' => '張杰',
+'张柏芝' => '張栢芝',
 '张乐于张徐' => '張樂于張徐',
+'强制' => '強制',
 '强制作用' => '強制作用',
 '强奸' => '強姦',
 '强干' => '強幹',
@@ -5171,7 +5170,6 @@ public static $zh2Hant = [
 '复始' => '復始',
 '复活节历表' => '復活節曆表',
 '复苏' => '復甦',
-'征人' => '徵人',
 '征令' => '徵令',
 '征信' => '徵信',
 '征候' => '徵候',
@@ -5399,6 +5397,8 @@ public static $zh2Hant = [
 '恶斗' => '惡鬥',
 '惴栗' => '惴慄',
 '意大利面' => '意大利麵',
+'愛河里花子' => '愛河里花子',
+'爱河里花子' => '愛河里花子',
 '爱困' => '愛睏',
 '感于' => '感於',
 '愿朴' => '愿樸',
@@ -5513,7 +5513,7 @@ public static $zh2Hant = [
 '扛大梁' => '扛大樑',
 '扯面' => '扯麵',
 '扶余' => '扶餘',
-'批准的' => '批准的',
+'批准' => '批准',
 '批准确定' => '批准確定',
 '批复' => '批覆',
 '批注' => '批註',
@@ -5577,16 +5577,8 @@ public static $zh2Hant = [
 '拳局' => '拳跼',
 '拼死拼活' => '拼死拼活',
 '拾沈' => '拾瀋',
-'拿下表' => '拿下錶',
-'拿下钟' => '拿下鐘',
 '拿准' => '拿準',
 '拿破仑' => '拿破崙',
-'挂图' => '挂圖',
-'挂帅' => '挂帥',
-'挂彩' => '挂彩',
-'挂念' => '挂念',
-'挂号' => '挂號',
-'挂车' => '挂車',
 '挌斗' => '挌鬥',
 '挑大梁' => '挑大樑',
 '挑斗' => '挑鬥',
@@ -5663,10 +5655,8 @@ public static $zh2Hant = [
 '掌柜' => '掌柜',
 '排骨面' => '排骨麵',
 '挂名' => '掛名',
-'挂帘' => '掛帘',
 '挂历' => '掛曆',
 '挂钩' => '掛鈎',
-'挂钟' => '掛鐘',
 '挂面' => '掛麵',
 '采下' => '採下',
 '采伐' => '採伐',
@@ -6086,7 +6076,7 @@ public static $zh2Hant = [
 '栗栖溪' => '栗栖溪',
 '校准' => '校準',
 '校舍' => '校舍',
-'核准的' => '核准的',
+'核准' => '核准',
 '格于' => '格於',
 '格范' => '格範',
 '格里历' => '格里曆',
@@ -6599,7 +6589,7 @@ public static $zh2Hant = [
 '争斗' => '爭鬥',
 '爰定祥历' => '爰定祥厤',
 '爽荡' => '爽蕩',
-'尔冬' => '爾冬陞',
+'尔冬' => '爾冬陞',
 '墙里' => '牆裡',
 '片里' => '片裡',
 '片言只语' => '片言隻語',
@@ -6665,7 +6655,9 @@ public static $zh2Hant = [
 '甄后' => '甄后',
 '瓮安' => '甕安',
 '甚于' => '甚於',
+'甜、咸' => '甜、鹹',
 '甜水面' => '甜水麵',
+'甜咸' => '甜鹹',
 '甜面酱' => '甜麵醬',
 '生力面' => '生力麵',
 '生于' => '生於',
@@ -6692,6 +6684,9 @@ public static $zh2Hant = [
 '男仆' => '男僕',
 '界里' => '界裡',
 '畏于' => '畏於',
+'留发展' => '留發展',
+'留发生' => '留發生',
+'留发行' => '留發行',
 '留长发' => '留長髮',
 '留发' => '留髮',
 '毕于' => '畢於',
@@ -6805,8 +6800,6 @@ public static $zh2Hant = [
 '相于' => '相於',
 '相冲' => '相衝',
 '相斗' => '相鬥',
-'看下表' => '看下錶',
-'看下钟' => '看下鐘',
 '看法里' => '看法裡',
 '看准' => '看準',
 '看表面' => '看表面',
@@ -6827,8 +6820,6 @@ public static $zh2Hant = [
 '困觉' => '睏覺',
 '睡游病' => '睡遊病',
 '瞄准' => '瞄準',
-'瞅下表' => '瞅下錶',
-'瞅下钟' => '瞅下鐘',
 '瞎蒙' => '瞎矇',
 '了望' => '瞭望',
 '了然' => '瞭然',
@@ -6864,6 +6855,7 @@ public static $zh2Hant = [
 '确瘠' => '确瘠',
 '碑志' => '碑誌',
 '碗里' => '碗裡',
+'碧河里' => '碧河里',
 '碰钟' => '碰鐘',
 '确系' => '確係',
 '码表' => '碼錶',
@@ -6921,6 +6913,7 @@ public static $zh2Hant = [
 '秦沈客运' => '秦瀋客運',
 '移祸于' => '移禍於',
 '稀松' => '稀鬆',
+'程十发' => '程十髮',
 '棱台' => '稜台',
 '棱子' => '稜子',
 '棱层' => '稜層',
@@ -6998,24 +6991,6 @@ public static $zh2Hant = [
 '竹制' => '竹製',
 '竹溪县' => '竹谿縣',
 '笑里藏刀' => '笑裡藏刀',
-'第一出现' => '第一出現',
-'第一出現' => '第一出現',
-'第一出線' => '第一出線',
-'第一出线' => '第一出線',
-'第一出' => '第一齣',
-'第七出' => '第七齣',
-'第三出局' => '第三出局',
-'第三出' => '第三齣',
-'第九出' => '第九齣',
-'第二出線' => '第二出線',
-'第二出线' => '第二出線',
-'第二出' => '第二齣',
-'第五出局' => '第五出局',
-'第五出' => '第五齣',
-'第八出' => '第八齣',
-'第六出' => '第六齣',
-'第四出局' => '第四出局',
-'第四出' => '第四齣',
 '笔杆' => '筆桿',
 '笔秃墨干' => '筆禿墨乾',
 '等于' => '等於',
@@ -7596,6 +7571,7 @@ public static $zh2Hant = [
 '虫部' => '虫部',
 '蚊动牛斗' => '蚊動牛鬥',
 '蛇发女妖' => '蛇髮女妖',
+'蛋白发' => '蛋白發',
 '蜂后' => '蜂后',
 '蜂涌' => '蜂湧',
 '蜂准' => '蜂準',
@@ -7769,6 +7745,7 @@ public static $zh2Hant = [
 '复目' => '複目',
 '复眼' => '複眼',
 '复种' => '複種',
+'复穗' => '複穗',
 '复线' => '複線',
 '复习' => '複習',
 '复色' => '複色',
@@ -8215,6 +8192,7 @@ public static $zh2Hant = [
 '游客' => '遊客',
 '游宦' => '遊宦',
 '游山玩水' => '遊山玩水',
+'游廊' => '遊廊',
 '游必有方' => '遊必有方',
 '游憩' => '遊憩',
 '游戏' => '遊戲',
@@ -8222,6 +8200,7 @@ public static $zh2Hant = [
 '游手好闲' => '遊手好閒',
 '游方' => '遊方',
 '游星' => '遊星',
+'游春' => '遊春',
 '游乐' => '遊樂',
 '游标卡尺' => '遊標卡尺',
 '游历' => '遊歷',
@@ -8629,7 +8608,6 @@ public static $zh2Hant = [
 '陈杰' => '陳杰',
 '陳杰' => '陳杰',
 '陈炼' => '陳鍊',
-'陆游' => '陸遊',
 '阳春面' => '陽春麵',
 '阳历' => '陽曆',
 '阳历史' => '陽歷史',
@@ -8648,6 +8626,7 @@ public static $zh2Hant = [
 '只身' => '隻身',
 '雄斗斗' => '雄斗斗',
 '雅范' => '雅範',
+'集团' => '集團',
 '集数里' => '集數裡',
 '集于' => '集於',
 '集里' => '集裡',
@@ -8764,6 +8743,7 @@ public static $zh2Hant = [
 '预报不准' => '預報不準',
 '预制' => '預製',
 '领袖欲' => '領袖慾',
+'头发现' => '頭發現',
 '头里' => '頭裡',
 '头长发' => '頭長髮',
 '头发' => '頭髮',
@@ -9016,10 +8996,11 @@ public static $zh2Hant = [
 '发短心长' => '髮短心長',
 '发禁' => '髮禁',
 '发笺' => '髮箋',
+'发簪' => '髮簪',
 '发纱' => '髮紗',
 '发结' => '髮結',
 '发丝' => '髮絲',
-'发网' => '髮網',
+'发网菌' => '髮網菌',
 '发脚' => '髮腳',
 '发肤' => '髮膚',
 '发胶' => '髮膠',
@@ -9027,7 +9008,6 @@ public static $zh2Hant = [
 '发蜡' => '髮蠟',
 '发踊冲冠' => '髮踴沖冠',
 '发辫' => '髮辮',
-'发针' => '髮針',
 '发钗' => '髮釵',
 '发长' => '髮長',
 '发际' => '髮際',
@@ -9241,6 +9221,7 @@ public static $zh2Hant = [
 '鹤发' => '鶴髮',
 '鸾鉴' => '鸞鑑',
 '鹰雕' => '鹰鵰',
+'咸、甜' => '鹹、甜',
 '咸味' => '鹹味',
 '咸嘴淡舌' => '鹹嘴淡舌',
 '咸土' => '鹹土',
@@ -9255,6 +9236,7 @@ public static $zh2Hant = [
 '咸汤' => '鹹湯',
 '咸潟' => '鹹潟',
 '咸湿' => '鹹濕',
+'咸甜' => '鹹甜',
 '咸的' => '鹹的',
 '咸粥' => '鹹粥',
 '咸肉' => '鹹肉',
@@ -10521,6 +10503,7 @@ public static $zh2Hans = [
 '潄' => '漱',
 '潑' => '泼',
 '潔' => '洁',
+'潕' => '𣲘',
 '潙' => '沩',
 '潛' => '潜',
 '潤' => '润',
@@ -11842,6 +11825,7 @@ public static $zh2Hans = [
 '躒' => '跞',
 '躓' => '踬',
 '躕' => '蹰',
+'躘' => '𨀁',
 '躚' => '跹',
 '躝' => '𨅬',
 '躡' => '蹑',
@@ -13874,7 +13858,6 @@ public static $zh2TW = [
 '行人路' => '人行道',
 '石勒苏益格' => '什勒斯維希',
 '石勒蘇益格' => '什勒斯維希',
-'界面' => '介面',
 '伊利诺伊州' => '伊利諾州',
 '伊斯坦布尔' => '伊斯坦堡',
 '伊斯坦布爾' => '伊斯坦堡',
@@ -14010,6 +13993,8 @@ public static $zh2TW = [
 '航天器' => '太空飛行器',
 '尼日利亚' => '奈及利亞',
 '尼日利亞' => '奈及利亞',
+'內羅畢' => '奈洛比',
+'内罗毕' => '奈洛比',
 '忌廉' => '奶油',
 '荷里活' => '好萊塢',
 '威廉姆斯' => '威廉士',
@@ -14028,7 +14013,6 @@ public static $zh2TW = [
 '安提瓜和巴布達' => '安地卡及巴布達',
 '洪都拉斯' => '宏都拉斯',
 '密歇根' => '密西根',
-'宽带' => '寬頻',
 '老挝人民民主共和国' => '寮人民民主共和國',
 '老撾人民民主共和國' => '寮人民民主共和國',
 '老挝' => '寮國',
@@ -14422,7 +14406,6 @@ public static $zh2TW = [
 '格莱美奖' => '葛萊美獎',
 '黑山共和国' => '蒙特內哥羅共和國',
 '黑山共和國' => '蒙特內哥羅共和國',
-'滿地可' => '蒙特婁',
 '蒙特利尔' => '蒙特婁',
 '蒙特利爾' => '蒙特婁',
 '普密蓬' => '蒲美蓬',
@@ -14704,7 +14687,6 @@ public static $zh2HK = [
 '布控' => '佈控',
 '布于' => '佈於',
 '布於' => '佈於',
-'布施' => '佈施',
 '布景' => '佈景',
 '布满' => '佈滿',
 '布滿' => '佈滿',
@@ -15032,6 +15014,7 @@ public static $zh2HK = [
 '光著錄' => '光著錄',
 '柯林頓' => '克林頓',
 '克羅埃西亞' => '克羅地亞',
+'奈洛比' => '內羅畢',
 '公布' => '公佈',
 '冒著' => '冒着',
 '冒著作' => '冒著作',
@@ -15194,6 +15177,7 @@ public static $zh2HK = [
 '吹著錄' => '吹著錄',
 '呆著' => '呆着',
 '呆里呆气' => '呆裏呆氣',
+'告里' => '告裏',
 '味著' => '味着',
 '味著作' => '味著作',
 '味著名' => '味著名',
@@ -15869,6 +15853,8 @@ public static $zh2HK = [
 '撼著者' => '撼著者',
 '撼著述' => '撼著述',
 '撼著錄' => '撼著錄',
+'择日占星' => '擇日占星',
+'擇日占星' => '擇日占星',
 '擋著' => '擋着',
 '擋著作' => '擋著作',
 '擋著名' => '擋著名',
@@ -15895,6 +15881,7 @@ public static $zh2HK = [
 '擺著者' => '擺著者',
 '擺著述' => '擺著述',
 '擺著錄' => '擺著錄',
+'收錄著' => '收錄着',
 '攻占' => '攻佔',
 '放著' => '放着',
 '放著作' => '放著作',
@@ -16637,6 +16624,7 @@ public static $zh2HK = [
 '系列里' => '系列裏',
 '係數' => '系數',
 '系里' => '系裏',
+'紀錄著' => '紀錄着',
 '約占' => '約佔',
 '约占' => '約佔',
 '紐賓士域' => '紐賓士域',
@@ -16859,7 +16847,6 @@ public static $zh2HK = [
 '葉爾欽' => '葉利欽',
 '葡占' => '葡佔',
 '葫芦里卖甚么药' => '葫蘆裏賣甚麼藥',
-'滿地可' => '蒙特利爾',
 '蒙特婁' => '蒙特利爾',
 '蒙著' => '蒙着',
 '蒙著作' => '蒙著作',
@@ -16992,6 +16979,7 @@ public static $zh2HK = [
 '記著者' => '記著者',
 '記著述' => '記著述',
 '記著錄' => '記著錄',
+'記錄著' => '記錄着',
 '試著' => '試着',
 '試著作' => '試著作',
 '試著名' => '試著名',
@@ -17925,6 +17913,7 @@ public static $zh2CN = [
 '關著述' => '关著述',
 '關帳' => '关账',
 '記憶體' => '内存',
+'奈洛比' => '内罗毕',
 '甘比亞' => '冈比亚',
 '冒著' => '冒着',
 '冒著書' => '冒著书',
@@ -18253,6 +18242,8 @@ public static $zh2CN = [
 '坐著稱' => '坐著称',
 '坐著者' => '坐著者',
 '坐著述' => '坐著述',
+'坚杜拜' => '坚杜拜',
+'堅杜拜' => '坚杜拜',
 '堅貞著' => '坚贞着',
 '坦尚尼亞' => '坦桑尼亚',
 '伊波拉' => '埃博拉',
@@ -18346,7 +18337,6 @@ public static $zh2CN = [
 '定著者' => '定著者',
 '定著述' => '定著述',
 '波里活' => '宝莱坞',
-'寬頻' => '宽带',
 '密执安' => '密歇根',
 '密西根' => '密歇根',
 '對著' => '对着',
@@ -18575,6 +18565,7 @@ public static $zh2CN = [
 '想著述' => '想著述',
 '義大利' => '意大利',
 '戈巴契夫' => '戈尔巴乔夫',
+'成份股' => '成份股',
 '成份' => '成分',
 '戰著' => '战着',
 '戰著書' => '战著书',
@@ -18818,6 +18809,7 @@ public static $zh2CN = [
 '撼著者' => '撼著者',
 '撼著述' => '撼著述',
 '作業系統' => '操作系统',
+'收錄著' => '收录着',
 '收帳' => '收账',
 '放著' => '放着',
 '放著作' => '放著作',
@@ -19550,6 +19542,7 @@ public static $zh2CN = [
 '索馬利蘭' => '索马里兰',
 '正體中文' => '繁体中文',
 '強斯頓環礁' => '约翰斯顿岛',
+'紀錄著' => '纪录着',
 '縱著' => '纵着',
 '組份' => '组分',
 '經常帳' => '经常账',
@@ -19686,7 +19679,6 @@ public static $zh2CN = [
 '落著稱' => '落著称',
 '落著者' => '落著者',
 '落著述' => '落著述',
-'滿地可' => '蒙特利尔',
 '蒙特婁' => '蒙特利尔',
 '蒙著' => '蒙着',
 '蒙著書' => '蒙著书',
@@ -19770,6 +19762,7 @@ public static $zh2CN = [
 '計畫' => '计划',
 '電腦程式' => '计算机程序',
 '認帳' => '认账',
+'記錄著' => '记录着',
 '記著' => '记着',
 '記著書' => '记著书',
 '記著作' => '记著作',
index 0c51902..e03ef78 100644 (file)
        "recentchangeslinked-page": "Bladsynaam:",
        "recentchangeslinked-to": "Besigtig wysigings aan bladsye met skakels na die bladsy",
        "recentchanges-page-added-to-category": "[[:$1]] by kategorie gevoeg",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] en {{PLURAL:$2|een bladsy|$2 bladsye}} by kategorie gevoeg",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] en [[Special:WhatLinksHere/$1|{{PLURAL:$2|een bladsy|$2 bladsye}}]] by kategorie gevoeg",
        "recentchanges-page-removed-from-category": "[[:$1]] uit kategorie verwyder",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] en {{PLURAL:$2|een bladsy|$2 bladsye}} van kategorie verwyder",
        "autochange-username": "Outomatiese MediaWiki-wysiging",
index a7d5d44..516a780 100644 (file)
        "cancel": "Cancelar",
        "moredotdotdot": "Más...",
        "mypage": "Pachina",
-       "mytalk": "Pachina de discusión",
+       "mytalk": "Pachina de descusión",
        "anontalk": "Pachina de descusión d'ista IP",
        "navigation": "Navego",
        "and": "&#32;y",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|versión|versions}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versión|versions}} dende $2",
        "javascripttest": "Prebatinas de JavaScript",
-       "javascripttest-pagetext-noframework": "Ista pachina ye reservada ta fer as prebas de JavaScrip.",
-       "javascripttest-pagetext-unknownframework": "Bastida de prebas \"$1\" desconoixida.",
-       "javascripttest-pagetext-frameworks": "Por favor, trigue una d'as siguients bastidas de prebas: $1",
-       "javascripttest-pagetext-skins": "Trigue una apariencia ta fer as prebas con ella:",
        "javascripttest-qunit-intro": "Mire-se [$1 a documentación de prebatinas] en mediawiki.org",
        "tooltip-pt-userpage": "A suya pachina d'usuario",
        "tooltip-pt-anonuserpage": "A pachina d'usuario de l'adreza IP dende a que ye editando",
        "watchlisttools-view": "Amostrar cambeos",
        "watchlisttools-edit": "Veyer y editar a lista de seguimiento",
        "watchlisttools-raw": "Editar a lista de seguimiento en formato texto",
-       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discusión]])",
+       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|descusión]])",
        "duplicate-defaultsort": "Pare cuenta: A clau d'ordenación por defecto «$2» anula l'anterior clau d'ordenación por defecto «$1».",
        "version": "Versión",
        "version-extensions": "Estensions instalatas",
index c134c29..1ad03ef 100644 (file)
@@ -58,7 +58,8 @@
                        "Haytham morsy",
                        "BAB ZAA",
                        "ASammour",
-                       "Maroen1990"
+                       "Maroen1990",
+                       "Sonic N800"
                ]
        },
        "tog-underline": "سطر تحت الوصلات:",
        "botpasswords-updated-body": "كلمة سر البوت\"$1\" قد حذفت.",
        "botpasswords-deleted-title": "كلمة سر البوت حذفت",
        "botpasswords-deleted-body": "كلمة سر البوت\"$1\" قد حذفت.",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider غير متاح.",
        "resetpass_forbidden": "كلمات السر لا يمكن تغييرها",
        "resetpass-no-info": "يجب أن تكون مسجل الدخول للوصول إلى هذه الصفحة مباشرة.",
        "resetpass-submit-loggedin": "تغيير كلمة السر",
        "mergehistory-fail-no-change": "دمج التاريخ لم يدمج أية مراجعات. برجاء التحقق من معاملات الصفحة والزمن.",
        "mergehistory-fail-permission": "سماحيات غير كافية لدمج التاريخ.",
        "mergehistory-fail-self-merge": "الصفحتان المصدر والوجهة هما نفس الصفحة.",
+       "mergehistory-fail-timestamps-overlap": "مراجعات المصدر تتداخل أو تأتي بعد مراجعات الوجهة.",
        "mergehistory-fail-toobig": "لا يمكن إجراء دمج التاريخ بسبب تجاوز حدود عدد المراجعات المنقولة {{PLURAL:$1|المراجعة الواحدة|المراجعتين|$1 مراجعات|$1 مراجعة}}.",
        "mergehistory-no-source": "الصفحة المصدر $1 غير موجودة.",
        "mergehistory-no-destination": "الصفحة الهدف $1 غير موجودة.",
        "right-createpage": "إنشاء الصفحات (التي ليست صفحات نقاش)",
        "right-createtalk": "إنشاء صفحات النقاش",
        "right-createaccount": "إنشاء حسابات مستخدم جديدة",
+       "right-autocreateaccount": "تسجيل الدخول باستخدام حساب مستخدم خارجي",
        "right-minoredit": "التعليم على التعديلات كطفيفة",
        "right-move": "نقل الصفحات",
        "right-move-subpages": "نقل الصفحات مع صفحاتها الفرعية",
        "uploadstash-badtoken": "لم ينجح أداء ذلك العمل، ربما لأن وثائق تفويض التحرير الخاصة بك منتهية الصلاحية. حاول مرة أخرى.",
        "uploadstash-errclear": "فشلت عملية مسح الملفات.",
        "uploadstash-refresh": "تحديث قائمة الملفات",
+       "uploadstash-thumbnail": "اعرض صورة مصغرة",
        "invalid-chunk-offset": "قطعة أوفست غير صالحة",
        "img-auth-accessdenied": "رفض الوصول",
        "img-auth-nopathinfo": "PATH_INFO مفقود.\nخادومك ليس مضبوطاً لتمرير هذه المعلومة.\nقد يكون مبنياً على نظام CGI ولا يمكنه دعم img_auth.\nراجع https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "apihelp-no-such-module": "الوحدة \"$1\" غير موجودة.",
        "apisandbox": "ملعب API",
        "apisandbox-jsonly": "الجافا سكريبت مطلوبة لاستخدام ملعب API",
+       "apisandbox-api-disabled": "واجهة برمجة التطبيق API معطلة في هذا الموقع.",
        "apisandbox-fullscreen": "وسع اللوحة",
        "apisandbox-unfullscreen": "أظهر الصفحة",
        "apisandbox-submit": "عمل الطلب",
        "apisandbox-dynamic-error-exists": "يوجد بالفعل معامل باسم \"$1\".",
        "apisandbox-deprecated-parameters": "معاملات مهملة",
        "apisandbox-submit-invalid-fields-title": "بعض الحقول غير صالحة",
+       "apisandbox-submit-invalid-fields-message": "برجاء تصحيح الحقل المعلم والمحاولة مرة أخرى.",
        "apisandbox-results": "النتائج",
        "apisandbox-sending-request": "إرسال طلب API ...",
        "apisandbox-loading-results": "استقبال طلبات API ...",
        "changecontentmodel-title-label": "عنوان الصفحة",
        "changecontentmodel-model-label": "نموذج محتوى جديد",
        "changecontentmodel-reason-label": "السبب:",
+       "changecontentmodel-submit": "تغيير",
        "changecontentmodel-success-title": "نموذج المحتوى تم تغييره",
        "changecontentmodel-success-text": "نوع المحتوى ل[[:$1]] تم تغييره.",
        "changecontentmodel-cannot-convert": "المحتوى على [[:$1]] لا يمكن تحويله لنوع من $2.",
        "import-logentry-upload-detail": "{{PLURAL:$1|لا مراجعات|مراجعة واحدة|مراجعتان|$1 مراجعات|$1 مراجعة}}",
        "import-logentry-interwiki-detail": "تم استيراد {{PLURAL:$1||مراجعة واحدة|مراجعتين|$1 مراجعات|$1 مراجعة}} من $2",
        "javascripttest": "اختبار جافاسكربت",
-       "javascripttest-pagetext-noframework": "هذه الصفحة محجوزة لإجراء أختبارات الجافا سكريبت.",
-       "javascripttest-pagetext-unknownframework": "إطار اختبار غير معروف \"$1\".",
        "javascripttest-pagetext-unknownaction": "فعل غير معروف \"$1\".",
-       "javascripttest-pagetext-frameworks": "الرجاء اختيار أحد أطر الاختبارات التالية: $1",
-       "javascripttest-pagetext-skins": "قم باختيار الواجهة لإجراء الإحتبارات بها:",
        "javascripttest-qunit-intro": "راجع [$1 وثيقة الاختبار] على mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|صفحة المستخدم}} الخاصة بك",
        "tooltip-pt-anonuserpage": "صفحة المستخدم للأيبي الذي تقوم بالتحرير من خلاله",
        "pageinfo-language": "لغة محتوى الصفحة",
        "pageinfo-content-model": "نموذج محتوى الصفحة",
        "pageinfo-robot-policy": "فهرسة الروبوتات",
-       "pageinfo-robot-index": "مسموحة",
-       "pageinfo-robot-noindex": "غير مسموحة",
+       "pageinfo-robot-index": "مسموح بها",
+       "pageinfo-robot-noindex": "غير مسموح بها",
        "pageinfo-watchers": "عدد المراقبين",
        "pageinfo-visiting-watchers": "عدد مراقبي الصفحة الذين زاروا التعديلات الأخيرة",
        "pageinfo-few-watchers": "أقل من {{PLURAL:$1||مراقب واحد|مراقبين اثنين|$1 مراقبين|$1 مراقباً|$1 مراقب}}",
        "version-libraries-description": "الوصف",
        "version-libraries-authors": "المؤلفون",
        "redirect": "تحويل حسب  الملف , المستخدم ,الصفحة , معرف الدخول",
-       "redirect-legend": "تحويل إلى ملف أو صفحة",
        "redirect-summary": "هذه الصفحة الخاصة تحوّل إلى ملف (باسمه) أو صفحة (برقم إحدى مراجعاتها) أو إلى صفحة مستخدم (برقمه التعريفي). الاستخدام [[{{#Special:Redirect}}/file/Example.jpg]] أو [[{{#Special:Redirect}}/revision/328429]] أو [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "حوّل",
        "redirect-lookup": "ابحث في:",
        "sessionprovider-generic": "جلسات $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "جلسات قائمة على ملفات تعريف الارتباط (كوكيز)",
        "sessionprovider-nocookies": "قد يتم تعطيل الكوكيز. تأكد من تمكين ملفات تعريف الأرتباط وأبد مرةأخرى.",
-       "randomrootpage": "صفحة جذر عشوائية"
+       "randomrootpage": "صفحة جذر عشوائية",
+       "log-action-filter-block": "نوع المنع:",
+       "log-action-filter-delete": "نوع الحذف:",
+       "log-action-filter-protect": "نوع الحماية:",
+       "log-action-filter-upload": "نوع الرفع:",
+       "log-action-filter-all": "الكل",
+       "log-action-filter-block-block": "منع",
+       "log-action-filter-block-reblock": "منع التعديل",
+       "log-action-filter-block-unblock": "رفع المنع",
+       "log-action-filter-delete-delete": "حذف الصفحات",
+       "log-action-filter-delete-event": "حذف السجلات",
+       "log-action-filter-delete-revision": "حذف المراجعات",
+       "log-action-filter-protect-protect": "حماية",
+       "log-action-filter-protect-modify": "تعديل الحماية",
+       "log-action-filter-protect-unprotect": "رفع الحماية",
+       "log-action-filter-upload-upload": "رفع جديد",
+       "log-action-filter-upload-overwrite": "إعادة الرفع"
 }
index e444fd2..354c74b 100644 (file)
@@ -61,7 +61,7 @@
        "editfont-serif": "حروف بل زوايد",
        "sunday": "الحد",
        "monday": "لثنين",
-       "tuesday": "اÙ\84تÙ\84اتÙ\87",
+       "tuesday": "اÙ\84Ø«Ù\84اث",
        "wednesday": "لاربعه",
        "thursday": "الخميس",
        "friday": "الجمعه",
        "january": "جانفي",
        "february": "فيفري",
        "march": "مارس",
-       "april": "Ø£فريل",
+       "april": "افريل",
        "may_long": "ماي",
        "june": "جوان",
-       "july": "جويليي",
-       "august": "Ø£وت",
-       "september": "سبتامبر",
-       "october": "كتوبر",
-       "november": "نوفامبر",
+       "july": "جويلية",
+       "august": "اوت",
+       "september": "سبتمبر",
+       "october": "اكتوبر",
+       "november": "نوفمبر",
        "december": "ديسمبر",
        "january-gen": "جانفي",
        "february-gen": "فيفري",
        "jan": "جانفي",
        "feb": "فيفري",
        "mar": "مارس",
-       "apr": "Ø£فريل",
+       "apr": "افريل",
        "may": "ماي",
        "jun": "جوان",
-       "jul": "جويليي",
-       "aug": "Ø£وت",
-       "sep": "سبتامبر",
-       "oct": "كتوبر",
-       "nov": "نوفامبر",
-       "dec": "ديسامبر",
+       "jul": "جويلية",
+       "aug": "اوت",
+       "sep": "سبتمبر",
+       "oct": "اكتوبر",
+       "nov": "نوفمبر",
+       "dec": "ديسمبر",
        "january-date": "جانفيي $1",
        "february-date": "فيفريي $1",
        "march-date": "مارس $1",
        "december-date": "ديسمبر $1",
        "period-am": "تاع الصباح",
        "period-pm": "تاع العشيّة",
-       "pagecategories": "{{PLURAL:$1|Ù\81صÙ\8aÙ\84Ø©|Ù\81صÙ\8aÙ\84ات}}",
+       "pagecategories": "{{PLURAL:$1|Ù\83اتÙ\8aÚ­Ù\88رÙ\8a\83اتÙ\8aÚ­Ù\88رÙ\8aات}}",
        "category_header": "الباجه في التصنيف \"$1\"",
        "subcategories": "تصنيفات تحتيه",
        "category-media-header": "فيشيي ميلتيميديا فالكاتيكورى  \"$1\"",
        "mypage": "باجه",
        "mytalk": "تقرعيج",
        "anontalk": "تقرعيج",
-       "navigation": "تبحار",
+       "navigation": "ناڥيڭاسيون",
        "and": "&#32;و",
        "qbfind": "فتش",
        "qbbrowse": "اتجوّل فل مضمون",
        "faq": "المسقسية المتعاوده",
        "faqpage": "Project:سؤالات متكرره",
        "actions": "أفعال",
-       "namespaces": "بÙ\84اصة ØªØ§Ø¹ Ø£Ø³Ù\85Ù\88ات",
+       "namespaces": "بÙ\84اصة ØªØ§Ø¹ Ø§Ù\84اساÙ\85Ù\8a",
        "variants": "تنويعات",
-       "navigation-heading": "اÙ\84Ù\82اÙ\8aÙ\85Ø© ØªØ§Ø¹ Ø§Ù\84Ù\80تبحار",
+       "navigation-heading": "اÙ\84Ù\84Ù\8aستة ØªØ§Ø¹ Ø§Ù\84Ù\86اڥÙ\8aڭاسÙ\8aÙ\88Ù\86",
        "errorpagetitle": "غلطه",
        "returnto": "ولي إلى $1.",
-       "tagline": "من{{SITENAME}}",
+       "tagline": "من {{SITENAME}}",
        "help": "معاونة",
        "search": "فتّش",
        "searchbutton": "فتّش",
        "history": "تاريخ الملف",
        "history_short": "تاريخ",
        "updatedmarker": "مبدّل منلي الزيارة تاعي الـتالية",
-       "printableversion": "نسخة تاع طبيع",
-       "permalink": "Ù\88صÙ\8aÙ\84 دايم",
+       "printableversion": "ڥرسيون تقدر تطبعها",
+       "permalink": "Ù\84Ù\8aاÙ\86 دايم",
        "print": "امبريمي",
        "view": "اقرا",
        "view-foreign": "شوف على $1",
        "talkpage": "قرعَج على هاد الباجة",
        "talkpagelinktext": "تناقش",
        "specialpage": "باجة خوصوصيّة",
-       "personaltools": "دوزان شخصيه",
+       "personaltools": "دوزان مواليهم",
        "articlepage": "شوف الباجة تاع المحتاوا",
-       "talk": "مهادرة",
-       "views": "Ø´Ù\88Ù\81ات",
-       "toolbox": "دÙ\88زاÙ\86",
+       "talk": "تناقش",
+       "views": "Ø¢Ù\81Ù\8aشاج",
+       "toolbox": "ادÙ\8eÙ\88ات",
        "userpage": "شوف الباجة تاع المستعملي",
        "projectpage": "شوف الباجة تاع البروجي",
        "imagepage": "شوف الباجة تاع الفيشي",
        "viewhelppage": "شوف الباجة تاع المعاونة",
        "categorypage": "شوف الباجة تاع الصنيف",
        "viewtalkpage": "شوف التقرعيج",
-       "otherlanguages": "ب لوغات وحدُخرة",
+       "otherlanguages": "ب لوغات اخرين",
        "redirectedfrom": "(محول من $1)",
        "redirectpagesub": "باجة تاع التحوال",
        "redirectto": "حوّل لـ:",
-       "lastmodifiedat": "Ù\87اد Ø§Ù\84باجÙ\87 Ø±Ø§Ù\87Ù\8a ØªØ¨Ø¯Ù\91Ù\84ت Ù\86Ù\87ار Ø§Ù\84Ù\80 $1, Ø¹Ù\84Ù\89 Ø§Ù\84Ù\80ساعة $2.",
+       "lastmodifiedat": "Ù\87اذ Ø§Ù\84صÙ\81حة Ø±Ø§Ù\87Ù\8a ØªØ¨Ø¯Ù\91Ù\84ت Ø§Ø®Ù\91ر Ù\85رÙ\91Ø© Ù\86Ù\87ار $1Ø\8c Ù\85عا $2.",
        "viewcount": "هاد الباجة نشافت {{PLURAL:$1|خطرة وحدة|$1 خطرة}}.",
        "protectedpage": "باجة محضيّة",
-       "jumpto": "اÙ\82Ù\81ز ل:",
-       "jumptonavigation": "تبحار",
+       "jumpto": "سÙ\8aر ل:",
+       "jumptonavigation": "ناڥيڭاسيون",
        "jumptosearch": "فتّش",
        "view-pool-error": "اعدرونا، السربايات راهم مغبّنين ف هاد الوقيتة.\nبزّاف المستعمليّين راهم باغيين يشوفو هاد الباجة.\nاصبرو شي وقيتة قبل ما تحاولو تلحقو لها عاود.\n\n$1",
        "generic-pool-error": "اعدرونا، السربايات راهم مغبّنين ف هاد الوقيتة.\nبزّاف المستعمليّين راهم باغيين يشوفو هاد الباجة.\nاصبرو شي وقيتة قبل ما تحاولو تلحقو لها عاود.",
        "pool-errorunknown": "خلطة ماشي معروفة",
        "pool-servererror": "السربيس تاع العدّان راه حابس ( $1 ).",
        "poolcounter-usage-error": "غلطة تاع ستُعمال: $1",
-       "aboutsite": "على {{SITENAME}}",
-       "aboutpage": "Project:على",
+       "aboutsite": "كلّ شي على {{SITENAME}}",
+       "aboutpage": "Project:معلومات",
        "copyright": "المحتاوا راه تحت النسخة $1 تاع الليسانس، غير يلا كان مكتوب حاجاخرة.",
        "copyrightpage": "{{ns:project}}:حقوق النسخ",
        "currentevents": "الختيّارات",
        "currentevents-url": "Project:خبورات",
        "disclaimers": "تنبيهات",
-       "disclaimerpage": "Project:التنبيهات العامة",
+       "disclaimerpage": "Project:التنبيهات العامّة",
        "edithelp": "معونة",
        "helppage-top-gethelp": "معاونة",
-       "mainpage": "الپاجة اللولانيّة",
-       "mainpage-description": "اÙ\84پاجة Ø§Ù\84Ù\84Ù\88Ù\84اÙ\86Ù\8aÙ\91Ø©",
+       "mainpage": "الپاجة الاولانيّة",
+       "mainpage-description": "صÙ\81حة Ø§Ù\84استÙ\82باÙ\84",
        "policy-url": "Project:المقاون",
-       "portal": "بÙ\88رطاÙ\8a المجتمع",
-       "portal-url": "Project:بÙ\88رطاÙ\8a المجتمع",
-       "privacy": "السياسة تاع الخصوصية",
+       "portal": "بÙ\88ابة المجتمع",
+       "portal-url": "Project:بÙ\88ابة المجتمع",
+       "privacy": "السياسة تاع الخصوصيّة",
        "privacypage": "Project:السياسة تاع الخصوصيّة",
        "badaccess": "مشكل فل مسموحات",
        "badaccess-group0": "ماشي مقبول ليك تدير الشي الّي راك تسيّي تديرهُ.",
        "versionrequired": "النسخة $1 تاع ميدياويكي ملزومة",
        "versionrequiredtext": "النسخة $1 تاع ميدياويكي راهي ملزومة باش تنجم تستعمل هاد الباجة.\nشوف [[Special:Version|الباجة تاع النسخات باش تفهم كتَر على هاد الشي]]",
        "ok": "قابل",
-       "retrievedfrom": "جاÙ\8aبÙ\8aÙ\86Ù\87 من \"$1\"",
+       "retrievedfrom": "جاÙ\8aبÙ\8aÙ\86Ù\88 من \"$1\"",
        "youhavenewmessages": "عندك $1 ($2).",
        "youhavenewmessagesfromusers": "{{PLURAL:$4|عندك}} $1 من عند {PLURAL:$3|مستعملي واحد|زوج تاع المستعمليّين|$3 مستعملي}} ($2).",
        "youhavenewmessagesmanyusers": "عندك $1 من عند شحال من مستعملي ($2).",
        "feed-invalid": "النوع تاع التلقيمة ماشي مصلاح.",
        "feed-unavailable": "التلقيمات ما راهمش موجودين.",
        "site-rss-feed": "تيار آر‌إس‌إس $1",
-       "site-atom-feed": "$1 تيار آتوم",
+       "site-atom-feed": "سينيال آتوم تاع $1",
        "page-rss-feed": "تلقيمة RSS تاع \"$1\"",
        "page-atom-feed": "$1 تيار آتوم",
        "red-link-title": "$1 (الباجة ما كاينة شي)",
        "sort-descending": "رتّب بل نازولي",
        "sort-ascending": "رتّب بل طالوعي",
-       "nstab-main": "اÙ\84باجة",
+       "nstab-main": "صÙ\81Ø­ة",
        "nstab-user": "باجة{{GENDER:{{BASEPAGENAME}}|المستخدم|المستخدمة}}",
        "nstab-media": "باجة تاع ميديا",
        "nstab-special": "باجه خوصوصيّة",
        "nstab-template": "مودال",
        "nstab-help": "باجة تاع معاونة",
        "nstab-category": "تصنيف",
-       "mainpage-nstab": "الپاجة اللولانيّة",
+       "mainpage-nstab": "الپاجة الاولانيّة",
        "nosuchaction": "الشي الّي طلبتهُ ما كاينش",
        "nosuchactiontext": "الفعلة الّي مطلوبة فل URL ماشي مقبولة.\nبالاك ما دخّلتوش الـ URL كيما لازم ولا تاني تبّعتو كاش وصيل مغلوط.\nينجم تاني يكون كاين عُلّة فل لوجيسيال الّي مستعمل فـ {{SITENAME}}.",
        "nosuchspecialpage": "هاد الباجة الخوصوصيّة ما كاينش منها",
        "loginlanguagelabel": "اللوغه: $1",
        "suspicious-userlogout": "المطلب تاعك باش تسجّل خارج ما تسجّلش خاطر راه يبان مرسول من عند بحّار معطّل ولا  خزّان تاع وسّاط (proxy cache).",
        "createacct-another-realname-tip": "السميّة الحقّانيّة ماشي ملزومة.\nيلا تستعملها غادي تصلاح باش تنسّب ليك الخدمة الّي غادي تديرها.",
-       "pt-login": "دخÙ\84Ø©",
+       "pt-login": "ادخÙ\84",
        "pt-login-button": "دخول",
        "pt-createaccount": "اصنع حساب",
        "pt-userlogout": "الخروج",
        "revertmerge": "فرق",
        "history-title": " «$1»: تاريخ المراجعات",
        "difference-title": "فروقات بين التبدالات تاع \"$1\"",
-       "lineno": "سطر$1:",
+       "lineno": "سطر $1:",
        "compareselectedversions": "كومباري بين نسختين مخيرين",
        "editundo": "نحي",
        "diff-multi-sameuser": "({{PLURAL:$1|تبديلة متوسّطة وحدة|$1 تبديلات متوسّطين}} ماشي {{PLURAL:$1|مورّية|$1 مورّيين}} من عند نفس المستعملي)",
        "action-edit": "عدل هاذ الباجه",
        "nchanges": "$1 تبديله{{PLURAL:$1||s}}",
        "enhancedrc-history": "تاريخ",
-       "recentchanges": "اÙ\84تبداÙ\84ات Ø§Ù\84تÙ\88اÙ\84ا",
+       "recentchanges": "اÙ\84تبداÙ\84ات Ø§Ù\84اخÙ\91رة",
        "recentchanges-legend": "واش تختار ف`التبدالات التوالا",
        "recentchanges-summary": "اجبر التبدالات اللواخر الّي صراو ف هاد الصفحة.",
        "recentchanges-feed-description": "تبع التبديلات الجدد للويكي في هاذ التيار .",
        "recentchangeslinked-summary": "هاذي ليستة تع التبديلات اللي تمت هاذ الخطرة للباجات الموصولة من باجة معينة (ولا للأعضاء الداخلين في تصنيف معين).\nالصفحات في [[Special:Watchlist|ليستت مراقبة نتاعك]] '''مغلظه'''",
        "recentchangeslinked-page": "اسم الباجه:",
        "recentchangeslinked-to": "بين التبديلات للباجات الموصولة للباجه المعطية عوضا العكس",
-       "upload": "طلع فيشي",
+       "upload": "طلّع فيشيي",
        "uploadlogpage": "ريجيستر رفع الفيشيات",
        "filedesc": "ملخص",
        "license": "ترخيص:",
        "nolinkstoimage": "ما كانش باجات موصوله لهاذ الفيشي.",
        "sharedupload-desc-here": "هاذ الملف جاي من $1. يمكن يكون مستعمل من بروجيات وحد أخرين.\nالتوصيف نتاعو في [$2 باجت الصفات] محطوطه هنا لتحت.",
        "upload-disallowed-here": "ما تنحمش تعدّل هاد التصويرة",
-       "randompage": "باجة Ø¹Ù\84Ù\89 الزهر",
+       "randompage": "صÙ\81حة Ø¹ الزهر",
        "statistics": "إحصائيّات",
        "nbytes": "{{PLURAL:$1|بايت 1|$1 بايت}}",
        "nmembers": "$1 اعضاء{{PLURAL:$1||s}}",
        "tooltip-invert": "علّم هاد المقّبسة باش تخبّي التبدالات تاع الصفحات الّي فيها وسَع` التسمية (و وسَع التسمية المربوط يلا كاين)",
        "namespace_association": "وسَع التسمية المربوط",
        "tooltip-namespace_association": "علّم على هاد المقيبسة باش تدخّل تاني المهادرة ولا وسَع التسمية تاع الموضوع المربوط معا وسَع التسمية المسيليكسيوني",
-       "blanknamespace": "أساسي",
+       "blanknamespace": "رئÙ\8aسي",
        "contributions": "مساهمات {{GENDER:$1|المستخدم|المستخدمه}}",
        "contributions-title": "مساهمات {{GENDER:$1|المستخدم|المستخدمه}} $1",
        "mycontris": "المساهمات تاعي",
        "sp-contributions-username": "عنوان أيبي والال اسم مستخدم:",
        "sp-contributions-toponly": "ما تورّي غير المشاركات التوالا تاع المقالات",
        "sp-contributions-submit": "تفتاش",
-       "whatlinkshere": "واش واصل هنا",
+       "whatlinkshere": "شنوّ يوصّل ل هنا",
        "whatlinkshere-title": "الباجات اللي تقين في \"$1\"",
        "whatlinkshere-page": "الباجه:",
        "linkshere": "هاذ الباجات يوصلو إلى '''[[:$1]]''':",
        "tooltip-pt-preferences": "الختيّارات {{GENDER:|تاعك}}",
        "tooltip-pt-watchlist": "ليستت الباجات الي راك أتبع تبديلاتهم",
        "tooltip-pt-mycontris": "الليستة تاع المساهمات {{GENDER:|تاعك}}",
-       "tooltip-pt-login": "Ù\85ادابÙ\8aÙ\83 ØªØ³Ø¬Ù\84 Ø§Ù\84دخÙ\84Ø© ØªØ§Ø¹Ù\83 Ø\8c Ø¨ØµÙ\91Ø­ Ù\87ادا Ù\85اشÙ\8a Ù\85Ù\84زÙ\88Ù\85",
+       "tooltip-pt-login": "Ù\85اذا Ø¨Ù\8aÙ\83 ØªØ¯Ø®Ù\84 Ù\81 Ø§Ù\84Ù\83Ù\88Ù\86ت ØªØ§Ø¹Ù\83Ø\9b Ù\84اÙ\83Ù\86 Ù\87اذا Ù\85ا Ø´Ù\8a Ù\85Ù\84زÙ\88Ù\85 Ø¹Ù\84Ù\8aÙ\83",
        "tooltip-pt-logout": "سجل خروج",
-       "tooltip-pt-createaccount": "Ù\86Ù\86صح Ø¨Ø§Ø´ ØªØµÙ\86ع Ø­Ø³Ø§Ø¨ Ù\88 ØªØ³Ø¬Ù\84 Ø¯Ø®Ù\84تÙ\83 ; Ø¹Ù\84Ù\89 Ù\83Ù\84 Ø­Ø§Ù\84 Ù\85اÙ\87Ù\88Ø´ ضروري",
-       "tooltip-ca-talk": "مناقشه على هاد باجت المحتوا",
-       "tooltip-ca-edit": "بدÙ\91Ù\84 Ù\87اد Ø§Ù\84Ù\80صÙ\81Ø­Ù\87",
+       "tooltip-pt-createaccount": "Ù\85اذا Ø¨Ù\8aÙ\86ا Ù\84Ù\88 Ù\83اÙ\86 ØªØ¹Ù\85Ù\84 Ø­Ø³Ø§Ø¨ Ù\88تدخÙ\84 Ø¨Ù\8aÙ\87Ø\9b Ù\88 Ù\84اÙ\83Ù\86 Ù\87اذا Ù\85ا Ø´Ù\8a ضروري",
+       "tooltip-ca-talk": "مناقشة على هاذ الصفحة تاع المحتوى",
+       "tooltip-ca-edit": "بدÙ\91Ù\84 Ù\81 Ù\87اذ Ø§Ù\84Ù\80صÙ\81حة",
        "tooltip-ca-addsection": "ابدأ طرف جديد",
        "tooltip-ca-viewsource": "هاذ الباجه محميه. و شنو تقدرو تشوفو الأصلي نتاعها",
-       "tooltip-ca-history": "المراجعات التوالا تاع الباجة (معا المساهمين تاوعها)",
+       "tooltip-ca-history": "الڥرسيونات القدام ديال هاذ الصفحة",
        "tooltip-ca-protect": "بروتيجي هاذالباجه",
        "tooltip-ca-delete": "امحي هاذ الباجه",
        "tooltip-ca-move": "بدل أسم هذ الباجه",
        "tooltip-ca-watch": "زيد هذ الباجة لل ليستة تاعك تاع التتباع",
        "tooltip-ca-unwatch": "اقلع هاد الباجة منل ليستة تاعك تاع التتباع",
        "tooltip-search": " فتّش في {{SITENAME}}",
-       "tooltip-search-go": "رÙ\88Ø­ Ù\84 Ø¨Ø§Ø¬Ø© Ø¹Ù\86دÙ\87ا Ø°Ø§Ù\83 Ø§Ù\84آسÙ\85 Ø¨Ø¯Ù\91ات Ù\8aÙ\84ا Ù\83اÙ\86ت Ù\83اÙ\8aÙ\86Ø©",
-       "tooltip-search-fulltext": "فتّش على باجة ب هاد الكتبة",
-       "tooltip-p-logo": "زÙ\88ر Ø§Ù\84پاجة Ø§Ù\84Ù\84Ù\88Ù\84اÙ\86Ù\8aÙ\91Ø©",
+       "tooltip-search-go": "رÙ\88Ø­ Ù\84 ØµÙ\81حة Ø¹Ù\86دÙ\87ا Ù\86Ù\81س Ù\87اذ Ø§Ù\84اسÙ\85 Ø§Ù\8aذا ØªÙ\88جÙ\92دت",
+       "tooltip-search-fulltext": "فتّش ع الپاجات الّي فيها هاذ النصّ",
+       "tooltip-p-logo": "زÙ\88ر ØµÙ\81حة Ø§Ù\84استÙ\82باÙ\84",
        "tooltip-n-mainpage": "زور الپاجة اللولانيّة",
-       "tooltip-n-mainpage-description": "زÙ\88ر Ø§Ù\84پاجة Ø§Ù\84Ù\84Ù\88Ù\84اÙ\86Ù\8aÙ\91Ø©",
-       "tooltip-n-portal": "على الپروجي،واش تقدر تدير، وين تصيب واش تحتاج",
-       "tooltip-n-currentevents": "صÙ\8aب Ø®Ø¨Ø§Ø±Ø§Øª Ù\85ستÙ\91رÙ\8aÙ\86 Ø¹Ù\84Ù\89 Ø§Ù\84صÙ\88اÙ\84Ø­ Ø§Ù\84Ù\91Ù\8a Ø±Ø§Ù\87Ù\85 Ù\8aصراÙ\88 Ø¶Ø±Ù\83ا",
-       "tooltip-n-recentchanges": "الليستة تاع التبدالات الجديدة فل ويكي",
-       "tooltip-n-randompage": "Ø·Ù\84Ù\91ع Ø¨Ø§Ø¬Ù\87 Ø¹Ù\84Ù\89 الزهر",
-       "tooltip-n-help": "بلاصة المعونة",
-       "tooltip-t-whatlinkshere": "Ù\84Ù\8aستة ØªØ§Ø¹ Ù\83اÙ\85Ù\84 Ø¨Ø§Ø¬Ø§Øª Ø§Ù\84Ù\85حتاÙ\88ا Ø§Ù\84Ù\88اصÙ\84Ù\87 هنا",
+       "tooltip-n-mainpage-description": "زÙ\88ر ØµÙ\81حة Ø§Ù\84استÙ\82باÙ\84",
+       "tooltip-n-portal": "ع المشروع، شنوّ تقدر تدير، فين تلقى الحاجات الّي حاجتك بيها",
+       "tooltip-n-currentevents": "Ø´Ù\88Ù\81 Ø§Ø´ Ù\82اعد Ù\8aصÙ\8aر",
+       "tooltip-n-recentchanges": "ليستة تاع التبدالات الاخّرين ف الويكي",
+       "tooltip-n-randompage": "شرجÙ\8a ØµÙ\81حة Ø¹ الزهر",
+       "tooltip-n-help": "بلاصة المعاونة",
+       "tooltip-t-whatlinkshere": "Ù\84Ù\8aستة Ø¯Ù\8aاÙ\84 ØµÙ\81حات Ø§Ù\84Ù\88Ù\8aÙ\83Ù\8a Ø§Ù\84Ù\83Ù\84Ù\91 Ø§Ù\84Ù\91Ù\8a ØªÙ\88صÙ\91Ù\84 Ù\84 هنا",
        "tooltip-t-recentchangeslinked": "ليستة تاع التبديلات التوالا تاع الباجات الّي عندهم رباط معا هادي",
        "tooltip-feed-atom": "سيلان آتوم تاع هاد الباجة",
        "tooltip-t-contributions": "شوف ليستة تاع المساهمات تاع {{GENDER:$1|هاد المستعملي|هاد المستعمليّة}}",
        "tooltip-t-emailuser": "أرسل بريه لهاذ المستخدم",
-       "tooltip-t-upload": "أرسÙ\84 ØªØµÙ\88Ù\8aرة Ù\88 Ø¥Ù\84ا Ø£Ù\8a Ù\85Ù\84Ù\81 Ù\85Ù\8aدÙ\8aا Ù\84Ù\84سرÙ\81ر",
-       "tooltip-t-specialpages": "ليستة تاع كامل الباجات الخصوصيّة",
-       "tooltip-t-print": "نسخه لهاذ الباجه قابله للطبيع",
+       "tooltip-t-upload": "Ø·Ù\84Ù\91ع Ù\81Ù\8aØ´Ù\8aÙ\8aات",
+       "tooltip-t-specialpages": "ليستة تاع الباجات الخاصّين كلّهم",
+       "tooltip-t-print": "ڥرسيون تقدر تطبعها",
        "tooltip-t-permalink": "وصيل دايم رايح ل هاد النسخة تاع الباجة",
        "tooltip-ca-nstab-main": "شوف باجه المحتوى",
        "tooltip-ca-nstab-user": "شوف باجت المستعمل",
        "tooltip-undo": "\"نحّي\" فاصي هاد الـمعاودة و حلّ تاقة تاع تبدال بشوفه قبلانيّه. تخلّي باش ترجع لل معاوده التاليه و تزيد الـسبّة علاش فل قابسه تاع الـحويصله.",
        "tooltip-summary": "دخل تلخيص صغير",
        "simpleantispam-label": "مسيّة ضدّ السبام.\nما تعمّرش هادا!",
-       "pageinfo-toolboxlink": "Ù\85عÙ\84Ù\88Ù\85ات Ø¹Ù\84Ù\89 Ù\87اد Ø§Ù\84باجة",
+       "pageinfo-toolboxlink": "Ù\85عÙ\84Ù\88Ù\85ات Ø¹Ù\84Ù\89 Ù\87اد Ø§Ù\84صÙ\81Ø­ة",
        "previousdiff": "→ التعديل الي قبل",
        "nextdiff": "التبديل الجاي ←",
        "file-info-size": "$1 × $2 بكسل حجم الملف: $3، نوع MIME: $4",
        "watchlisttools-raw": "موديفي ليستت التبيعه الخام",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|تقرعيج]])",
        "duplicate-defaultsort": "'''توليه:''' مفتاح التستيف الافتراضي \"$2\" ديباسا مفتاح التستيف الافتراضي التالي\"$1\".",
-       "specialpages": "الباجات الخصوصية",
+       "specialpages": "الپاجات الخاصّين",
        "external_image_whitelist": " #<pre>خلى هاذ السطر كيما راه\n#حط منثورات التعبيرات المنتظمة (برك الجزء الي يروح بين //) بالتحت\n#هاذ يكون مطابقتها مع مسارات التصاوير البرانيه (الموصولة بصفه مباشره)\n#هاذي الي تشبهغادي تنعرض  كتصاور، خلاف هذا برك وصيلة للتصويرة غادي تنعرض\n#السطور اللي تبدأا ب# تعتبر تعليقات\n#هذا لا يتأثر بحالة الحروف\n\n#حط كامل منثورات التعبيرات المنتظمة فوق هذا السطر. خلي هاذ السطر سواسوا كيما هو</pre>",
        "tag-filter": "صفاية[[Special:Tags|الوشام]]:",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1||وسم|وسمان|وسوم}}]]: $2)",
        "logentry-move-move": "{{GENDER:$2|نقّل|نقّلت}} $1 الصفحة $3 لـ $4",
        "logentry-newusers-create": "راه تفتح حساب {{GENDER:$2|المستخدم|المستخدمه}} $1",
        "logentry-upload-upload": " {{GENDER:$2|نزّل|نزّلت}} $1 $3",
-       "searchsuggest-search": "تفتاش"
+       "searchsuggest-search": "فتّش"
 }
index ef8ef21..f547a60 100644 (file)
        "nocookieslogin": "{{SITENAME}} usa «cookies» pa identificar a los usuarios.\nTien les «cookies» desactivaes.\nPor favor activeles y vuelva a intentalo.",
        "nocookiesfornew": "La cuenta nun se creó porque nun pudimos confirmar l'orixe.\nComprueba que tienes activaes les «cookies», recarga esta páxina y vuelvi a intentalo.",
        "noname": "Nun conseñasti un nome d'usuariu válidu.",
-       "loginsuccesstitle": "Aniciu de sesión correutu",
+       "loginsuccesstitle": "Identificáu",
        "loginsuccess": "'''Aniciasti sesión en {{SITENAME}} como «$1».'''",
        "nosuchuser": "Nun hai nengún usuariu col nome «$1».\nLos nomes d'usuariu distinguen mayúscules y minúscules.\nMira que tea bien escritu o [[Special:UserLogin/signup|crea una cuenta nueva]].",
        "nosuchusershort": "Nun hai nengún usuariu col nome «$1».\nMira que tea bien escritu.",
        "createaccount-title": "Creación de cuenta pa {{SITENAME}}",
        "createaccount-text": "Daquién creó una cuenta cola to direición de corréu electrónicu en {{SITENAME}} ($4) col nome «$2», y cola contraseña «$3».\nAgora tendríes d'aniciar sesión y camudar la contraseña.\n\nPues escaecer esti mensaxe si esta cuenta creóse por error.",
        "login-throttled": "Ficisti demasiaos intentos d'aniciu de sesión recientes.\nPor favor espera $1 enantes d'intentalo otra vuelta.",
-       "login-abort-generic": "Falló la identificación - Encaboxao",
+       "login-abort-generic": "Falló l'aniciu de sesión - Encaboxao",
        "login-migrated-generic": "La to cuenta migróse ya'l to nome d'usuariu yá nun esiste nesta wiki.",
        "loginlanguagelabel": "Llingua: $1",
        "suspicious-userlogout": "La to solicitú de zarrar sesión refugose porque paez qu'unvióla un restolador frañíu o un proxy de caché.",
        "newpassword": "Contraseña nueva:",
        "retypenew": "Vuelvi a escribir la contraseña nueva:",
        "resetpass_submit": "Configurar la contraseña y aniciar sesión",
-       "changepassword-success": "¡Camudóse la contraseña correutamente!",
+       "changepassword-success": "Camudóse la contraseña.",
        "changepassword-throttled": "Ficisti demasiaos intentos d'aniciu de sesión recientes.\nPor favor espera $1 enantes d'intentalo otra vuelta.",
        "botpasswords": "Contraseñes de bots",
        "botpasswords-summary": "Les <em>contraseñes de bot</em> permiten l'accesu a una cuenta d'usuariu por aciu de la API sin usar les credenciales d'accesu de la cuenta principal. Los permisos d'usuariu disponibles al aniciar sesión con una contraseña de bot puen tar torgaos.\n\nSi nun sabes pa qué val esto, probablemente nun tendríes d'usalo. Naide tendría de pidite nunca que xeneres una d'estes y que-y la deas.",
        "botpasswords-insert-failed": "Nun pudo amestase'l nome de bot «$1». ¿Taba añadíu yá?",
        "botpasswords-update-failed": "Nun pudo anovase'l nome de bot «$1». ¿Desaniciaríase?",
        "botpasswords-created-title": "Creóse la contraseña de bot",
-       "botpasswords-created-body": "La contraseña de bot «$1» creóse correchamente.",
+       "botpasswords-created-body": "Creóse la contraseña del bot llamáu «$1» del usuariu «$2».",
        "botpasswords-updated-title": "Anovóse la contraseña de bot",
-       "botpasswords-updated-body": "La contraseña de bot «$1» anovóse correchamente.",
+       "botpasswords-updated-body": "Anovóse la contraseña del bot llamáu «$1» del usuariu «$2».",
        "botpasswords-deleted-title": "Desanicióse la contraseña de bot",
-       "botpasswords-deleted-body": "La contraseña de bot «$1» desanicióse.",
+       "botpasswords-deleted-body": "Desanicióse la contraseña del bot llamáu «$1» del usuariu «$2».",
        "botpasswords-newpassword": "La nueva contraseña p'aniciar sesión con strong>$1</strong> ye <strong>$2</strong>. <em>Por favor, rexistra esto pa referencies futures.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider nun ta disponible.",
        "botpasswords-restriction-failed": "Hai torgues de contraseña de bot que torgaron esti aniciu de sesión.",
        "resetpass-no-info": "Tienes d'aniciar sesión pa entrar direutamente a esta páxina.",
        "resetpass-submit-loggedin": "Camudar la contraseña",
        "resetpass-submit-cancel": "Encaboxar",
-       "resetpass-wrong-oldpass": "Contraseña temporal o actual inválida.\nSeique yá camudaras correutamente la contraseña o que pidieras una nueva contraseña temporal.",
+       "resetpass-wrong-oldpass": "Contraseña temporal o actual inválida.\nSeique yá camudaras la contraseña o que pidieras una nueva contraseña temporal.",
        "resetpass-recycled": "Por favor, cambie la so contraseña por otra distinta de la actual.",
        "resetpass-temp-emailed": "Anició sesión con un códigu temporal unviáu per corréu electrónicu.\nPa completar l'aniciu de sesión, tien de definir una nueva contraseña equí:",
        "resetpass-temp-password": "Contraseña temporal:",
        "newarticle": "(Nuevu)",
        "newarticletext": "Siguisti un enllaz a un artículu qu'inda nun esiste.\nPa crear la páxina, empecipia a escribir nel cuadru d'embaxo (mira la [$1 páxina d'ayuda] pa más información).\nSi llegasti equí por enquivocu, calca nel botón <strong>atrás</strong> del to restolador.",
        "anontalkpagetext": "----\n''Esta ye la páxina d'alderique pa un usuariu anónimu qu'inda nun creó una cuenta o que nun la usa.''\nPola mor d'ello ha usase la direición numbérica IP pa identificalu/la.\nTala IP pue compartise por varios usuarios.\nSi yes un usuariu anónimu y notes qu'hai comentarios irrelevantes empobinaos pa ti, por favor [[Special:UserLogin/signup|crea una cuenta]] o [[Special:UserLogin/signup|identifícate]] pa torgar futures confusiones con otros usuarios anónimos.",
-       "noarticletext": "Nestos momentos nun hai testu nesta páxina.\nPues [[Special:Search/{{PAGENAME}}|buscar esti títulu de páxina]] n'otres páxines,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar los rexistros rellacionaos],\no [{{fullurl:{{FULLPAGENAME}}|action=edit}} editar esta páxina]</span>.",
+       "noarticletext": "Nestos momentos nun hai testu nesta páxina.\nPuedes [[Special:Search/{{PAGENAME}}|buscar esti títulu de páxina]] n'otres páxines,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar los rexistros rellacionaos],\no [{{fullurl:{{FULLPAGENAME}}|action=edit}} crear esta páxina]</span>.",
        "noarticletext-nopermission": "Nestos momentos nun hai testu nesta páxina.\nPue [[Special:Search/{{PAGENAME}}|buscar esti títulu de páxina]] n'otres páxines o <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar los rexistros rellacionaos]</span>, pero nun tiene permisu pa crear esta páxina.",
        "missing-revision": "La revisión #$1 de la páxina llamada \"{{FULLPAGENAME}}\" nun esiste.\n\nDe vezu la causa d'esto ye siguir un enllaz antiguu del historial a una páxina que se desanició.\nSe puen alcontrar más detalles nel [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} rexistru de desanicios].",
        "userpage-userdoesnotexist": "La cuenta d'usuariu «$1» nun ta rexistrada.\nPor favor comprueba si quies crear/editar esta páxina.",
        "previewnote": "'''Alcuerdate de qu'esto ye sólo una vista previa.'''\n¡Los cambios entá nun se guardaron!",
        "continue-editing": "Dir al área d'edición",
        "previewconflict": "Esta vista previa amuesa'l testu del área d'edición d'arriba tal como apaecerá si escueyes guardar.",
-       "session_fail_preview": "'''¡Sentímoslo muncho! Nun pudimos procesar la to edición porque hebo una perda de datos de la sesión.'''\nPor favor, vuelvi a intentalo.\nSi inda nun funciona, intenta [[Special:UserLogout|colar]] y volver a aniciar sesión.",
+       "session_fail_preview": "¡Sentímoslo muncho! Nun pudimos procesar la edición porque hebo una perda de datos de la sesión.\n\nSeique zarróse la sesión. <strong>Comprueba si tienes abierta la sesión y vuelve a intentalo</strong>.\nSi inda nun funcionara, tenta [[Special:UserLogout|colar]] y volver a aniciar sesión y comprueba que'l restolador permite les cookies d'esti sitiu.",
        "session_fail_preview_html": "¡Sentímoslo! Nun pudo procesase la to edición por aciu d'una perda de datos de la sesión.\n\n<em>Como {{SITENAME}} tien el HTML puru activáu, la vista previa ta tapecida como precaución escontra ataques en JavaScript.</em>\n\n<strong>Si esti ye un intentu llexítimu d'edición, por favor vuelvi a intentalo.</strong>\nSi inda nun funciona, intenta [[Special:UserLogout|colar]] y volver a aniciar sesión, y comprueba que'l to restolador permite les cookies d'esti sitiu.",
        "token_suffix_mismatch": "'''La to edición nun s'aceutó porque'l to navegador mutiló los caráuteres de puntuación nel editor.'''\nLa edición nun foi aceutada pa prevenir corrupciones na páxina de testu.\nDacuando esto pasa por usar un serviciu proxy anónimu basáu en web que tenga fallos.",
        "edit_form_incomplete": "'''Delles partes del formulariu d'edición nun llegaron al sirvidor; comprueba que les ediciones tean intactes y vuelvi a tentalo.'''",
        "revdelete-unsuppress": "Desaniciar les torgues nes revisiones restauraes",
        "revdelete-log": "Motivu:",
        "revdelete-submit": "Aplicar a {{PLURAL:$1|la revisión seleicionada|les revisiones seleicionaes}}",
-       "revdelete-success": "'''Visibilidá de revisiones anovada correutamente.'''",
+       "revdelete-success": "Cambiada la visibilidá de revisiones.",
        "revdelete-failure": "'''La visibilida de revisiones nun se pudo anovar:'''\n$1",
-       "logdelete-success": "Configuróse correutamente la visibilidá del rexistru.",
+       "logdelete-success": "Configuróse la visibilidá del rexistru.",
        "logdelete-failure": "'''Nun se pudo configurar la visibilidá del rexistru:'''\n$1",
        "revdel-restore": "camudar visibilidá",
        "pagehist": "Historial de la páxina",
        "mergehistory-done": "$3 {{PLURAL:$3|revisión|revisiones}} de $1 {{PLURAL:$3|fusionóse|fusionáronse}} en [[:$2]].",
        "mergehistory-fail": "Nun pudo facese la fusión d'historiales, por favor comprueba los parámetros de páxina y hora.",
        "mergehistory-fail-bad-timestamp": "La marca de tiempu ye inválida.",
+       "mergehistory-fail-invalid-source": "La páxina d'orixe ye inválida.",
+       "mergehistory-fail-invalid-dest": "La páxina de destín ye inválida.",
+       "mergehistory-fail-no-change": "La fusión d'historiales nun fusionó nenguna revisión. Por favor, comprueba los parámetros de páxina y tiempu.",
+       "mergehistory-fail-permission": "Permisos insuficientes pa fusionar los historiales.",
+       "mergehistory-fail-self-merge": "Les páxines d'orixe y destín son la mesma.",
+       "mergehistory-fail-timestamps-overlap": "Les revisiones de la fonte se sobreponen o vienen después de les revisiones del destín.",
        "mergehistory-fail-toobig": "Nun pudo fusionase l'historial porque moveríense más del máximu de $1 {{PLURAL:$1|revisión|revisiones}}.",
        "mergehistory-no-source": "La páxina d'orixe $1 nun esiste.",
        "mergehistory-no-destination": "La páxina de destín $1 nun esiste.",
        "userrights-changeable-col": "Grupos que pues camudar",
        "userrights-unchangeable-col": "Grupos que nun pues camudar",
        "userrights-conflict": "¡Conflictu de cambiu de permisos d'usuariu! Por favor, revise y confirme los cambios.",
-       "userrights-removed-self": "Retiró correutamente los sos propios drechos. Poro, yá nun tendrá accesu a esta páxina.",
+       "userrights-removed-self": "Desaniciasti los tos propios permisos. Poro, yá nun tienes accesu a esta páxina.",
        "group": "Grupu:",
        "group-user": "Usuarios",
        "group-autoconfirmed": "Usuarios autoconfirmaos",
        "recentchangeslinked-page": "Nome de la páxina:",
        "recentchangeslinked-to": "Amosar los cambios de les páxines qu'enllacen en cuenta de los de la páxina dada",
        "recentchanges-page-added-to-category": "[[:$1]] amestóse a la categoría",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] y {{PLURAL:$2|otra páxina|otres $2 páxines}} amestaes a la categoría",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] y [[Special:WhatLinksHere/$1|{{PLURAL:$2|otra páxina|otres $2 páxines}}]] amestaes a la categoría",
        "recentchanges-page-removed-from-category": "[[:$1]] desanicióse de la categoría",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] y {{PLURAL:$2|otra páxina|otres $2 páxines}} desaniciaes de la categoría",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] y [[Special:WhatLinksHere/$1|{{PLURAL:$2|otra páxina|otres $2 páxines}}]] desaniciaes de la categoría",
        "autochange-username": "Cambiu automáticu de MediaWiki",
        "upload": "Xubir ficheru",
        "uploadbtn": "Xubir ficheru",
        "backend-fail-read": "Nun se pudo lleer el ficheru $1.",
        "backend-fail-create": "Nun se pudo escribir el ficheru $1.",
        "backend-fail-maxsize": "Nun se pudo escribir el ficheru  $1  porque ye mayor de {{PLURAL:$2|un byte|$2 bytes}}.",
-       "backend-fail-readonly": "Nesti momentu el motor d'almacenamientu \"$1\" ta en mou de sólo llectura. El motivu dau foi: \"$2\"",
+       "backend-fail-readonly": "Nesti momentu el motor d'almacenamientu \"$1\" ta en mou de sólo llectura. El motivu dau ye: <em>$2</em>",
        "backend-fail-synced": "El ficheru \"$1\" ta nún estáu inconsistente colos motores d'almacenamientu internos",
        "backend-fail-connect": "Nun se pudo coneutar col motor d'almacenamientu \"$1\".",
        "backend-fail-internal": "Hebo un fallu desconocíu nel motor d'almacenamientu \"$1\".",
        "uploadstash-summary": "Esta páxina ufre accesu a ficheros que tan xubíos (o en procesu de xubía), pero qu'entá nun s'espublizaron na wiki. Estos ficheros nun son visibles pa naide, sacante l'usuariu que los xubió.",
        "uploadstash-clear": "Desaniciar los ficheros de la reserva",
        "uploadstash-nofiles": "Nun tienes ficheros na reserva.",
-       "uploadstash-badtoken": "Nun se pudo facer esa operación, seique porque caducó la identificación pa editar. Vuelvi a intentalo.",
-       "uploadstash-errclear": "Nun se pudieron desaniciar los ficheros.",
+       "uploadstash-badtoken": "Nun pudo facese esa operación. Seique caducó la identificación pa editar. Vuelve a tentalo.",
+       "uploadstash-errclear": "Falló'l desaniciu de los ficheros.",
        "uploadstash-refresh": "Anovar la llista de ficheros",
        "invalid-chunk-offset": "Allugamientu inválidu del fragmentu",
        "img-auth-accessdenied": "Accesu denegáu",
        "apihelp": "Ayuda de la API",
        "apihelp-no-such-module": "Nun s'alcuentra'l módulu «$1».",
        "apisandbox": "Zona de pruebes API",
+       "apisandbox-jsonly": "Necesítase JavaScript pa usar la zona de pruebes de la API.",
        "apisandbox-api-disabled": "La API ta desactivada nesti sitiu.",
        "apisandbox-intro": "Usa esta páxina pa esperimentar cola <strong>API de serviciu web de MediaWiki</strong>.\nConsulta [[mw:API:Main page|la documentación de la API]] pa más detalles tocante al so usu. Exemplu: [//www.mediawiki.org/wiki/API#A_simple_example llamar al conteníu d'una Páxina principal]. Seleiciona una aición pa ver más exemplos.\n\nTen presente que, anque esto ye una zona de pruebes, les aiciones que faigas nesta páxina puen camudar la wiki.",
        "apisandbox-fullscreen": "Espander el panel",
+       "apisandbox-fullscreen-tooltip": "Espander el panel de la zona de pruebes pa llenar la pantalla del navegador.",
+       "apisandbox-unfullscreen": "Amosar la páxina",
+       "apisandbox-unfullscreen-tooltip": "Amenorgar el panel de la zona de pruebes pa que tean disponibles los enllaces de navegación de MediaWiki.",
        "apisandbox-submit": "Facer solicitú",
        "apisandbox-reset": "Llimpiar",
+       "apisandbox-retry": "Reintentar",
+       "apisandbox-loading": "Cargando la información pal módulu de la API «$1»...",
+       "apisandbox-load-error": "Asocedió un error al cargar la información del módulu de la API «$1»: $2",
+       "apisandbox-no-parameters": "Esti módulu de la API nun tien parámetros.",
+       "apisandbox-helpurls": "Enllaces d'ayuda",
        "apisandbox-examples": "Exemplos",
+       "apisandbox-dynamic-parameters": "Más parámetros",
+       "apisandbox-dynamic-parameters-add-label": "Amestar parámetru:",
+       "apisandbox-dynamic-parameters-add-placeholder": "Nome del parámetru",
+       "apisandbox-dynamic-error-exists": "Yá existe un parámetru llamáu «$1».",
+       "apisandbox-deprecated-parameters": "Parámetros anticuaos",
+       "apisandbox-fetch-token": "Rellenu automáticu del pase",
+       "apisandbox-submit-invalid-fields-title": "Dalgunos campos son inválidos",
+       "apisandbox-submit-invalid-fields-message": "Por favor, igua los campos señalaos y téntalo nuevamente.",
        "apisandbox-results": "Resultaos",
+       "apisandbox-sending-request": "Unviando solicitú a la API...",
+       "apisandbox-loading-results": "Recibiendo los resultaos de la API...",
+       "apisandbox-results-error": "Asocedió un error al cargar la respuesta de la consulta API: $1.",
        "apisandbox-request-url-label": "URL de la solicitú:",
        "apisandbox-request-time": "Duración de la solicitú: {{PLURAL:$1|$1 ms}}",
+       "apisandbox-results-fixtoken": "Igua'l token y vuelve a unviar",
+       "apisandbox-results-fixtoken-fail": "Nun pudo recuperase'l token «$1».",
+       "apisandbox-alert-page": "Los campos d'esta páxina nun son válidos.",
+       "apisandbox-alert-field": "El valor d'esti campu nun ye válidu.",
        "booksources": "Fontes de llibros",
        "booksources-search-legend": "Busca de fontes de llibros",
        "booksources-search": "Buscar",
        "delete-toobig": "Esta páxina tien un historial d'ediciones grande, más de $1 {{PLURAL:$1|revisión|revisiones}}.\nRestrinxóse l'esborráu d'estes páxines pa evitar perturbaciones accidentales de {{SITENAME}}.",
        "delete-warning-toobig": "Esta páxina tien un historial d'ediciones grande, más de $1 {{PLURAL:$1|revisión|revisiones}}.\nEsborralu pue perturbar les operaciones de la base de datos de {{SITENAME}};\nobra con precaución.",
        "deleteprotected": "Nun pues desaniciar esta páxina porque ta protexida.",
-       "deleting-backlinks-warning": "'''Avisu:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Otres páxines]] enllacen a, o trescluyen de, la páxina que ta a piques de desaniciar.",
+       "deleting-backlinks-warning": "<strong>Avisu:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|Otres páxines]] enllacen a, o trescluyen de, la páxina que tas a piques de desaniciar.",
        "rollback": "Revertir ediciones",
        "rollbacklink": "revertir",
        "rollbacklinkcount": "revertir $1 {{PLURAL:$1|edición|ediciones}}",
        "changecontentmodel-title-label": "Títulu de la páxina",
        "changecontentmodel-model-label": "Nuevu modelu de conteníu",
        "changecontentmodel-reason-label": "Motivu:",
+       "changecontentmodel-submit": "Camudar",
        "changecontentmodel-success-title": "Cambióse'l modelu de conteníu",
        "changecontentmodel-success-text": "Cambióse'l tipu de conteníu de [[:$1]].",
        "changecontentmodel-cannot-convert": "El conteníu de [[:$1]] nun puede convertise a un tipu de $2.",
        "changecontentmodel-nodirectediting": "El modelu de conteníu $1 nun tien encontu pa edición direuta",
        "log-name-contentmodel": "Rexistru de cambios del modelu de conteníu",
        "log-description-contentmodel": "Socesos rellacionaos colos modelos de conteníu d'una páxina",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|creó}} la páxina $3 usando un modelu de conteníu non predetermináu «$5»",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|cambió}}'l modelu de conteníu de la páxina $3 dende «$4» a «$5»",
        "logentry-contentmodel-change-revertlink": "revertir",
        "logentry-contentmodel-change-revert": "revertir",
        "import-nonewrevisions": "Nun s'importó denguna revision (o yá taben toes presentes, o se saltaron por errores).",
        "xml-error-string": "$1 na llinia $2, col $3 (byte $4): $5",
        "import-upload": "Xubir datos XML",
-       "import-token-mismatch": "Perdiéronse los datos de la sesión. Intentalo otra vuelta.",
+       "import-token-mismatch": "Perda de datos de la sesión.\n\nSeique zarróse la sesión. <strong>Comprueba si tienes abierta la sesión y vuelve a intentalo</strong>.\nSi inda nun funcionara, tenta [[Special:UserLogout|colar]] y volver a aniciar sesión y comprueba que'l restolador permite les cookies d'esti sitiu.",
        "import-invalid-interwiki": "Nun se puede importar d'esi wiki.",
        "import-error-edit": "La páxina «$1» nun s'importó porque nun tienes permisu pa editala.",
        "import-error-create": "La páxina «$1» nun s'importó porque nun tienes permisu pa creala.",
        "tags-delete-not-allowed": "Les etiquetes definíes por una estensión nun puen desaniciase mentanto la estensión nun lo permita específicamente.",
        "tags-delete-not-found": "La etiqueta «$1» nun esiste.",
        "tags-delete-too-many-uses": "La etiqueta «$1» aplícase a más {{PLURAL:$2|d'una revisión|de $2 revisiones}}, lo que quier dicir que nun pue desaniciase.",
-       "tags-delete-warnings-after-delete": "La etiqueta «$1» desanicióse correutamente, pero {{PLURAL:$2|alcontróse'l siguiente avisu|alcontráronse los siguientes avisos}}:",
+       "tags-delete-warnings-after-delete": "Desanicióse la etiqueta «$1», pero {{PLURAL:$2|alcontróse'l siguiente avisu|alcontráronse los siguientes avisos}}:",
        "tags-activate-title": "Activar etiqueta",
        "tags-activate-question": "Tas a piques d'activar la etiqueta «$1».",
        "tags-activate-reason": "Motivu:",
        "tags-edit-revision-legend": "Amestar o desaniciar etiquetes {{PLURAL:$1|d'esta revisión|de toles $1 revisiones}}",
        "tags-edit-logentry-legend": "Amestar o desaniciar etiquetes {{PLURAL:$1|d'esta entrada del rexistru|de les $1 entraes del rexistru}}",
        "tags-edit-existing-tags": "Etiquetes esistentes:",
-       "tags-edit-existing-tags-none": "''Nenguna''",
+       "tags-edit-existing-tags-none": "<em>Nenguna</em>",
        "tags-edit-new-tags": "Etiquetes nueves:",
        "tags-edit-add": "Amestar estes etiquetes:",
        "tags-edit-remove": "Desaniciar estes etiquetes:",
        "tags-edit-reason": "Motivu:",
        "tags-edit-revision-submit": "Aplicar los cambios a {{PLURAL:$1|esta revisión|$1 revisiones}}",
        "tags-edit-logentry-submit": "Aplicar los cambios a {{PLURAL:$1|esta entrada del rexistru|$1 entraes del rexistru}}",
-       "tags-edit-success": "Los cambios aplicáronse correutamente.",
+       "tags-edit-success": "Aplicáronse los cambios.",
        "tags-edit-failure": "Nun pudieron aplicase los cambios:\n$1",
        "tags-edit-nooldid-title": "Revisión de destín inválida",
        "tags-edit-nooldid-text": "O nun conseñasti una revisión sobre la qu'aplicar esta función, o la revisión conseñada nun esiste.",
        "expand_templates_generate_xml": "Amosar l'árbole d'análisis sintáuticu XML",
        "expand_templates_generate_rawhtml": "Ver el HTML en bruto",
        "expand_templates_preview": "Vista previa",
-       "expand_templates_preview_fail_html": "<em>Como {{SITENAME}} tien activáu el códigu HTML puru y hebo una perda de datos de la sesión, la vista previa ta tapecida como precaución escontra ataques de JavaScript.</em>\n\n<strong>Si esti ye un intentu llexítimu d'accesu a la vista previa, vuelvi a intentalo.</strong>\nSi inda nun funciona, intenta [[Special:UserLogout|salir]] y volver a entrar na to cuenta.",
+       "expand_templates_preview_fail_html": "<em>Como {{SITENAME}} tien activáu el códigu HTML puru y hebo una perda de datos de la sesión, la vista previa ta tapecida como precaución escontra ataques de JavaScript.</em>\n\n<strong>Si esti ye un intentu llexítimu d'accesu a la vista previa, vuelve a tentalo.</strong>\nSi inda nun funciona, tenta [[Special:UserLogout|salir]] y volver a entrar na to cuenta, y comprueba que'l to restolador permite les cookies d'esti sitiu.",
        "expand_templates_preview_fail_html_anon": "<em>Como {{SITENAME}} tien activáu el códigu HTML puru y nun aniciasti sesión, la vista previa ta tapecida como precaución escontra ataques de JavaScript.</em>\n\n<strong>Si esti ye un intentu llexítimu d'accesu a la vista previa, intenta [[Special:UserLogin|entrar]] y vuelvi a intentalo.</strong>",
        "expand_templates_input_missing": "Fai falta dar daqué de testu d'entrada.",
        "pagelanguage": "Cambiar la llingua de la páxina",
index f8cc340..3ac6686 100644 (file)
        "contributions": "{{GENDER:$1|ایشلدن}} چالیشمالاری",
        "contributions-title": "$1 ایشلدن چالیشمالاری",
        "mycontris": "چالیشمالار",
+       "anoncontribs": "چالیشمالار",
        "contribsub2": "{{GENDER:$3|$1}} اوچون ($2)",
        "contributions-userdoesnotexist": "«$1» ایشلدن حسابی ثبت اولونماییب‌دیر.",
        "nocontribs": "بو موشخصاتا اویغون دییشدیر تاپیلمادی",
        "import-logentry-upload-detail": "{{PLURAL:$1|بیر|$1}} نوسخه ایچری گتیریلدی",
        "import-logentry-interwiki-detail": "$2-دن {{PLURAL:$1|بیر|$1}} نوسخه ایچری گتیریلدی",
        "javascripttest": "جاوااسکریپت تِستی",
-       "javascripttest-pagetext-noframework": "بو صحیفه، جاوااسکریپت تِستلرینی ایشلدمگه ساخلانیلیب‌دیر.",
-       "javascripttest-pagetext-unknownframework": "تانینمامیش تِست ائتمه سیستِمی «$1».",
        "javascripttest-pagetext-unknownaction": "تانینمایان ایش «$1».",
-       "javascripttest-pagetext-frameworks": "لوطفاً بو تِست ائتمه سیستِملرین بیرینی سئچین: $1",
-       "javascripttest-pagetext-skins": "تِستلرین ایجرا ائتمک اوچون بیر قابیق سئچین:",
        "javascripttest-qunit-intro": "mediawiki.org-دا [$1 تِست ائتمه سندلندیرمه‌لری]نه باخین.",
        "tooltip-pt-userpage": "ایشلدن صفحه‌نیز",
        "tooltip-pt-anonuserpage": "سیز او آی‌پی آدرسیله دَییشیکلیک ائتدیگینیز ایستیفاده‌چی صحیفه‌سی",
        "version-libraries-description": "آچیقلاما",
        "version-libraries-authors": "یازارلار",
        "redirect": "فایل، ایستیفاده‌چی، صفحه یا نوسخه آی‌دی-سی ایله یول‌لاندیرما",
-       "redirect-legend": "بیر فایل یا صحیفه‌یه یول‌لاندیرما",
        "redirect-summary": "بو اؤزل صحیفه، بیر فایلا (فایل آدی ایله)، صفحه‌یه (نوسخه یا صفحه آی‌دی-سی ایله) یا ایستیفاده‌چی صفحه‌سینه (ایستیفاده‌چی نومره آی‌دی-سی ایله) یول‌لاندیریر. ایشلتمک: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]]، [[{{#Special:Redirect}}/revision/328429]]، یا [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "گئت",
        "redirect-lookup": "آختار:",
index b2fc126..b9ad9f6 100644 (file)
                        "Ҡамыр Батыр",
                        "아라",
                        "Ләйсән",
-                       "Macofe"
+                       "Macofe",
+                       "Азат Хәлилов",
+                       "Айбикә",
+                       "З. ӘЙЛЕ",
+                       "Янмурза Баки",
+                       "Айсар",
+                       "Lizalizaufa",
+                       "Кутлубаева Кунсулу Закиевна",
+                       "Вильданова Гюзель"
                ]
        },
        "tog-underline": "Һылтанмалар аҫтына һыҙыу:",
-       "tog-hideminor": "Әһәмиәте ҙур булмаған төҙәтеүҙәрҙе һуңғы үҙгәртеүҙәр исемлегендә күрһәтмәҫкә",
+       "tog-hideminor": "Һуңғы үҙгәртеүҙәрҙең бәләкәй төҙәтеүҙәрен күрһәтмәҫкә",
        "tog-hidepatrolled": "Һуңғы үҙгәртеүҙәр исемлегендә тикшерелгән үҙгәртеүҙәрҙе йәшер",
-       "tog-newpageshidepatrolled": "ЯңÑ\8b Ð±Ð¸Ñ\82Ñ\82Ó\99Ñ\80 Ð¸Ñ\81емлегендÓ\99 Ñ\82икÑ\88еÑ\80елгÓ\99н Ò¯Ò\99гÓ\99Ñ\80Ñ\82еүÒ\99Ó\99Ñ\80Ò\99е Ð¹Ó\99Ñ\88еÑ\80",
-       "tog-hidecategorization": "Биттәр категоризацияһын йәшереү",
+       "tog-newpageshidepatrolled": "ТикÑ\88еÑ\80елгÓ\99н Ð±Ð¸Ñ\82Ñ\82Ó\99Ñ\80Ò\99е Ñ\8fÒ£Ñ\8b Ð±Ð¸Ñ\82Ñ\82Ó\99Ñ\80 Ñ\82еÒ\99мÓ\99һендÓ\99 ÐºÒ¯Ñ\80Ò»Ó\99Ñ\82мÓ\99ҫкÓ\99",
+       "tog-hidecategorization": "Биттәрҙең категоризацияһын йәшерергә",
        "tog-extendwatchlist": "Барлыҡ үҙгәртеүҙәрҙе үҙ эсенә алған, киңәйтелгән күҙәтеү исемлеге",
        "tog-usenewrc": "Һуңғы төҙәтеүҙәр һәм күҙәтеү исемлегендәге үҙгәрештәрҙе төркөмдәргә бүлергә",
-       "tog-numberheadings": "Ð\91аÑ\88иÑ\81емдÓ\99Ñ\80Ò\99е автоматик рәүештә номерланһын",
+       "tog-numberheadings": "Ð\90Ñ\82амалаÑ\80 автоматик рәүештә номерланһын",
        "tog-showtoolbar": "Мөхәррирләгән ваҡытта өҫкө ҡоралдар панелен күрһәтергә (JavaScript кәрәк)",
        "tog-editondblclick": "Биттәрҙе ике сиртеү менән мөхәррирләргә",
-       "tog-editsectiononrightclick": "Бүлектәрҙе исемдәренә төрткөнөң уң яғына сиртеп үҙгәртергә",
+       "tog-editsectiononrightclick": "Бүлектәрҙе исемдәрен төрткөнөң уң яғына баҫып үҙгәртергә",
        "tog-watchcreations": "Мин төҙөгән биттәрҙе һәм күсергән файлдарҙы күҙәтеү исемлегенә өҫтәргә",
        "tog-watchdefault": "Мин үҙгәрткән биттәр һәм файлдар аңлатмаһын күҙәтеү исемлегенә өҫтәргә",
        "tog-watchmoves": "Мин исемен үҙгәрткән биттәрҙе һәм файлдарҙы күҙәтеү исемлегенә өҫтәргә",
        "jumpto": "Унда күсергә:",
        "jumptonavigation": "төп йүнәлештәр",
        "jumptosearch": "эҙләү",
-       "view-pool-error": "Ò\92Ó\99Ñ\84Ò¯ Ð¸Ñ\82егеÒ\99, Ñ\85Ó\99Ò\99еÑ\80ге Ð²Ð°Ò¡Ñ\8bÑ\82Ñ\82а Ñ\81еÑ\80веÑ\80Ò\99аÑ\80 Ð°Ñ\80Ñ\82Ñ\8bÒ¡ Ñ\82ейÓ\99лгÓ\99н.\nÐ\91Ñ\8bл Ð±Ð¸Ñ\82Ñ\82е Ò¡Ð°Ñ\80аÑ\80Ò\93а Ñ\82елÓ\99Ò¯Ñ\81елÓ\99Ñ\80 Ð±Ð¸Ðº ÐºÒ¯Ð¿.\nÐ\97инһаÑ\80 Ð±Ñ\8bл Ð±Ð¸Ñ\82кÓ\99 Ò»Ñ\83Ò£Ñ\8bрак кереп ҡарағыҙ.\n\n$1",
+       "view-pool-error": "Ò\92Ó\99Ñ\84Ò¯ Ð¸Ñ\82егеÒ\99, Ñ\85Ó\99Ò\99еÑ\80ге Ð²Ð°Ò¡Ñ\8bÑ\82Ñ\82а Ñ\81еÑ\80веÑ\80Ò\99аÑ\80 Ð°Ñ\80Ñ\82Ñ\8bÒ¡ Ñ\82ейÓ\99лгÓ\99н.\nÐ\91Ñ\8bл Ð±Ð¸Ñ\82Ñ\82е Ò¡Ð°Ñ\80аÑ\80Ò\93а Ñ\82елÓ\99Ò¯Ñ\81елÓ\99Ñ\80 Ð±Ð¸Ðº ÐºÒ¯Ð¿.\nÐ\91Ñ\8bл Ð±Ð¸Ñ\82кÓ\99 Ò»Ñ\83Ò£Ò\93арак кереп ҡарағыҙ.\n\n$1",
        "generic-pool-error": "Ғәфү итегеҙ, хәҙерге ваҡытта серверҙар көсөргәнешле эшләй.\nБыл болды ҡарарға теләүселәр бик күп.\nЗинһар, бер ни тиклем көтөгөҙ һәм һуңыраҡ тағы мөрәжәғәт итеп ҡарағыҙ.",
        "pool-timeout": "Блоклауҙы көтөү ваҡыты үтте",
        "pool-queuefull": "Һорауҙар сираты тулы",
        "databaseerror-query": "Һоратыу: $1",
        "databaseerror-function": "Функция:$1",
        "databaseerror-error": "Хата: $1",
+       "transaction-duration-limit-exceeded": "$1 яҙмаһы оҙонлоғо мөмкин булған $2 сикләүен {{PLURAL:$2|секундҡа}}уҙып китте. Ҙур булмаған операциялар эшләп ҡарағыҙ.",
        "laggedslavemode": "'''Иғтибар:''' биттә һуңғы үҙгәртеүҙәр күрһәтелмәгән булырға мөмкин.",
        "readonly": "Мәғлүмәттәр базаһы бикләнгән",
        "enterlockreason": "Ябылыу сәбәбен һәм ваҡытын белдерегеҙ.",
        "readonlytext": "Яңы мәҡәләләр өҫтәү һәм мәғлүмәттәр базаһындағы башҡа үҙгәртеүҙәр хәҙер тыйылған. Был планлы хеҙмәтләндереү сәбәпле булыуы мөмкин, аҙаҡтан ғәҙәти хәлгә ҡайтасаҡ.\n\nЯбыусы хаким ҡалдырған аңлатма:\n$1",
-       "missing-article": "Ð\9cÓ\99Ò\93лүмÓ\99Ñ\82Ñ\82Ó\99Ñ\80 Ð±Ð°Ð·Ð°Ò»Ñ\8bнда Â«$1» $2 Ð±Ð¸Ñ\82енең Ò»Ð¾Ñ\80алÒ\93ан Ñ\82екÑ\81Ñ\82Ñ\8b Ñ\82абÑ\8bлманÑ\8b.\n\nÐ\91Ñ\8bл, Ò\93Ó\99Ò\99Ó\99Ñ\82Ñ\82Ó\99, Ð¸Ò«ÐºÐµÑ\80гÓ\99н Ò»Ñ\8bлÑ\82анма Ð±Ñ\83йÑ\8bнÑ\81а Ñ\8eйÑ\8bлÒ\93ан Ð±Ð¸Ñ\82Ñ\82ең  Ò¯Ò\99гÓ\99Ñ\80Ñ\82еү Ñ\82аÑ\80иÑ\85Ñ\8bна ÐºÒ¯Ñ\81кÓ\99ндÓ\99 ÐºÐ¸Ð»ÐµÐ¿ Ñ\81Ñ\8bÒ\93а.\n\nÓ\98гÓ\99Ñ\80 Ñ\85аÑ\82анÑ\8bÒ£ Ñ\81Ó\99бÓ\99бе Ñ\83л Ð±Ñ\83лмаһа, Ñ\82имÓ\99к Ò»ÐµÒ\99 Ð¿Ñ\80огÑ\80аммала Ñ\85аÑ\82а Ñ\82апҡанһÑ\8bÒ\93Ñ\8bÒ\99.\nÐ\91Ñ\8bл Ñ\82Ñ\83Ñ\80ала Ð·Ð¸Ð½Ò»Ð°Ñ\80 URL-дÑ\8b ÐºÒ¯Ñ\80Ò»Ó\99Ñ\82еп, [[Special:ListUsers/sysop|Ñ\85акимгÓ\99]] белдерегеҙ.",
+       "missing-article": "Ð\9cÓ\99Ò\93лүмÓ\99Ñ\82Ñ\82Ó\99Ñ\80 Ð±Ð°Ð·Ð°Ò»Ñ\8bнда Â«$1» $2 Ð±Ð¸Ñ\82енең Ò»Ð¾Ñ\80алÒ\93ан Ñ\82екÑ\81Ñ\8b Ñ\82абÑ\8bлманÑ\8b.\n\nÐ\91Ñ\8bл, Ò\93Ó\99Ò\99Ó\99Ñ\82Ñ\82Ó\99, Ð¸Ò«ÐºÐµÑ\80гÓ\99н Ò»Ñ\8bлÑ\82анма Ð±Ñ\83йÑ\8bнÑ\81а Ñ\8eйÑ\8bлÒ\93ан Ð±Ð¸Ñ\82Ñ\82ең Ò¯Ò\99гÓ\99Ñ\80Ñ\82еү Ñ\82аÑ\80иÑ\85Ñ\8bна ÐºÒ¯Ñ\81кÓ\99ндÓ\99 ÐºÐ¸Ð»ÐµÐ¿ Ñ\81Ñ\8bÒ\93а.\n\nÓ\98гÓ\99Ñ\80 Ñ\85аÑ\82анÑ\8bÒ£ Ñ\81Ó\99бÓ\99бе Ñ\83л Ð±Ñ\83лмаһа, Ñ\82имÓ\99к, Ò»ÐµÒ\99 Ð¿Ñ\80огÑ\80аммала Ñ\85аÑ\82а Ñ\82апҡанһÑ\8bÒ\93Ñ\8bÒ\99.\nÐ\91Ñ\8bл Ñ\82Ñ\83Ñ\80ала, URL-дÑ\8b ÐºÒ¯Ñ\80Ò»Ó\99Ñ\82еп, [[Special:ListUsers/sysop|Ñ\85акимÒ\93а]] белдерегеҙ.",
        "missingarticle-rev": "(версия № $1)",
        "missingarticle-diff": "(айырма: $1, $2)",
        "readonly_lag": "Өҫтәмә сервер төп сервер менән синхронлашҡанға тиклем мәғлүмәттәр базаһы автоматик рәүештә үҙгәрештәргә ҡаршы ябылған.",
+       "nonwrite-api-promise-error": " 'Promise-Non-Write-API-Action' HTTP исеменә ғариза ебәрелде, тик API модюленә китте.",
        "internalerror": "Эске хата",
        "internalerror_info": "Эске хата: $1",
        "internalerror-fatal-exception": "$1 тибындағы төҙәтә алмаҫлыҡ ҡағиҙәнән ситкә тайпылыш",
        "badtitletext": "Биттең һоратылған исеме дөрөҫ түгел, буш йәки телдәр араһы йәки интервики исеме яңылыш күрһәтелгән. Исемдә тыйылған символдар булыуы ла мөмкин.",
        "title-invalid-empty": "Һоратылған бит башлығы буш йәки исемдәр арауығы була.",
        "title-invalid-utf8": "Һеҙ эҙләгән биттә дөрөҫ булмаған UTF-8 символдар теҙмәһе бар.",
+       "title-invalid-interwiki": "Һеҙ һораған биттә интервики-һылтанма бар, был исемдәрҙә ҡулланыла алмай.",
+       "title-invalid-talk-namespace": "Һеҙ һораған бит исеме булмаған фекер алышыу битенә һылтана.",
+       "title-invalid-characters": "Һеҙ һораған биттә ярамаған $1 символы бар.",
+       "title-invalid-relative": " (/,../) юлы булған исем ғәмәлдә түгел, ҡулланыусы браузер менән ҡулланған ваҡытта улар йыш ҡына асылмай.",
+       "title-invalid-magic-tilde": "Һоралған исемдә ярамаған исем бар (<nowiki>~~~</nowiki>).",
+       "title-invalid-too-long": "Һоралған бит исеме бик оҙон. $1 {{PLURAL:$1|байттан}} артмаҫҡа тейеш.",
+       "title-invalid-leading-colon": "Һораған бит башында ярамаған ике нөктә бар.",
        "perfcached": "Был мәғлүмәттәр кэштан алынған, уларҙа һуңғы үҙгәртеүҙәр булмаҫҡа мөмкин. Кэшта иң күбе {{PLURAL:$1|язма}} һаҡлана.",
        "perfcachedts": "Был мәғлүмәттәр кэштан алынған, ул һуңғы тапҡыр $1 яңыртылды.  Кэшта иң күбе  {{PLURAL:$4|язма}} һаҡлана",
        "querypage-no-updates": "Был битте яңыртыу хәҙер тыйылған.\nБында күрһәтелгән мәғлүмәттәр яңыртылмаясаҡ.",
        "viewyourtext": "Был биттәге '''үҙгәртеүҙәрегеҙҙең''' сығанаҡ текстын ҡарай һәм күсермәһен ала алаһығыҙ:",
        "protectedinterface": "Был биттә программаның интерфейс хәбәре бар. Вандализм осраҡтарын булдырмау өсөн, был битте үҙгәртеү тыйыла.\nБыл хәбәрҙең тәржемәһен өҫтәү йәки үҙгәртеү өсөн, зинһар, MediaWiki проектының [//translatewiki.net/ translatewiki.net] локалләштереү сайтын ҡулланығыҙ.",
        "editinginterface": "'''Иғтибар.''' Һеҙ программаның арайөҙ тексты булған битте мөхәррирләйһегеҙ.\nУны үҙгәртеү, башҡа ҡулланыусыларҙын арайөҙ күренешен үҙгәртәсәктер.\nТәржемә өсөн [//translatewiki.net/wiki/Main_Page?setlang=ba translatewiki.net] адресын, MediaWiki-ны локалләштереү проектын ҡулланыу яҡшыраҡ буласаҡтыр.",
+       "translateinterface": "Был хәбәрҙе тәржәмә итү өсөн [//translatewiki.net/ translatewiki.net]сайтын ҡулланығыҙ.",
        "cascadeprotected": "Был бит үҙгәртеүҙәрҙән һаҡланған, сөнки ул эҙмә-эҙлекле һаҡлау ҡуйылған {{PLURAL:$1|1=биткә|биттәргә}} керә:\n$2",
        "namespaceprotected": "«$1» исем арауығындағы биттәрҙе мөхәррирләү өсөн хоҡуҡтарығыҙ юҡ.",
        "customcssprotected": "Был CSS-битте үҙгәртеү хоҡуғығыҙ юҡ, сөнки унда башҡа ҡулланыусының шәхси көйләүҙәре бар.",
        "invalidtitle-knownnamespace": "\"$2\" исем арауығы һәм \"$3\"  тексты исем өсөн ярамай",
        "invalidtitle-unknownnamespace": "\"$2\" тексты һәм \"$1\" арауыҡ өсөн билдәһеҙ номерлы исем ярамай",
        "exception-nologin": "Танылмағанһығыҙ",
-       "exception-nologin-text": "Был битте ҡарау йәки һоратылған ғәмәлде башҡарыу өсөн системала [[Special:Userlogin|танылыр]] кәрәк.",
+       "exception-nologin-text": "Был битте ҡарау йәки һоратылған ғәмәлде башҡарыу өсөн системала танылырға кәрәк.",
+       "exception-nologin-text-manual": "Был биткә кереү өсөн $1 булырға тейеш",
        "virus-badscanner": "Көйләү хатаһы: Билдәһеҙ вирустар сканеры: ''$1''",
        "virus-scanfailed": "сканлау хатаһы ($1 коды)",
        "virus-unknownscanner": "беленмәгән антивирус:",
        "logouttext": "'''Һеҙ эш сеансын тамамланығыҙ.'''\n\nҠайһы бер биттәр һеҙ системаға танылмаған кеүек күренеүен дауам итер. Быны бөтөрөү өсөн браузер кэшын таҙартығыҙ.",
        "cannotlogoutnow-title": "Хәҙер үк сығып булмай",
+       "cannotlogoutnow-text": "$1 файҙалланған ваҡытта инергә ярамай",
        "welcomeuser": "Рәхим итегеҙ $1!",
        "welcomecreation-msg": "Иҫәп яҙыуығыҙ яһалды.\nШәхси [[Special:Preferences|{{SITENAME}} көйләүҙәрен]] үҙегеҙгә уңайлы итеп үҙгәртергә онотмағыҙ.",
        "yourname": "Ҡатнашыусы исеме",
        "userlogin-remembermypassword": "Системала ҡалырға",
        "userlogin-signwithsecure": "Һаҡланыулы тоташыу",
        "cannotloginnow-title": "Хәҙер үк инеп булмай",
+       "cannotloginnow-text": "$1 файҙалланған ваҡытта инергә ярамай",
        "yourdomainname": "Һеҙҙең домен",
-       "password-change-forbidden": "Был викила серһүҙегеҙҙе үҙгәртә алмайһығыҙ.",
+       "password-change-forbidden": "Был викиҙа серһүҙегеҙҙе үҙгәртә алмайһығыҙ.",
        "externaldberror": "Тышҡы мәғлүмәт базаһы менән танылғанда хата барлыҡҡа килде йәки тышҡы үҙ көйләүҙәрегеҙҙе үҙгәртер өсөн хоҡуҡтарығыҙ етәрле түгел.",
        "login": "Танылыу",
        "nav-login-createaccount": "Танылыу йәки теркәлеү",
        "wrongpassword": "Һеҙ ҡулланған серһүҙ ҡабул ителмәй. Яңынан яҙып ҡарағыҙ.",
        "wrongpasswordempty": "Зинһар, буш булмаған серһүҙ керетегеҙ.",
        "passwordtooshort": "Серһүҙ кәмендә $1 {{PLURAL:$1|символдан}} торорға тейеш.",
+       "passwordtoolong": "Серһүҙ {{PLURAL:$1|1 символдан}} артмаҫҡа тейеш.",
+       "passwordtoopopular": "Йыш ҡулланыдған серһүҙ ҡабул ителмәй, Башҡа серһүҙ һайлағыҙ.",
        "password-name-match": "Керетелгән серһүҙ ҡулланыусы исеменән айырылырға тейеш.",
        "password-login-forbidden": "Был ҡатнашыусы исемен һәм серһүҙҙе ҡулланыу тыйылған",
        "mailmypassword": "Серһүҙҙе ташлатыу",
        "createaccount-text": "Кемдер, электрон почта адресығыҙҙы күрһәтеп, {{SITENAME}} ($4) проектында «$3» пароле менән «$2» исемле иҫәп яҙыуы теркәне. Һеҙҙең кереүегеҙ һәм серһүҙегеҙҙе алмаштырыуығыҙ кәрәк.\n\nИҫәп яҙыуы яңылыш яһалһа, был хатҡа иғтибар итмәгеҙ.",
        "login-throttled": "Һеҙ системаға ҡат-ҡат танылырға тырыштығыҙ.\nТағы бер танылырҙан алда, зинһар, $1 көтөгөҙ.",
        "login-abort-generic": "Танылыу уңышһыҙ тамамланды",
+       "login-migrated-generic": "Һеҙҙең иҫәп яҙмаһы күсерелде, викила һеҙҙең иҫәп яҙмаһы башҡа юҡ.",
        "loginlanguagelabel": "Тел: $1",
        "suspicious-userlogout": "Һеҙҙең сеансты тамамлау тураһында һорауығыҙ кире ҡағылды, сөнки ул төҙөк булмаған браузер йәки кэшлаусы прокси тарафынан ебәрелгән һорауға оҡшаған.",
        "createacct-another-realname-tip": "Ысын исемегеҙ (мотлаҡ түгел).\nУны яҙып ҡуйһағыҙ, ул биткә кем төҙәтеү индергәнен күрһәтеү өсөн ҡулланыласаҡ.",
        "user-mail-no-addy": "Электрон почта адресы булмайынса электрон хәбәр ебәреп ҡараны",
        "user-mail-no-body": "Буш йә мәғәнәһеҙ йөкмәткеле ҡыҫҡа электрон хат ебәрергә тырышҡан.",
        "changepassword": "Серһүҙҙе үҙгәртергә",
-       "resetpass_announce": "Һеҙ системала электрон почта аша алынған ваҡытлыса серһүҙ менән танылдығыҙ. Системаға кереүҙә тамалау өсөн яңы серһүҙ булдырығыҙ.",
+       "resetpass_announce": "Системаға кереүҙә тамалау өсөн яңы серһүҙ булдырығыҙ.",
        "resetpass_header": "Иҫәп яҙыуы серһүҙен үҙгәртеү",
        "oldpassword": "Иҫке серһүҙ:",
        "newpassword": "Яңы серһүҙ:",
        "retypenew": "Серһүҙҙе яңынан керетегеҙ:",
        "resetpass_submit": "Серһүҙ ҡуйырға һәм танышырға",
        "changepassword-success": "Серһүҙегеҙ уңышлы үҙгәртелде!",
+       "changepassword-throttled": "Һеҙ системаға ҡат-ҡат танылырға тырыштығыҙ.\nТағы бер танылырҙан алда, зинһар, $1 көтөгөҙ.",
+       "botpasswords": "Роботтар серһүҙе.",
+       "botpasswords-summary": "<em>ПРобот пароле</em> API иҫәп яҙмаһына логин һәм паролһыҙ инергә мөмкинлек бирә. Робот пароле менән ингәндә ҡулланыусы хоҡуғы сикләнгән булыуы мөмкин.\n\nНи өсөн икәнен белмәһәгеҙ, быны эшләмәүегеҙ яҡшыраҡ.",
+       "botpasswords-disabled": "Роботтар серһүҙе һүндерелгән.",
+       "botpasswords-no-central-id": "Робот серһүҙен ҡулланыу өсөн үҙәк иҫәп яҙмаһына инергә кәрәк.",
+       "botpasswords-existing": "Робот серһүҙҙәре.",
+       "botpasswords-createnew": "Робот өсөн яңы серһүҙ булдырырға.",
+       "botpasswords-editexisting": "Робот серһүҙен мөхәррирләргә.",
        "botpasswords-label-appid": "Бот исеме:",
        "botpasswords-label-create": "Төҙөргә",
        "botpasswords-label-update": "Яңыртырға",
        "botpasswords-label-delete": "Юйырға",
        "botpasswords-label-resetpassword": "Серһүҙҙе ташлатыу",
        "botpasswords-label-grants": "Ҡулланылған рөхсәттәр:",
+       "botpasswords-help-grants": "Һәр рөхсәт иҫәп яҙмаһы булған ҡулланыусы хоҡуҡтарын ҡулланырға рөхсәт бирә. Тулыраҡ мәғлүмәт өсөн [[Special:ListGrants|рөхсәт таблицаһын]] ҡарағыҙ.",
+       "botpasswords-label-restrictions": "Ҡулланыуҙы сикләү:",
+       "botpasswords-label-grants-column": "Рөхсәт",
+       "botpasswords-bad-appid": "$1 исемле робот ярамай.",
+       "botpasswords-insert-failed": "$1 исемле роботты өҫтәп булманы. Бәлки өҫтәлгән булғандыр?",
+       "botpasswords-update-failed": "$1 исемле роботты яңыртып булманы. Бәлки ул юйылғандыр?",
+       "botpasswords-created-title": "Робот серһүҙе булдырылды.",
+       "botpasswords-created-body": "$1 роботы өсөн $2 ҡулланыусыһы серһүҙе эшләнде.",
+       "botpasswords-updated-title": "Робот серһүҙе булдырылды.",
+       "botpasswords-updated-body": "$1 роботы өсөн $2 ҡулланыусыһы серһүҙе яңыртылды.",
+       "botpasswords-deleted-title": "Робот серһүҙе юйылды.",
+       "botpasswords-deleted-body": "$1 роботы өсөн $2 ҡулланыусыһы серһүҙе юйылды.",
+       "botpasswords-newpassword": "Инеү өсөн яңы серһүҙ <strong>$1</strong> — <strong>$2</strong>. <em>Артабан ҡулланыу өсөн яһып алығыҙ.</em>",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider ғәмәлдә түгел.",
+       "botpasswords-restriction-failed": "Робот серһүҙе менән бәйле сәбәптәр булғанға инеү башҡарылманы.",
+       "botpasswords-invalid-name": "Күрһәтелгән ҡулланыусы исемендә робот $1 серһүҙен бүлеүсе тамға юҡ.",
+       "botpasswords-not-exist": "$1 ҡулланыусыһының $2 роботы өсөн серһеҙе юҡ.",
        "resetpass_forbidden": "Серһүҙҙе үҙгәртеп булмай",
        "resetpass-no-info": "Был битте туранан ҡарау өсөн һеҙгә системала танылырға кәрәк.",
        "resetpass-submit-loggedin": "Серһүҙҙе үҙгәртергә",
        "resetpass-submit-cancel": "Бөтөрөргә",
        "resetpass-wrong-oldpass": "Хаталы ваҡытлыса йәки ағымдағы серһүҙ.\nҺеҙ, бәлки, серһүҙегеҙҙе алмаштырғанһығыҙ йәки яңы серһүҙ һоратҡанһығыҙ.",
+       "resetpass-recycled": "Үҙегеҙҙекенән айырмалы серһүҙ һайлағыҙ.",
+       "resetpass-temp-emailed": "Һеҙ электорон почта аша ебәрелгән ваҡытлыса серһүҙ менән индегеҙ. Инеүҙе башҡарыу өсөн яңы серһүҙ яҙығыҙ.",
        "resetpass-temp-password": "Ваҡытлыса серһүҙ",
        "resetpass-abort-generic": "Серһүҙҙе үҙгәртеү киңәйеү тарафынан өҙөлдө.",
        "resetpass-expired": "Һеҙҙең серһүҙҙең ғәмәл ваҡыты үткән. Зинһар, системала танылыу өсөн яңы серҙһүҙ ҡуйығыҙ.",
+       "resetpass-expired-soft": "Һеҙҙең серһүҙ ваҡыты сыҡты, хәҙер ул үҙгәртелергә тейеш. Яңы серһүҙ һайлағыҙ, йәки уны үҙгәртеү өсөн «{{int:resetpass-submit-cancel}}» баҫығыҙ.",
+       "resetpass-validity-soft": "Ярамаған серһүҙ һайланған $1",
        "passwordreset": "Серһүҙҙе ташлатыу",
        "passwordreset-text-one": "Серһүҙегеҙҙе ташлар өсөн ош ҡалыпты тултырығыҙ.",
        "passwordreset-text-many": "{{PLURAL:$1|Серһүҙҙе ташлар өсөн яландарҙың береһен тултырығыҙ.}}",
        "passwordreset-emailtext-user": "{{SITENAME}} проектындағы $1 ҡулланыусыһы {{SITENAME}} ($4) проектындағы иҫәп яҙыуығыҙҙы хәтерләтеүҙе һоратты. Киләһе ҡулланыусы {{PLURAL:$3|1=иҫәп яҙыуы|иҫәп яҙыуҙары}} был электрон почта адресы менән бәйле:\n\n$2\n\nБыл ваҡытлыса {{PLURAL:$3|1=серһүҙ|серһүҙҙәр}} {{PLURAL:$5|$5 көн}} ғәмәлдә буласаҡ.\nҺеҙ системала танылырға һәм яңы серһүҙ һайларға тейешһегеҙ.\nӘгәр, һеҙ быны һоратмаған булһағыҙ йәки элекке серһүҙегеҙҙе киренән иҫләһәгеҙ һәм уны үҙгәртергә теләмәһәгеҙ, был хатҡа иғтибар итмәгеҙ һәм элекке серһүҙеҙҙе ҡулланыуҙы дауам итегеҙ.",
        "passwordreset-emailelement": "Ҡулланыусы исеме: \n$1\n\nВаҡытлыса серһүҙ: \n$2",
        "passwordreset-emailsentemail": "Серһүҙҙе ташлау тураһындағы мәғлүмәт менән электрон почта аша хат ебәрелде.",
+       "passwordreset-emailsentusername": "Әгәр был ҡатнашыусының исеменә бәйле  электрон почтаһының адресы булһа, ул саҡта  серһүҙҙе тергеҙеү өсөн  хат ебәреләсәк.",
        "passwordreset-emailsent-capture": "Серһүҙҙе ташлау тураһындағы мәғлүмәт менән электрон хат ебәрелде, уның тексы түбәндә бирелә:",
        "passwordreset-emailerror-capture": "Серһүҙҙе ташлау тураһында хәбәр итеүсе электрон хат булдырылғайны, ләкин уны  {{GENDER:$2|kullanıcıya}} түбәндәге сәбәп арҡаһында ебәреп булманы: $1",
        "changeemail": "Электрон почта адресын үҙгәртергә",
        "changeemail-header": "Электрон почта адресын үҙгәртеү",
+       "changeemail-passwordrequired": "Әлеге үҙгәрештәрҙе раҫлау өсөн, Һеҙгә ҡулланыусының серһүҙен яҙырға кәрәк",
        "changeemail-no-info": "Был биткә туранан ирешеү өсөн һеҙгә системала танылыу кәрәк.",
        "changeemail-oldemail": "Хәҙерге электрон почта адресы:",
        "changeemail-newemail": "Яңы электрон почта адресы:",
+       "changeemail-newemail-help": "Әгәр һеҙ үҙегеҙҙең электрон почтағыҙҙы юйҙыртырға теләһәгеҙ, был ялан буш ҡалдырылырға тейеш. Тик уны юйғандан һуң һеҙ онотолған серһүҙҙе ырғыта алмайһығыҙ һәм был  вики проекттан хат алмаясаҡһығыҙ.",
        "changeemail-none": "(юҡ)",
        "changeemail-password": "{{SITENAME}} прокты өсөн серһүҙегеҙ:",
        "changeemail-submit": "Адресты үҙгәртергә",
+       "changeemail-throttled": "Һеҙ системаға ҡат-ҡат танылырға тырыштығыҙ.\nТағы бер танылырҙан алда, зинһар, $1 көтөгөҙ.",
+       "changeemail-nochange": "Зинһар,башҡа яңы электрон почта адресын яҙығыҙ.",
        "resettokens": "Токендарҙы ташларға",
        "resettokens-text": "Иҫәп яҙмағыҙ менән бәйләнгән ҡайһы бер шәхси мәғлүмәттәрегеҙгә инеүгә юл асыусы токендарҙы ташлай алаһығыҙ.\n\nЯңылыштан уларҙы берәйһе менән уртаҡлашҡан  йәки аккаунтығыҙ ваттырылған осраҡта быны эшләү мотлаҡ.",
        "resettokens-no-tokens": "Ташлар өсөн токендар юҡ.",
        "preview": "Ҡарап сығыу",
        "showpreview": "Ҡарап сығырға",
        "showdiff": "Индерелгән үҙгәрештәр",
-       "anoneditwarning": "'''Иғтибар''': Һеҙ танылмағанһығыҙ. IP-адресығыҙ был биттең үҙгәртеүҙәр тарихына яҙыласаҡ.",
+       "blankarticle": "<strong>Иҫкәртеү:</strong> Һеҙ булдырасаҡ бит буш.\nӘгәр тағы ла «{{int:savearticle}}» кнопкаға баҫһағыҙ, шул уҡ йөкмәткеле бит  яңынан барлыҡҡа киләсәк.",
+       "anoneditwarning": "<strong>Иғтибар!</strong> Һеҙ сайтта теркәлмәнегеҙ. Әгәр ҙә һеҙ ниндәй ҙә булһа төҙәтмәләр  йәки үҙгәртүҙәр индерһәгеҙ, һеҙҙең IP-адрес башҡаларға ла күрһәтеләсәк. Сайтҡа <strong>[$1 керһәгеҙ]</strong> йәки <strong>[$2 ҡуллануысы яҙмаһын төҙөһәгеҙ]</strong>, һеҙ индергән үҙгәртеүҙәр һеҙҙең ҡулланыусы яҙмағыҙға бәйләнгән була, шулай уҡ башҡа мөмкинлектәр ҙә тыуасаҡ.",
        "anonpreviewwarning": "''Һеҙ танылмағанһығыҙ. Яҙҙырыу ваҡытында IP-адресығыҙ был биттең үҙгәртеүҙәр тарихына яҙыласаҡ.''",
        "missingsummary": "'''Иҫкәртеү.''' Һеҙ үҙгәртеүҙергә ҡыҫҡа тасуирлама яҙманығыҙ. Ҡабаттан «Битте һаҡларға» төймәһенә баҫһағыҙ, үҙгәртеүҙәрегеҙ тасуирламаһыҙ һаҡланасаҡ.",
+       "selfredirect": "<strong>Иғтибар:</strong> Һеҙ шул уҡ мәҡәләгә йүнәлтеү эшләйһегеҙ.\n «{{int:savearticle}}» төәмәһенә баҫһағыҙ тағы шул биткә йүнәлтеләсәк.",
        "missingcommenttext": "Зинһар, аҫҡа үҙ тасуирламағыҙҙы керетегеҙ.",
        "missingcommentheader": "'''Иҫкәртеү:''' Һеҙ был комментарий өсөн тема/исем яҙманығыҙ.\n«{{int:savearticle}}» төймәһенә ҡабат баҫыу менән үҙгәртеүҙерегеҙ исемһеҙ яҙыласаҡ.",
        "summary-preview": "Буласаҡ тасуирлама:",
        "subject-preview": "Тема/башлыҡты алдан ҡарау:",
+       "previewerrortext": "Алдан ҡарау ваҡытында хата китте.",
        "blockedtitle": "Ҡулланыусы блокланған",
        "blockedtext": "'''Иҫәп яҙыуығыҙ йәки IP-адресығыҙ блокланған.'''\n\nБлоклаусы хаким: $1.\nБелдерелгән сәбәп: ''$2''.\n\n* Блоклау башланған ваҡыт: $8\n* Блоклау  аҙағы: $6\n* Блоклауҙар һаны: $7\n\nҺеҙ $1 йәки башҡа [[{{MediaWiki:Grouppage-sysop}}|хакимгә]] блоклау буйынса һорауҙарығыҙҙы ебәрә алаһығыҙ.\nИҫегеҙҙе тотоғоҙ: әгәр һеҙ теркәлмәгән һәм электрон почта адресығыҙҙы раҫламаған булһағыҙ ([[Special:Preferences|көйләүҙәрем битендә]]), хакимгә хат ебәрә алмайһығыҙ. Шулай ук блоклау ваҡытында һеҙҙең хат ебәреү мөмкинлегегеҙ сикләгән булырға ла мөмкин.\nҺеҙҙең IP-адрес — $3, блоклау идентификаторы — #$5.\nХаттарҙа был мәғлүмәттәрҙе күрһәтергә онотмағыҙ.",
        "autoblockedtext": "Һеҙҙең IP-адресығыҙ автоматик рәүештә блокланған. Сәбәбе, был адрес элек блокланған ҡулланыусыларҙың береһе тарафынан ҡулланылған. Блоклаусы хаким ($1) киләһе сәбәпте белдергән:\n\n:«$2»\n\nБлоклаусы хаким: $1.\nБелдерелгән сәбәп: ''$2''.\n\n* Блоклау башланған ваҡыт: $8\n* Блоклау  аҙағы: $6\n* Блоклауҙар һаны: $7\n\nҺеҙ $1 йәки башҡа [[{{MediaWiki:Grouppage-sysop}}|хакимгә]] блоклау буйынса һорауҙарығыҙҙы ебәрә алаһығыҙ.\nИҫегеҙҙе тотоғоҙ: әгәр һеҙ теркәлмәгән һәм электрон почта адресығыҙҙы раҫламаған булһағыҙ ([[Special:Preferences|көйләүҙәрем битендә]]), хакимгә хат ебәрә алмайһығыҙ. Шулай ук блоклау ваҡытында һеҙҙең хат ебәреү мөмкинлегегеҙ сикләгән булырға ла мөмкин.\nҺеҙҙең IP-адрес — $3, блоклау идентификаторы — #$5.\nХаттарҙа был мәғлүмәттәрҙе күрһәтергә онотмағыҙ.",
        "yourdiff": "Айырмалыҡтар",
        "copyrightwarning": "Иғтибар, {{SITENAME}} сайтындағы бөтә өҫтәмәләр һәм үҙгәртеүҙәр $2 (ҡарағыҙ: $1) лицензияһы шарттары менән сығарылған тип иҫәпләнә. Әгәр текстарығыҙҙың ирекле рәүештә таратылыуын һәм төҙәтелеүен теләмәһәгеҙ, уларҙы бында өҫтәмәүегеҙ һорала.<br />\nШулай уҡ, керетелгән үҙгәртеүҙәрҙең авторы булыуығыҙҙы йәки уларҙы эстәлеге ирекле рәүештә таратылырға һәм үҙгәртелергә рөхсәт ителгән сығанаҡтан алыуығыҙҙы раҫлайһығыҙ.<br />\n'''РӨХСӘТ АЛМАЙЫНСА АВТОРЛЫҠ ХОҠУҠТАРЫ МЕНӘН ҺАҠЛАНҒАН МАТЕРИАЛДАР ҠУЙМАҒЫҘ!!!'''",
        "copyrightwarning2": "Иғтибар, һеҙ кереткән өҫтәмәләр башҡа ҡатнашыусылар тарафынан үҙгәртелергә йәки юйылырға мөмкин.\nӘгәр кемдең дә булһа текстарығыҙҙы үҙгәртеүен теләмәһәгеҙ, уларҙы бында ҡуймағыҙ.<br />\nШулай уҡ, кереткән өҫтәмәләрҙең авторы булыуығыҙҙы йәки уларҙы, эстәлеге ирекле рәүештә таратылырға һәм үҙгәртелергә рөхсәт ителгән сығанаҡтан алыуығыҙҙы раҫлайһығыҙ (ҡарағыҙ: $1).\n'''РӨХСӘТҺЕҘ, АВТОРЛЫҠ ХОҠУҠТАРЫ МЕНӘН ҺАҠЛАНҒАН МАТЕРИАЛДАР ҠУЙМАҒЫҘ!'''",
+       "editpage-cannot-use-custom-model": "Был бит моделе эстәлеген үҙгәртергә ярамай.",
        "longpageerror": "'''ХАТА: һаҡланасаҡ текст күләме $1 килобайт, был иһә рөхсәт ителгән {{PLURAL:$1|1=$1 килобайттан|$2 килобайттан}} күп. Битте һаҡлап булмай.'''",
-       "readonlywarning": "'''КИҪӘТЕҮ: Техник хеҙмәтләндереү сәбәпле мәғлүмәттәр базаһы блокланған, шунлыҡтан үҙгәртеүҙәрегеҙҙе хәҙер һаҡлай алмайһығыҙ.'''\nТексты аҙаҡтан ҡулланыу өсөн файлда һаҡлап тора алаһығыҙ.\n\nХаким белдергән сәбәп: $1",
+       "readonlywarning": "<strong>КИҪӘТЕҮ: Техник хеҙмәтләндереү сәбәпле мәғлүмәттәр базаһы блокланған, шунлыҡтан үҙгәртеүҙәрегеҙҙе хәҙер һаҡлай алмайһығыҙ.<strong>\nТексты аҙаҡтан ҡулланыу өсөн башҡа файлда һаҡлап тора алаһығыҙ.\n\nХаким белдергән сәбәп: $1",
        "protectedpagewarning": "'''КИҪӘТЕҮ: Һеҙ был битте үҙгәртә алмайһығыҙ, был хоҡуҡҡа хакимдәр генә эйә.'''\nБелешмә өсөн түбәндә һуңғы үҙгәртеү тураһында мәғлүмәт бирелә:",
        "semiprotectedpagewarning": "'''Киҫәтеү:''' был бит һаҡланған. Уны теркәлгән ҡулланыусылар ғына үҙгәртә ала.\nБелешмә өсөн түбәндә һуңғы үҙгәртеү тураһында мәғлүмәт бирелә:",
-       "cascadeprotectedwarning": "'''КИҪӘТЕҮ:''' Был битте тик хакимдәр генә үҙгәртә ала, сөнки ул эҙмә-эҙлекле һаҡлау ҡуйылған {{PLURAL:$1|1=киләһе биткә|киләһе биттәргә}} керә:",
+       "cascadeprotectedwarning": "<strong>Киҫәтеү:</strong> Был битте тик хакимдәр генә үҙгәртә ала.  Сөнки бит {{PLURAL:$1|каскадлы яҡлау исемлегенә индерелгән}}:",
        "titleprotectedwarning": "'''Киҫәтеү: Бындый исемле бит һаҡланған, уны үҙгәртеү өсөн [[Special:ListGroupRights|тейешле хоҡуҡҡа]] эйә булыу кәрәк.'''\nБелешмә өсөн түбәндә һуңғы үҙгәртеү тураһында мәғлүмәт бирелә:",
        "templatesused": "Был биттә ҡулланылған {{PLURAL:$1|1=ҡалып|ҡалыптар}}:",
        "templatesusedpreview": "Алдан ҡаралған биттә ҡулланылған {{PLURAL:$1|1=ҡалып|ҡалыптар}}:",
        "permissionserrors": "Инеү хоҡуғы хатаһы",
        "permissionserrorstext": "Түбәндәге {{PLURAL:$1|1=сәбәп|сәбәптәр}} буйынса һеҙҙең был ғәмәлде үтәү хоҡуғығыҙ юҡ:",
        "permissionserrorstext-withaction": "«'''$2'''» ғәмәлен башҡара алмайһығыҙ. {{PLURAL:$1|1=Сәбәбе|Сәбәптәре}}:",
+       "contentmodelediterror": "Был версияны мөхәррирләй алмайһығыҙ — <code>$1</code>, моделе ғәмәлдәге — <code>$2</code> моделенан айырыла.",
        "recreate-moveddeleted-warn": "'''Иғтибар: Һеҙ, элек юйылған битте яңынан яһарға теләйһегеҙ.'''\n\nҺеҙгә был битте яңынан яһау кәрәклеген яңынан уйлап ҡарағыҙ.\nТүбәндә биттең юйыу һәм исем үҙгәртеү яҙмалары килтерелә:",
        "moveddeleted-notice": "Был бит юйылған.\nБелешмә өсөн киләһе юйыу һәм исем үҙгәртеү яҙмалары килтерелә.",
+       "moveddeleted-notice-recent": "Үкенескә ҡаршы бит бит юйылған (һуүғы 24 сәғәт эсендә). Түбәндә юйыуҙар журналы һәм был журналға күсереүҙәр бирелгән.",
        "log-fulllog": "Бар яҙмаларҙы ҡарарға",
        "edit-hook-aborted": "Үҙгәртеүҙе ҡармаҡ-процедура кире ҡаҡты.\nӨҫтәмә аңлатма килтерелмәй.",
        "edit-gone-missing": "Битте яңыртып булмай.\nБәлки ул юйылғандыр.",
        "edit-already-exists": "Яңы бит яһап булмай.\nУл былай ҙа бар.",
        "defaultmessagetext": "Алдан билдәләнгән яҙма",
        "content-failed-to-parse": "$2 эстәлеге $1 төрөнә тура килмәй: $3.",
-       "invalid-content-data": "ЯÑ\80амаған мәғлүмәт",
+       "invalid-content-data": "ТÑ\8bйÑ\8bлған мәғлүмәт",
        "content-not-allowed-here": "\"$1\" эстәлеге [[$2]] бит өсөн ярамай",
        "editwarning-warning": "Икенсе биткә күсеү һеҙ индергән үҙгәрештәрҙең юғалыуына килтереүе мөмкин.\nӘгәр системала танылыу үтһәгеҙ, көйләүҙәрегеҙ битенең \"Мөхәррирләү\" бүлегендә был киҫәтеүҙе һүндерә алаһығыҙ.",
-       "content-model-wikitext": "викияҙма",
+       "editpage-notsupportedcontentformat-title": "Йөкмәтке форматы асылмай",
+       "editpage-notsupportedcontentformat-text": "$1 эстәлеге форматы $2 моделе форматы менән тап килмәй.",
+       "content-model-wikitext": "викитекст",
        "content-model-text": "ғәҙәти яҙма",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
-       "content-json-empty-object": "Ð\91Ñ\83Ñ\88 Ð½Ó\99мÓ\99",
+       "content-json-empty-object": "Ð\91Ñ\83Ñ\88 Ð¾Ð±Ñ\8aекÑ\82",
        "content-json-empty-array": "Буш массив",
+       "duplicate-args-warning": "<strong>Иғтибар:</strong> [[:$1]] берәүҙән артыҡ [[:$2]]  параметры  «$3» менән саҡыра. Һуңғы дәүмәл ҡулланыласаҡ.",
        "duplicate-args-category": "Ҡалыпты сығарғанда ҡабатланған аргументтарҙы ҡулланған биттәр",
        "duplicate-args-category-desc": "Түбәндәге ҡабатланған аргументтары <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> или <code><nowiki>{{foo|bar|1=bar}}</nowiki></code> булған ҡалыпты сығарыу эстәлекле биттәр.",
-       "expensive-parserfunction-warning": "'''Иғтибар:''' был биттә хәтерҙе күп ҡулланыусы функциялар ныҡ күп.\n\nҠуйылған сикләү: $2 {{PLURAL:$2|ҡулланыу}}, был осраҡта {{PLURAL:$1|$1 тапҡыр}} башҡарырға рөхсәт ителә.",
+       "expensive-parserfunction-warning": "<strong>Иғтибар:</strong>  был биттә хәтерҙе күп ҡулланыусы функциялар ныҡ күп.\n\nҠуйылған сикләү: $2 {{PLURAL:$2|ҡулланыу}}, был осраҡта {{PLURAL:$1|$1 тапҡыр}} башҡарырға рөхсәт ителә.",
        "expensive-parserfunction-category": "Хәтерҙе күп ҡулланыусы функциялары күп булған биттәр",
        "post-expand-template-inclusion-warning": "'''Иғтибар:''' Өҫтәлгән ҡалыптар күләме бик ҙур.\nҠайһы бер ҡалыптар өҫтәлмәйәсәк.",
        "post-expand-template-inclusion-category": "Рөхсәт ителгән күләмдән күп ҡалып ҡушылған биттәр",
        "parser-template-recursion-depth-warning": "($1) ҡалыбын рекурсия итеп ҡулланыу тәрәнлеге рөхсәт ителгәндән артып киткән",
        "language-converter-depth-warning": "Телдәрҙе үҙгәртеү тәрәнлегенең сиге үткән ($1)",
        "node-count-exceeded-category": "Төйөндәр һаны артҡан биттәр",
+       "node-count-exceeded-category-desc": "Биттә рөхсәт ителгән төйөндәр һаны артып киткән.",
        "node-count-exceeded-warning": "Биттә төйөндәр һаны артып киткән",
        "expansion-depth-exceeded-category": "Асылыу тәрәнлеге артып киткән биттәр",
        "expansion-depth-exceeded-category-desc": "Биттең асылыу тәрәнлеге мөмкин булған юғары сикте уҙған.",
        "undo-success": "Был үҙгәртеүҙе кире алып була. Зинһар, улар һеҙҙе ҡыҙыҡһындырған үҙгәртеүҙәр булыуынан шикләнмәҫ өсөн версияларҙы сағыштырыуҙы ҡарағыҙ һәм үҙгәртеүҙәрҙе ғәмәлғә керетер өсөн «Битте һаҡларға» төймәһенә баҫығыҙ.",
        "undo-failure": "Ара үҙгәртеүҙәр тура килмәү сәбәпле төҙәтеүҙе кире алып булмай.",
        "undo-norev": "Үҙгәртеүҙе кире алып булмай, сөнки юҡ йәки юйылған.",
+       "undo-nochange": "Төҙәтеү кире ҡайтарылған.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ҡулланыусыһының ([[User talk:$2|фекер алышыу]]) $1 үҙгәртеүенән баш тартыу",
        "undo-summary-username-hidden": "Исеме йәшерелгән ҡатнашыусының төҙәтеүен  $1 кире ҡағыу",
        "cantcreateaccounttitle": "Иҫәп яҙыуын яһап булмай",
        "cantcreateaccount-text": "Был IP-адрестан (<b>$1</b>) иҫәп яҙыуҙары булдырыу [[User:$3|$3]] тарафынан тыйылған.\n\n$3 белдергән сәбәп: ''$2''",
+       "cantcreateaccount-range-text": "{{GENDER:$3|Ҡатнашыусы}} [[User:$3|$3]] һеҙҙең IP-адрес ингән (<strong>$4</strong>) <strong>$1</strong> диапозонында иҫәп яҙмаһын булдырмаҫҡа {{GENDER:$3|тыйыу}} ҡуйҙы.\n\nОшо сәбәп күһәтелгән: $2.",
        "viewpagelogs": "Был биттең яҙмаларын ҡарарға",
        "nohistory": "Был биттең үҙгәртеүҙәр тарихы юҡ.",
        "currentrev": "Ағымдағы версия",
        "history-feed-description": "Викилағы был биттең үҙгәртеүҙәр тарихы",
        "history-feed-item-nocomment": "$1, $2",
        "history-feed-empty": "Һоратылған бит юҡ.\nУл бит юйылған йәки исеме үҙгәртелгән булыуы мөмкин.\nВикила оҡшаш биттәрҙе [[Special:Search|эҙләп ҡарағыҙ]].",
+       "history-edit-tags": "Һайланған версияның тегын үҙгәртергә.",
        "rev-deleted-comment": "(мөхәррирләү тасуирламаһы юйылған)",
        "rev-deleted-user": "(автор исеме юйылған)",
        "rev-deleted-event": "(яҙма юйылған)",
        "rev-deleted-user-contribs": "[ҡулланыусы исеме йәки IP-адрес юйылған — төҙәтеү өлөш битенән йәшерелде]",
        "rev-deleted-text-permission": "Биттең был өлгөһө '''юйылған'''.\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Юйыу яҙмалары журналында] аңлатмалар ҡалдырылыуы мөмкин.",
+       "rev-suppressed-text-permission": "Биттең был версияһы '''йәшерелгән'''.\nҺеҙ уны [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} йәшереү яҙмаларында] ҡарай алаһығыҙ .",
        "rev-deleted-text-unhide": "Биттең был версияһы '''юйылған'''.\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Юйыу яҙмаларында] аңлатмалар ҡалдырылыуы мөмкин.\nТеләгегеҙ булһа [был версияны $1] ҡарай алаһығыҙ.",
        "rev-suppressed-text-unhide": "Биттең был версияһы '''Йәшерелгән'''.\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Йәшереү яҙмаларында] аңлатмалар ҡалдырылыуы мөмкин.\nТеләгегеҙ булһа [был версияны $1] ҡарай алаһығыҙ.",
        "rev-deleted-text-view": "Биттең был версияһы '''юйылған'''.\nҺеҙ уны [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Юйыу яҙмаларында] ҡарай алаһығыҙ .",
        "rev-showdeleted": "күрһәтергә",
        "revisiondelete": "Бит версияларын юйырға/тергеҙергә",
        "revdelete-nooldid-title": "Маҡсат версия билдәләнмәгән",
-       "revdelete-nooldid-text": "Был функцияны үтәү өсөн һеҙ маҡсат версияны (йәки версияларҙы) билдәләмәнегеҙ. Билдәләнгән версия юҡ йәки версияны йәшерергә тырышаһығыҙ.",
+       "revdelete-nooldid-text": "Был функцияны үтәү өсөн һеҙ һуңғы версияны (йәки версияларҙы) билдәләмәнегеҙ. Билдәләнгән версия юҡ йәки версияны йәшерергә тырышаһығыҙ.",
        "revdelete-no-file": "Күрһәтелгән файл юҡ.",
        "revdelete-show-file-confirm": "$2, $3 ваҡытлы «<nowiki>$1</nowiki> файлының юйылған версияһын ҡарарға теләүегеҙҙе раҫлайһығыҙмы?",
        "revdelete-show-file-submit": "Эйе",
+       "revdelete-selected-text": "{{PLURAL:$1|Һайланған версия|Һайланған версиялар}} [[:$2]]:",
+       "revdelete-selected-file": "{{PLURAL:$1|Һайланған файл версияһы|Һайланған файл версиялары}} [[:$2]]:",
        "logdelete-selected": "Яҙманың {{PLURAL:$1|1=һайланған яҙыуы|һайланған яҙыуҙары}}:",
+       "revdelete-text-text": "Тарих битендә юйылған версиялар күренәсәк, ҡайһы бер өлөштәре ҡатнышыусылар өсөн асыҡ буласаҡ.",
+       "revdelete-text-file": "Тарих битендә юйылған файл версиялары күренәсәк, ҡайһы бер өлөштәре ҡатнышыусылар өсөн асыҡ буласаҡ",
+       "logdelete-text": "Тарих битендә юйылған версиялар күренәсәк, ҡайһы бер өлөштәре ҡатнышыусылар өсөн асыҡ буласаҡ.",
+       "revdelete-text-others": "Башҡа админситраторҙарың йәшәрелгән эстәлеккә инергә мөмкинлеге бар, өҫтәмә сикләүҙәр булмаған осраҡта, улар уны кире ҡайтара ала.",
        "revdelete-confirm": "Зинһар, был ғәмәлде үтәргә теләүегеҙҙе, буласаҡ һөҙөмтәләрҙә аңлауығыҙҙы, [[{{MediaWiki:Policy-url}}|ҡағиҙәләр]] буйынса эшләүегеҙҙе раҫлағыҙ.",
        "revdelete-suppress-text": "Йәшереү '''тик''' киләһе осраҡтарҙа ғына башҡарыла:\n\n* Уңай булмаған шәхси мәғлүмәт\n* ''өй адресы, телефон номерҙары, паспорт номеры һ.б.''",
        "revdelete-legend": "Күренеш сикләүҙәрен көйләргә:",
        "revdelete-hide-text": "Биттең был версияһының текстын йәшерергә",
        "revdelete-hide-image": "Файл эстәлеген йәшерергә",
-       "revdelete-hide-name": "Ò\92Ó\99мÓ\99лде Ò»Ó\99м Ð¼Ð°Ò¡Ñ\81аÑ\82Ñ\8bн йәшерергә",
+       "revdelete-hide-name": "Ò\92Ó\99мÓ\99лде Ò»Ó\99м ÐºÓ©Ð¹Ð»Ó\99Ò¯Ò\99е йәшерергә",
        "revdelete-hide-comment": "Үҙгәртеүҙәр тасуирламаһы",
        "revdelete-hide-user": "Мөхәррирләүсенең исеме/IP-адресы",
        "revdelete-hide-restricted": "Мәғлүмәттәрҙе хакимдәрҙән дә йәшерергә",
        "mergehistory-empty": "Һис бер версияны берләштереп булмай.",
        "mergehistory-done": "$1 битенең $3 {{PLURAL:$3|үҙгәртеүе}} уңышлы [[:$2]] менән берләштерелде.",
        "mergehistory-fail": "Бит тарихтарын берләштереп булманы, зирһар, бит һәм ваҡыт параметрҙарын яңынан тикшерегеҙ.",
+       "mergehistory-fail-bad-timestamp": "Ваҡыт тамғаһы дөрөҫ түгел.",
+       "mergehistory-fail-invalid-source": "Сығанаҡ бит дөрөҫ түгел.",
+       "mergehistory-fail-invalid-dest": "Маҡсат бите дөрөҫ түгел.",
+       "mergehistory-fail-no-change": "Бит тарихы версиялары ҡушылманы. Бит һәм ваҡыт параметрҙарын тикшерегеҙ.",
+       "mergehistory-fail-permission": "Бит тарихын ҡушыу өсөн хоҡуҡтар етәрлек түгел.",
+       "mergehistory-fail-self-merge": "Сығанаҡ һәм маҡсат бит бер төрлө.",
+       "mergehistory-fail-timestamps-overlap": "Сығанаҡ версия ҡаплана йәки тәғәйенләнгән версиянан һуң килә.",
+       "mergehistory-fail-toobig": "Бит тарихын ҡушып булмай, сәнки $1 лимитын күберәк {{PLURAL:$1|версияһына}} күсерергә кәрәк.",
        "mergehistory-no-source": "Сығанаҡ бит «$1» юҡ.",
        "mergehistory-no-destination": "Маҡсат бит «$1» юҡ.",
        "mergehistory-invalid-source": "Сығанаҡ биттең исеме дөрөҫ булырға тейеш.",
        "showhideselectedversions": "Һайланған версияларҙы күрһәтергә/йәшерергә",
        "editundo": "кире алыу",
        "diff-empty": "(айырмалар юҡ)",
+       "diff-multi-sameuser": "(был ҡулланыусының {{PLURAL:$1|аралағы версия $1|аралағы версиялары $1}} күрһәтелмәгән)",
+       "diff-multi-otherusers": "({{PLURAL:$1|$1 ваҡытлы версия| $1 ваҡытлы версия}} күрһәтелмәгән {{PLURAL:$2|$2 ҡатнашыусы|$2 ҡатнашыусылар}})",
        "diff-multi-manyusers": "(Кәмендә {{PLURAL:$2|$2 ҡатнашыусының}} {{PLURAL:$1|ваҡытлы версияһы}} күрһәтелмәгән)",
        "difference-missing-revision": "$1 айырмаһының {{PLURAL:$2|1=бер өлгөһө|$2 өлгөһө}} табылманы.\n\nБыл хәл, ғәҙәттә, юйылған биткә яһалған айырма һылтанмаһының ваҡыты үтеүенән барлыҡҡа килә.\nТулыраҡ мәғлүмәт өсөн ҡарағыҙ: [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} юйыу яҙмалары].",
        "searchresults": "Эҙләү һөҙөмтәләре",
        "shown-title": "Бер биттә $1 {{PLURAL:$1|1=һөҙөмтә|һөҙөмтә}} күрһәтергә",
        "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) ҡарарға",
        "searchmenu-exists": "'''Был вики-проектта «[[:$1]]» бите бар'''",
-       "searchmenu-new": "'''Был википроектта \"[[:$1]]\" бите булдырырға.'''",
+       "searchmenu-new": "{{PLURAL:$2|}}<strong>Был википроектта \"[[:$1]]\" бите булдырырға.</strong>",
        "searchprofile-articles": "Эстәлек биттәре",
        "searchprofile-images": "Мультимедиа",
        "searchprofile-everything": "Барыһы",
        "search-result-category-size": "{{PLURAL:$1|1=$1 ағза}} ({{PLURAL:$2|$2 эске категория}}, {{PLURAL:$3|$3 файл}})",
        "search-redirect": "(йүнәлтеү $1)",
        "search-section": "($1 бүлеге)",
+       "search-category": "(категория $1)",
        "search-file-match": "(файл эстәлеге менән тура килә)",
        "search-suggest": "Бәлки, ошоно эҙләйһегеҙҙер: $1",
+       "search-rewritten": "$1 нәтижәһе күрһәтелгән. $2 урынына эҙләргә.",
        "search-interwiki-caption": "Туғандаш проекттар",
        "search-interwiki-default": "$1 һөҙөмтәһе:",
        "search-interwiki-more": "(тағы)",
        "searchrelated": "ҡағылышлы",
        "searchall": "барыһы",
        "showingresults": "Түбәндә №&nbsp;<strong>$2</strong> һөҙөмтәнән башлап <strong>$1</strong> {{PLURAL:$1|һөҙөмтә}} күрһәтелгән.",
+       "showingresultsinrange": "Түбәндә №&nbsp;<strong>$2</strong> һөҙөмтәнән башлап <strong>$1</strong> {{PLURAL:$1|һөҙөмтә}} күрһәтелгән.<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|<strong>$3</strong> нәтижәнән <strong>$1</strong>| <strong>$3</strong> нәтижәләрҙән <strong>$1 — $2</strong>}}",
        "search-nonefound": "Был һорауға яуап биреүсе һөҙөмтәләр табылманы.",
+       "search-nonefound-thiswiki": "Был һорауға яуап биреүсе һөҙөмтәләр табылманы.",
        "powersearch-legend": "Киңәйтелгән эҙләү",
        "powersearch-ns": "Исем аралыҡтарында эҙләү:",
        "powersearch-togglelabel": "Һайла:",
        "rows": "Юлдар:",
        "columns": "Бағаналар:",
        "searchresultshead": "Эҙләү",
-       "stub-threshold": "<a href=\"#\" class=\"stub\">Материалдарға һылтанмалар </a> форматлау сиге (байттарҙа)",
+       "stub-threshold": "Яһалма һылтамаларҙың биҙәлеше буйынса сикләүҙәр ($1):",
        "stub-threshold-sample-link": "миҫал",
        "stub-threshold-disabled": "Һүндерелгән",
        "recentchangesdays": "Күҙәтеү исемлегендә күренгән көндәр һаны:",
        "prefs-common-css-js": "Бөтә күренештәр өсөн дөйөм CSS/JS:",
        "prefs-reset-intro": "Был битте, көйләүҙәрегеҙҙе ғәҙәттәге көйләүҙәргә ташлатыу өсөн ҡулланып була.\nРаҫлағандан һуң ғәмәлде кире ҡайтарып булмаясаҡ.",
        "prefs-emailconfirm-label": "Электрон почтаны раҫлау:",
-       "youremail": "Электрон почта *",
+       "youremail": "Электрон почта :",
        "username": "{{GENDER:$1|Ҡулланыусы исеме}}:",
        "prefs-memberingroups": "{{GENDER:$2|Ағза}} {{PLURAL:$1|төркөмө|төркөмдәре}}:",
        "prefs-registration": "Теркәлеү ваҡыты:",
-       "yourrealname": "Һеҙҙең ысын исемегеҙ (*)",
+       "yourrealname": "Һеҙҙең ысын исемегеҙ:",
        "yourlanguage": "Тышҡы күренештә ҡулланылған тел:",
        "yourvariant": "Эстәлектең тел варианты:",
        "prefs-help-variant": "Вики биттәренең эстәлеген күрһәтеү өсөн өҫтөнлөк бирелгән тел йәки орфография.",
        "right-sendemail": "Башҡа ҡатнашыусыларға электрон почта аша хат ебәреү",
        "right-passwordreset": "Серһүҙҙе яңыртыу осраҡтарын ҡарау",
        "right-managechangetags": "[[Special:Tags|билдәләр]] мәғлүмәттәр базаһында төҙөү һәм юйыу",
+       "right-applychangetags": " [[Special:Tags|тамғаһын]] үҙегеҙҙең төҙөтеү менән ҡулланырға",
+       "right-changetags": "Айырым үҙгәртеүҙәрҙә һәм журнал яҙмаланыда[[Special:Tags|тамғаһын]] өҫтәү һәм юйыу",
+       "grant-generic": "Хоҡуҡтар йыйынтығы «$1»",
+       "grant-group-page-interaction": "Башҡа биттәр менән бәйләнеш",
+       "grant-group-file-interaction": "Медиафайлдар менән бәйләнеш",
+       "grant-group-watchlist-interaction": "Күҙәтеүҙәр исемлеге менән бәйленеш",
        "grant-group-email": "Электрон хат ебәреү",
+       "grant-group-high-volume": "Юғары әүҙемлекле алым эшләргә",
+       "grant-group-customization": "Көйләүҙәр һәм өҫтөнлөк биргән көйләүҙәр",
+       "grant-group-administration": "Административ алымдар ҡулланыу",
+       "grant-group-other": "Әүҙемлек төрлө",
+       "grant-blockusers": "Иҫәп яҙмаларын блоклау һәм блоклауҙы асыу",
+       "grant-createaccount": "Иҫәп яҙмаһын булдырырға",
+       "grant-createeditmovepage": "Биттәрҙе булдырыу,мөхәррирләү һәм исемен үҙгәртеү",
+       "grant-delete": "Журналдағы биттәрҙе юйыу,төҙәтеү",
+       "grant-editinterface": "MediaWiki исеме арауығында төҙәтеү һәм ҡулланыусы CSS/JavaScript",
+       "grant-editmycssjs": "CSS/JavaScript ҡулланыусы кодын төҙәтеү",
        "grant-editmyoptions": "Һеҙҙең ҡулланыусы көйләүҙәрен мөхәррирләү",
+       "grant-editmywatchlist": "һеҙҙең күҙәтеүҙәр исемлеген мөхәррирләү",
+       "grant-editpage": "Ғәмәлдәге битте төҙәтеү",
+       "grant-editprotected": "Һаҡланған битте төҙәтеү",
+       "grant-highvolume": " Юғары әүҙемлектә мөхәррирләү",
+       "grant-oversight": "Башҡа ҡатнашыусылар тәҙәтеүенән бит версияһын йәшерергә",
+       "grant-patrol": "Бит үҙгәрештәрен күҙәтеү",
+       "grant-protect": "Битте һаҡлау һәм һаҡты сисеү",
+       "grant-rollback": "Биттеге үҙгәрештәрҙе кире ҡайтарыу",
+       "grant-sendemail": "Башҡа ҡатнашыусыларға электрон почта аша хат ебәреү",
+       "grant-uploadeditmovefile": "Файлдарҙы тейәү, алмаштырыу һәм исемен үҙгәртеү",
+       "grant-uploadfile": "Тағы файлдар тейәргә",
+       "grant-basic": "Төп хоҡуҡтар",
+       "grant-viewdeleted": "Юйылған файлдарҙы һәм биттерҙе тейәү",
+       "grant-viewmywatchlist": "һеҙҙең күҙәтеүҙәр исемлеген байҡау",
        "newuserlogpage": "Яңы ҡулланыусы яҙмалары",
        "newuserlogpagetext": "Яңы теркәлгән ҡатнашыусылар яҙмалары журналы.",
        "rightslog": "Ҡулланыусының хоҡуҡтары көндәлеге",
        "action-createpage": "Яңы бит яһау",
        "action-createtalk": "Фекер алышыу битен яһау",
        "action-createaccount": "Был ҡулланыусы иҫәп яҙыуын яһау",
+       "action-autocreateaccount": "Ҡатнашыусының тышҡы иҫәп яҙмаһы менән инергә",
+       "action-history": "Был биттең тарихын ҡарарға",
        "action-minoredit": "Был төҙәтеүҙе әҙ үҙгәреш тип билдәләү",
        "action-move": "Был биттең исемен үҙгәртеү",
        "action-move-subpages": "Был биттең һәм эске биттәренең исемен үҙгәртеү",
        "action-move-rootuserpages": "Ҡулланыусыларҙың төп биттәренең исемен үҙгәртеү",
+       "action-move-categorypages": "Категория биттәренең исемен үҙгәртеү",
        "action-movefile": "Был файлдың исемен үҙгәртеү",
        "action-upload": "Был файлды тейәү",
        "action-reupload": "Булған файлдың өҫтөнә яҙыу",
        "action-viewmywatchlist": "һеҙҙең күҙәтеүҙәр исемлеген байҡау",
        "action-viewmyprivateinfo": "һеҙҙең шәхси мәғлүмәтте байҡау",
        "action-editmyprivateinfo": "һеҙҙең шәхси мәғлүмәтте мөхәррирләү",
-       "nchanges": "$1 {{PLURAL:$1|1=үҙгәртеү|үҙгәртеү}}",
+       "action-editcontentmodel": "Биттең контент моделен мөхәррирләү",
+       "action-managechangetags": "Мәғлүмәт базаһында тамға булдырыу һәм юйыу",
+       "action-applychangetags": "Һеҙҙең үҙгәрештәр ТЕГын булдырырға",
+       "action-changetags": "Айырым үҙгәртеүҙәрҙә һәм журнал яҙмаланыда тег өҫтәү һәм юйыу",
+       "nchanges": "$1 {{PLURAL:$1|үҙгәртәү|үҙгәртеүҙәр}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|һеҙҙең һуңғы визит}}",
        "enhancedrc-history": "тарих",
        "recentchanges": "Һуңғы үҙгәртеүҙәр",
        "recentchanges-label-plusminus": "Бит шул тиклем байтҡа үҙгәрҙе",
        "recentchanges-legend-heading": "<strong>Легенда:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|Яңы биттәр исемлеген]] ҡарағыҙ)",
-       "rcnotefrom": "Түбәндә '''$2''' башлап ('''$1''' тиклем) үҙгәртеүҙәр күрһәтелгән.",
+       "recentchanges-submit": "Күрһәтергә",
+       "rcnotefrom": "Аҫтарак <strong>$3, $4</strong> өсөн {{PLURAL:$5|үҙгәртеүҙәр күрһәтелгән}} (<strong>$1</strong> артыҡ түгел).",
        "rclistfrom": "$3 $2 башлап яңы үҙгәртеүҙәрҙе күрһәт.",
        "rcshowhideminor": "бәләкәй төҙәтеүҙәрҙе $1",
        "rcshowhideminor-show": "Күрһәтергә",
        "rcshowhidemine": "минең үҙгәртеүҙәремде $1",
        "rcshowhidemine-show": "Күрһәтергә",
        "rcshowhidemine-hide": "Йәшерергә",
+       "rcshowhidecategorization": "$1 биттәрҙе категориялаштырыу",
+       "rcshowhidecategorization-show": "Күрһәтергә",
+       "rcshowhidecategorization-hide": "Йәшерелгән",
        "rclinks": "Һуңғы $2 көн эсендәге һуңғы $1 үҙгәртеүҙе күрһәтергә<br />$3",
        "diff": "айыр.",
        "hist": "тарих",
        "newpageletter": "Я",
        "boteditletter": "б",
        "number_of_watching_users_pageview": "[$1 күҙәткән {{PLURAL:$1|ҡатнашыусы}}]",
-       "rc_categories": "Ð\9eÑ\88о ÐºÐ°Ñ\82егоÑ\80иÑ\8fлаÑ\80Ò\99ан Ò\93Ñ\8bна («|» Ð¼ÐµÐ½Ó\99н Ð°Ð¹Ñ\8bÑ\80Ñ\8bÑ\80Ò\93а)",
-       "rc_categories_any": "Һәр",
+       "rc_categories": "Тик ÐºÐ°Ñ\82егоÑ\80иÑ\8fлаÑ\80Ò\99ан Ò\93Ñ\8bна (бүлеүÑ\81е Â«|»):",
+       "rc_categories_any": "Һайланғандың теләһә ҡайһыһы",
        "rc-change-size-new": "Үҙгәртештән һуң күләм: $1 {{PLURAL:$1|1=байт|байт}}",
        "newsectionsummary": "/* $1 */ яңы бүлек",
        "rc-enhanced-expand": "Ваҡ-төйәгенә тиклем күрһәтергә",
        "recentchangeslinked-summary": "Был күрһәтелгән бит һылтанма яһаған (йәки күрһәтелгән категорияға кергән) һуңғы үҙгәртеүҙәр исемлеге.\n[[Special:Watchlist|Күҙәтеү исемлегегеҙгә]] керә торған биттәр '''ҡалын''' итеп күрһәтелгән.",
        "recentchangeslinked-page": "Бит исеме:",
        "recentchangeslinked-to": "Киреһенсә, был биткә һылтанма яһаған биттәрҙәге үҙгәртеүҙәрҙе күрһәтергә",
+       "recentchanges-page-added-to-category": "[[:$1]] категорияға өҫтәлгән",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] һәм [[Special:WhatLinksHere/$1|{{PLURAL:$2|one page|$2 pages}}]]  категорияға өҫтәлгән",
+       "recentchanges-page-removed-from-category": "[[:$1]] категориянан алынған",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] һәм [[Special:WhatLinksHere/$1|{{PLURAL:$2|one page|$2 pages}}]]  категориянан алынған",
+       "autochange-username": "Автоматик рәүештә MediaWiki үҙгәртелә",
        "upload": "Файл тейәү",
        "uploadbtn": "Файлды тейәргә",
        "reuploaddesc": "Тейәү формаһына кире ҡайтырға",
        "upload-recreate-warning": "'''Иғтибар. Бындай исемле файл юйылған йәки күсерелгән. '''\nБыл биттең юйыуҙары һәм күсереүҙәре яҙмалары журналы түбәндә килтерелгән:",
        "uploadtext": "Файл тейәү өсөн түбәндәге форманы ҡулланығыҙ.\nЭлек тейәлгән файлдарҙы байҡар өсөн [[Special:FileList|тейәлгән файлдар исемлеген]] ҡарағыҙ. Файл тейәүҙәр шулай уҡ [[Special:Log/upload|тейәү яҙмаларына]], юйыуҙар иһә [[Special:Log/delete|юйыу яҙмаларына]] яҙылып баралар.\n\nФайлды мәҡәләгә өҫтәү өсөн киләһе юлдарҙы ҡуллана алаһығыҙ:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' — файлдың тулы өлгөһөн ҡуйыр өсөн;\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|тасуирлама]]</nowiki></code>''' — файлдың киңлек буйынса 200 нөктәгә тиклем бәләкәсәйтелгән, һулға тигеҙләнгән һәм аҫтында тасуирламаһы булған өлгөһөн ҡуйыр өсөн;\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' — эстәлеген биттә күрһәтмәйенсә файлға һылтанма ҡуйыу өсөн.",
        "upload-permitted": "{{PLURAL:$2|Рөхсәт ителгән файл төрө|Рөхсәт ителгән файл төрҙөре}}: $1.",
-       "upload-preferred": "Уңайлы файл типтары: $1.",
+       "upload-preferred": "Уңайлы файл типтары: {{PLURAL:$2|type|types}}: $1.",
        "upload-prohibited": "{{PLURAL:$2|Тыйылған файл төрө|Тыйылған файл төрҙәре}}: $1.",
        "uploadlogpage": "Тейәү яҙмалары",
        "uploadlogpagetext": "Түбәндә, һуңғы файл тейәүҙәр исемлеге күрһәтелгән.\nШулай уҡ [[Special:NewFiles|яңы файлдар галереяһын]] ҡарағыҙ; һуңғы тейәүҙәр ентекле рәүештә күрһәтелгән.",
        "ignorewarning": "Киҫәтеүҙәрҙе иғтибарға алмаҫҡа һәм барыбер файлды һаҡларға",
        "ignorewarnings": "Бөтә иҫкәрмәләргә иғтибар итмәҫкә",
        "minlength1": "Файлдың исеме кәмендә бер хәрефтән торорға тейеш.",
-       "illegalfilename": "«$1» Ñ\84айлÑ\8b Ð¸Ñ\81емендÓ\99 Ñ\80Ó©Ñ\85Ñ\81Ó\99Ñ\82 Ð¸Ñ\82елмÓ\99гÓ\99н Ñ\81имволдаÑ\80 Ð±Ð°Ñ\80.\nÐ\97инһаÑ\80 Ñ\84айл исемен үҙгәртегеҙ һәм яңынан тейәп ҡарағыҙ.",
+       "illegalfilename": "«$1» Ñ\84айлÑ\8b Ð¸Ñ\81емендÓ\99 Ñ\80Ó©Ñ\85Ñ\81Ó\99Ñ\82 Ð¸Ñ\82елмÓ\99гÓ\99н Ñ\81имволдаÑ\80 Ð±Ð°Ñ\80.\nФайл исемен үҙгәртегеҙ һәм яңынан тейәп ҡарағыҙ.",
        "filename-toolong": "Файл исемдәре 240 байтты үтергә тейеш түгел.",
        "badfilename": "Файлдың исеме $1 исеменә үҙгәртелде.",
        "filetype-mime-mismatch": "Файлдың «.$1» киңәйеүе файлдың ($2) MIME-төрөнә  тап килмәй.",
        "tmp-write-error": "Ваҡытлы файлға яҙҙырыу хатаһы.",
        "large-file": "Дәүмәле $1 байттан артмаған файлдар ҡулланырға кәңәш ителә (был файлдың дәүмәле $2 байт тәшкил итә).",
        "largefileserver": "Был файлдың дәүмәле рөхсәт ителгәндән ҙурыраҡ.",
-       "emptyfile": "Һеҙ тейәгән файл буш булырға тейеш.\nБыл файлдың исемен кереткән ваҡытта ебәрелгән хата арҡаһында булыуы мөмкин.\nЗинһар, һеҙ ысынлап та был файлды теләргә теләйһегеҙме икәнен тикшерегеҙ.",
+       "emptyfile": "Һеҙ тейәгән файл буш булырға тейеш.\nБыл файлдың исемен кереткән ваҡытта хата булыуы мөмкин.\nБыл файлды тейәргә теләйгәнегеҙҙе тикшерегеҙ.",
        "windows-nonascii-filename": "Был вики махсус символ булған файл исемдәрен терәкләмәй.",
        "fileexists": "Бындай исемле файл бар инде, зинһар, уны алыштырырға теләүегеҙҙә шикләнһәгеҙ,  <strong>[[:$1]]</strong>тикшерегеҙ.\n[[$1|thumb]]",
        "filepageexists": "Был файлдың тасуирламаһы бите булдырылған инде: <strong>[[:$1]]</strong>, әммә бындай исемле файл юҡ.\nКеретелгән тасуирлама файлдың тасуирламаһы битендә сыҡмаясаҡ.\nЯңы тасуирлама өҫтәр өсөн, һеҙгә уны ҡул менән үҙгәртергә тура киләсәк.\n[[$1|thumb]]",
-       "fileexists-extension": "Ð\9eÒ¡Ñ\88аÑ\88 Ð¸Ñ\81емле Ñ\84айл Ð±Ð°Ñ\80: [[$2|thumb]]\n* Ð¢ÐµÐ¹Ó\99лгÓ\99н Ñ\84айлдÑ\8bÒ£ Ð¸Ñ\81еме: <strong>[[:$1]]</strong>\n* Ð\91Ñ\83лÒ\93ан Ñ\84айлдÑ\8bÒ£ Ð¸Ñ\81еме: <strong>[[:$2]]</strong>\nÐ\97инһаÑ\80, Ð±Ð°Ñ\88ҡа Ð¸Ñ\81ем Ò»Ð°Ð¹Ð»Ð°Ò\93Ñ\8bÒ\99.",
+       "fileexists-extension": "Ð\9eÒ¡Ñ\88аÑ\88 Ð¸Ñ\81емле Ñ\84айл Ð±Ð°Ñ\80: [[$2|thumb]]\n* Ð¢ÐµÐ¹Ó\99лгÓ\99н Ñ\84айлдÑ\8bÒ£ Ð¸Ñ\81еме: <strong>[[:$1]]</strong>\n* Ð\91Ñ\83лÒ\93ан Ñ\84айлдÑ\8bÒ£ Ð¸Ñ\81еме: <strong>[[:$2]]</strong>\nÐ\91аÑ\88ҡа Ñ\82Ó©Ñ\80лө Ð¸Ñ\81ем Ò»Ð°Ð¹Ð»Ð¿Ñ\80Ò\93а Ñ\82елÓ\99йһегеÒ\99ме?",
        "fileexists-thumbnail-yes": "Файл бәләкәйтелгән өлгө ''(шартлы рәсем)'' булырға тейеш.\n[[$1|thumb]]\nЗинһар, <strong>[[:$1]]</strong> файлын тикшерегеҙ.\nӘгәр ул ошо уҡ файлдың төп өлгөһө булһа, уның бәләкәйтелгән өлгөһөн айырым тейәүҙең кәрәге юҡ.",
        "file-thumbnail-no": "Файлдың исеме <strong>$1</strong> менән башлана.\nБәлки, ул рәсемдең бәләкәйтелгән өлгөһөлөр ''(шартлы рәсем)''.\nӘгәр һеҙҙә был рәсемдең ҙур өлгөһө булһа, зинһар, уны керетегеҙ йәки файлдың исемен үҙгәртегеҙ.",
        "fileexists-forbidden": "Бындай исемле файл бар инде һәм ул үҙгәртелә алмай.\nӘгәр һеҙ шулай ҙа был файлды тейәргә теләһәгеҙ, зинһар, кире ҡайтығыҙ һәм уны икенсе исем аҫтында тейәгеҙ.\n[[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "Бындай исемле файл дөйөм файл һаҡлағыста бар инде.\nӘгәр һеҙ шулай ҙа был файлды тейәргә теләһәгеҙ, зинһар, кире ҡайтығыҙ һәм яңы исем һайлағыҙ.\n[[File:$1|thumb|center|$1]]",
        "file-exists-duplicate": "Был файл түбәндәге {{PLURAL:$1|1=файл|файлдар}} менән тап килә:",
        "file-deleted-duplicate": "Оҡшаш файл ([[:$1]]) юйылғайны инде. Уны ҡайтанан тейәр алдынан, зинһар, файлды юйыу тарихын ҡарағыҙ.",
+       "file-deleted-duplicate-notitle": "Ошоға оҡшаған файл юйылған,ә исеме тыйылған булған. Яңынан тейәү алдынан администратор хоҡуғы булған кешенән тыйылған файлдарҙы ҡарап сығыуын һорарға кәрәк.",
        "uploadwarning": "Киҫәтеү",
        "uploadwarning-text": "Зинһар, түбәндәге файл тасуирламаһын үҙгәртегеҙ һәм яңынан ҡабатлап ҡарағыҙ.",
        "savefile": "Һөҙгөстө яҙҙырып ҡуйырға",
        "uploaddisabledtext": "Файлдар тейәү рөхсәт ителмәй.",
        "php-uploaddisabledtext": "Файлдар тейәү PHP көйләүҙәрендә рөхсәт ителмәй. Зинһар, file_uploads көйләүен тикшерегеҙ.",
        "uploadscripted": "Файлда булған HTML-кодты йәки скриптты браузер дөрөҫ эшкәртмәүе мөмкин.",
+       "upload-scripted-pi-callback": "XML стилендәге таблицаны эшкәртеү инструкцияһы булған файлды тейеп булмай.",
+       "uploaded-script-svg": "Тейәлгән SVG-файлында хәүефле  «$1» элементы табылды.",
+       "uploaded-hostile-svg": "Тейәлгән SVG-файлда хәүефле CSS-код табылды.",
+       "uploaded-event-handler-on-svg": "SVG-файлдары өсөн  <code>$1=\"$2\"</code> атрибуты ҡуйыу рөхсәт ителмәй.",
+       "uploaded-href-attribute-svg": "SVG-файлында href-атрибуты  <code><$1 $2=\"$3\"></code> тик http:// йәки https:// башланған маҡсатҡа рөхсәт ителә.",
+       "uploaded-href-unsafe-target-svg": "Тейәлгән SVG-файлда хәүефле мәғлүмәт табылды: URI <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-animate-svg": "Тейәлгән SVG-файлында тег «animate»  табылды,  «from»-атрибут <code>&lt;$1 $2=\"$3\"&gt;</code> ярҙамында һылтанманы үҙгәртә ала.",
+       "uploaded-setting-event-handler-svg": "Тейәлгән SVG-файлда  <code>&lt;$1 $2=\"$3\"&gt;</code> коды табылды, атрибуттар ҡуйыу блокланды.",
+       "uploaded-setting-href-svg": "«href» атрибутына  «set» тегын ҡуйыу блокланды.",
+       "uploaded-wrong-setting-svg": "«set» тегын файҙаланыу  блокланды. Тейәлгән SVG-файлында  <code>&lt;set to=\"$1\"&gt;</code> конструкцияһы табылды.",
+       "uploaded-setting-handler-svg": "SVG«handler» атрибутын өҫтәүсе SVG блокланды.Тейәлгән SVG-файлда  <code>$1=\"$2\"</code> конструкцияһы табылды.",
+       "uploaded-remote-url-svg": "SVG«handler» атрибутын өҫтәүсе SVG блокланды.Тейәлгән SVG-файлда  <code>$1=\"$2\"</code> конструкцияһы табылды.",
+       "uploaded-image-filter-svg": "Тейәлгән SVG-файлда рәсемдәр фильтры табылды URL-адресом <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploadscriptednamespace": " SVG-файлында ярамаған исем бар '$1'",
+       "uploadinvalidxml": "Тейәлгән файлда анализлап булмай XML .",
        "uploadvirus": "Файлда вирус бар!\nТулыраҡ мәғлүмәт: $1",
        "uploadjava": "Был, эсендә Java .class файлы булған ZIP-архив.\nИменлек өсөн Java-файлдарын тейәү тыйылған.",
        "upload-source": "Сығанаҡ файл",
        "upload-options": "Тейәү көйләүҙәре",
        "watchthisupload": "Файлды күҙәтергә",
        "filewasdeleted": "Бындай исемле файл бығаса булған һәм юйылған. Зинһар, ҡабаттан тейәр алдынан $1 битен ҡарағыҙ.",
+       "filename-thumb-name": "Файл исеме рәсемдең бәләкәйләтелгән исеменә оҡшаған. Зинһар, бындай миниатюраларҙы вики-проектҡа тейәмәгеҙ. Әгәр һеҙгә был файл бик кәрәк булһа, исемен эстәлегенә ярашлы үҙгәртегеҙ.",
        "filename-bad-prefix": "Тейәлә торған файлдың исеме ''«$1»''' менән башлана һәм ул цифрлы камераларҙа файлдарға уҙенән-үҙе бирелә торған исемгә оҡшаған.\nЗинһар, файлды яҡшыраҡ тасуирлаған исем һайлағыҙ.",
        "upload-proto-error": "Протокол дөрөҫ түгел",
        "upload-proto-error-text": "Алыҫтан тейәү өсөн <code>http://</code> йәки <code>ftp://</code> менән башланған адрес кәрәк.",
        "upload-too-many-redirects": "URL бигерәк күп йүнәлтмәләр яһай.",
        "upload-http-error": "HTTP хата килеп сыҡты: $1",
        "upload-copy-upload-invalid-domain": "Был доменға ҡараған сайттарҙан файл күсереү асыҡ түгел",
+       "upload-foreign-cant-upload": "Вики ситтәге репозиторийға файл тейәргә көйләнмәгән.",
+       "upload-dialog-title": "Файлды тейәргә",
+       "upload-dialog-button-cancel": "Кире алырға",
+       "upload-dialog-button-done": "Әҙер",
+       "upload-dialog-button-save": "Һаҡларға",
+       "upload-dialog-button-upload": "Тейәргә",
+       "upload-form-label-infoform-title": "Ентеклерәк",
+       "upload-form-label-infoform-name": "Исем",
+       "upload-form-label-infoform-name-tooltip": "Башлыҡтың үҙенсәләкле исеме һаҡланасаҡ. Ябай телдә яҙылған исем һәм пробелдар ҡулланырға була. Киңәйтеүҙәр ҡулланмағыҙ.",
+       "upload-form-label-infoform-description": "Тасуирлау",
+       "upload-form-label-infoform-description-tooltip": "Был әҫәр тураһында ҡыҫҡаса тасуирлама бирегеҙ. Фото өсөн - фотола нимә иң мөһиме, төшөрөлгән урынды яҙығыҙ.",
+       "upload-form-label-usage-title": "Ҡулланыу",
+       "upload-form-label-usage-filename": "Файл исеме",
+       "foreign-structured-upload-form-label-own-work": "Был минең эш",
+       "foreign-structured-upload-form-label-infoform-categories": "Категориялар",
+       "foreign-structured-upload-form-label-infoform-date": "Дата",
+       "foreign-structured-upload-form-label-own-work-message-local": "Тейәлгән файл  {{SITENAME}} лицензия сәйәсәтенә ярашлы икәнен раҫлайым.",
+       "foreign-structured-upload-form-label-not-own-work-message-local": "{{SITENAME}} ҡағиҙәләренә ярашлы файлды тейәй алмаһағыҙ, диалог теҙерәһен ябығыҙ ҙа тейәү !с!н башҡа ысулды һайлағыҙ.",
+       "foreign-structured-upload-form-label-not-own-work-local-local": "Ошонда эшләп ҡарағыҙ[[Special:Upload|килешеү буйынса тейәү бите]].",
+       "foreign-structured-upload-form-label-own-work-message-default": "Был файлды дөйөм репозиторийға күсереүемде аңлайым. Быны ҡулланыусы килешеүе һәм лицензия сәйәсәтенә ярашлы эшләүемде раҫлайым.",
+       "foreign-structured-upload-form-label-not-own-work-message-default": "{{SITENAME}} ҡағиҙәләренә ярашлы файлды тейәй алмаһағыҙ, диалог теҙерәһен ябығыҙ ҙа тейәү өсөн башҡа ысулды һайлағыҙ.",
+       "foreign-structured-upload-form-label-not-own-work-local-default": "{{SITENAME}} талаптарына ярашлы файлы тейәп булһа,  [[Special:Upload|тейәү битен]] ҡарағыҙ.",
+       "foreign-structured-upload-form-label-own-work-message-shared": "Мин ошо файлдың авторы икәнемде раҫлайым һәм был файлды   Викискладта [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0] лицензияһы аҫтынан кире алмаҫҡа урынлаштырырға ризалы! бирәм, шулай уҡ  [https://wikimediafoundation.org/wiki/ҡулланыу шарттары] менән килешәм.",
+       "foreign-structured-upload-form-label-not-own-work-message-shared": "Әгәр ошо файлдың авторы түгелһегеҙ һәм уны икенсе лицензия аҫтында сығарырға теләйһегеҙ икән,  [https://commons.wikimedia.org/wiki/Special:UploadWizard Викискладҡа күсереү оҫталары] мөмкинлеген файҙаланығыҙ.",
+       "foreign-structured-upload-form-label-not-own-work-local-shared": "{{SITENAME}} талаптарына ярашлы файлы тейәп булһа,  [[Special:Upload|тейәү битен]] ҡарағыҙ.",
        "backend-fail-stream": "$1 файлын трансляциялап булмай.",
        "backend-fail-backup": "$1 файлының резерв күсермәһен эшләп булмай.",
        "backend-fail-notexists": "$1 файлы юҡ.",
        "backend-fail-closetemp": "Ваҡытлы файлды ябып булмай.",
        "backend-fail-read": "«$1» файлын уҡып булмай.",
        "backend-fail-create": "«$1» файлын яҙып булмай.",
-       "backend-fail-maxsize": "$1 Ñ\84айлÑ\8bн Ñ\8fÒ\99Ñ\8bп Ð±Ñ\83лманÑ\8b, Ñ\81өнки Ñ\83нÑ\8bÒ£ ÐºÒ¯Ð»Ó\99ме {{PLURAL:$2|1=$2 Ð±Ð°Ð¹Ñ\82Ñ\82ан|$2 Ð±Ð°Ð¹Ñ\82Ñ\82ан}} ÐºÒ¯Ð¿.",
+       "backend-fail-maxsize": "$1 Ñ\84айлÑ\8bн Ñ\8fÒ\99Ñ\8bп Ð±Ñ\83лманÑ\8b, Ñ\81өнки Ñ\83нÑ\8bÒ£ ÐºÒ¯Ð»Ó\99ме {{PLURAL:$2|1=$2 Ð±Ð°Ð¹Ñ\82Ñ\82ан|$2 Ð±Ð°Ð¹Ñ\82Ñ\82ан}} Ð°Ñ\80Ñ\82Ñ\8bÒ¡.",
        "backend-fail-readonly": "$1 һаҡлағысы әлегә уҡыу өсөн генә асыҡ. Сәбәбе: $2",
        "backend-fail-synced": "$1 файлы эске һаҡлағыста ярашһыҙ хәлдә тора.",
        "backend-fail-connect": "\"$1\" һаҡлағысы менән бәйләнеш яһап булманы.",
        "uploadstash-badtoken": "Был ғәмәлде башҡарып булманы, һеҙҙең төҙәтеү яҙмағыҙ ғәмәлдән сыҡҡан булыуы ихтимал. Яңынан ҡабатлап ҡарағыҙ.",
        "uploadstash-errclear": "Файлдарҙы таҙартып булманы.",
        "uploadstash-refresh": "Файлдар исемлеген яңыртырға",
+       "uploadstash-thumbnail": "һүрәттәрҙе ҡарау",
        "invalid-chunk-offset": "Ҡабул ителмәгән фрагмент шылыуы",
        "img-auth-accessdenied": "Керергә рөхсәт ителмәй",
        "img-auth-nopathinfo": "PATH_INFO юҡ.\nҺеҙҙең сервер был мәғлүмәтте ебәреү өсөн көйләнмәгән.\nУның CGI нигеҙендә эшләүе һәм img_auth ҡулланмауы мөмкин.\nТулыраҡ мәғлүмәт: https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization",
        "licenses-edit": "Лицензия параметрҙарын үҙгәртергә",
        "license-nopreview": "(Ҡарап сығыу мөмкин түгел)",
        "upload_source_url": "(Дөрөҫ, дөйөм ҡулланыу өсөн асыҡ URL-адрес)",
-       "upload_source_file": "(һеҙҙең компьютерҙағы файл)",
+       "upload_source_file": "(һеҙ компьютерҙағы файлды һайланығыҙ)",
+       "listfiles-delete": "юйырға",
        "listfiles-summary": "Был ярҙамсы бит бөтә тейәлгән файлдарҙы күрһәтә.",
        "listfiles_search_for": "Файл исеме буйынса эҙләү:",
        "listfiles-userdoesnotexist": "\"$1\" иҫәп яҙмаһы теркәлмәгән.",
        "filerevert-legend": "Файлдың элекке өлгөһөнә ҡайтыу",
        "filerevert-intro": "Һеҙ '''[[Media:$1|$1]]''' файлын [$2 $3 булдырылған $4 өлгөһөнә] ҡайтараһығыҙ.",
        "filerevert-comment": "Сәбәп:",
-       "filerevert-defaultcomment": "$1 $2 өлгөһөнә ҡайтыу",
+       "filerevert-defaultcomment": "$1 $2 ($3) өлгөһөнә ҡайтыу",
        "filerevert-submit": "Кире алырға",
        "filerevert-success": "'''[[Media:$1|$1]]''' [$2 $3 булдырылған $4 өлгөһөнә] ҡайтарылды.",
        "filerevert-badversion": "Файлдың күрһәтелгән ваҡыт билдәһе менән алдағы урындағы өлгөһө юҡ.",
        "unwatchedpages": "Бер кем дә күҙәтмәгән биттәр",
        "listredirects": "Йүнәлтеүҙәр исемлеге",
        "listduplicatedfiles": "Күсермәләр менән файлдар исемлеге",
+       "listduplicatedfiles-summary": "Был файлдар исемлеге, һуңғы файл башҡа ҡайһы бер файлдарҙың дубликаты һанала. Тик локаль файрдар иҫәпләнә.",
+       "listduplicatedfiles-entry": " [[:File:$1|$1]] файлының — [[$3|{{PLURAL:$2|$2 дубликаты}}]] бар.",
        "unusedtemplates": "Ҡулланылмаған ҡалыптар",
        "unusedtemplatestext": "Был биттә {{ns:template}} исемдәр арауығының бөтә башҡа биттәргә индерелмәгән биттәре исемлеге килтерелгән.\nҠалыпты юйыр алдынан, уға башҡа һылтанмалар юҡлығын тикшерергә онотмағыҙ.",
        "unusedtemplateswlh": "Башҡа һылтанмалар",
        "randomincategory-nopages": "[[:Category:$1|$1]] категорияһында биттәр юҡ.",
        "randomincategory-category": "Категория:",
        "randomincategory-legend": "Категорияла осраҡлы файл",
+       "randomincategory-submit": "Күсергә",
        "randomredirect": "Осраҡлы биткә күсеү",
        "randomredirect-nopages": "\"$1\" исемдәр арауығында йүнәлтеүҙәр юҡ.",
        "statistics": "Статистика",
        "unusedimages": "Ҡулланылмаған файлдар",
        "wantedcategories": "Кәрәкле категориялар",
        "wantedpages": "Кәрәкле биттәр",
+       "wantedpages-summary": "Иң күп һылтанмалары булған ғәмәлдәге биттәр, булмаған биттәргә һылтанмаһы булған биттәр күрһәтермәгән. Ғәмәлдә булмаған биттәргә һылтанмаларҙы ҡарау өсөн [[{{#special:BrokenRedirects}}|ғәмәлдә булмаған йүнәлтеүҙәр]].",
        "wantedpages-badtitle": "Һорау һөҙөмтәләрендә дөрөҫ булмаған исем: $1",
        "wantedfiles": "Кәрәкле файлдар",
        "wantedfiletext-cat": "Киләһе файлдарҙы улар булмаған хәлдә ҡулланырға тырышыла. Тыш һаҡлағыстарҙа булған файлдар был исемлеккә яңылыш эләгеүе мөмкин. Бындай хаталы белдереүҙәр <del>һыҙыҡ</del> менән күрһәтеләсәк. Шулай уҡ, булмаған файлдарҙы алған биттәр киләһе исемлектә күрһәтелгән: [[:$1]]",
+       "wantedfiletext-cat-noforeign": "Түбәндәге файлдар ҡулланыла, әммә ғәмәлдә юҡ. Бынан тыш был файлға һылтаныусы биттәр ғәмәлдә юҡ һәм [[:$1]] битендә иҫәпләнә.",
        "wantedfiletext-nocat": "Киләһе файлдарҙы улар булмаған хәлдә ҡулланырға тырышыла. Тыш һаҡлағыстарҙа булған файлдар был исемлеккә яңылыш эләгеүе мөмкин. Бындай хаталы белдереүҙәр <del>һыҙыҡ</del> менән күрһәтеләсәк.",
+       "wantedfiletext-nocat-noforeign": "Түбәндәге файл ҡулланыла, әммә ул юҡ.",
        "wantedtemplates": "Кәрәкле ҡалыптар",
        "mostlinked": "Иң күп һылтанма яһалған биттәр",
        "mostlinkedcategories": "Иң күп һылтанма яһалған категориялар",
-       "mostlinkedtemplates": "Ð\98Ò£ ÐºÒ¯Ð¿ Ò»Ñ\8bлÑ\82анма Ñ\8fһалÒ\93ан Ò¡Ð°Ð»Ñ\8bпÑ\82ар",
+       "mostlinkedtemplates": "Ð\98Ò£ ÐºÒ¯Ð¿ Ò¡Ñ\83лланÑ\8bлÒ\93ан Ð±Ð¸Ñ\82Ñ\82Ó\99р",
        "mostcategories": "Күп категорияларға кертелгән биттәр",
        "mostimages": "Иң күп һылтанма яһалған рәсемдәр",
        "mostinterwikis": "Иң күп интервики-һылтанмалы биттәр",
        "mostrevisions": "Иң күп үҙгәртеү яһалған биттәр",
        "prefixindex": "Исемдәре башында ҡушымта торған биттәр",
        "prefixindex-namespace": "Префикслы бар биттәр ( $1 исемдәр арауығы)",
+       "prefixindex-submit": "Күрһәтергә",
        "prefixindex-strip": "Һөҙөмтәләр исемлегендә префиксты йәшерергә",
        "shortpages": "Ҡыҫҡа биттәр",
        "longpages": "Оҙон биттәр",
        "deadendpagestext": "Түбәндәге биттәр {{SITENAME}} проектының башҡа биттәренә һылтанма яһамай.",
        "protectedpages": "Һаҡланған биттәр",
        "protectedpages-indef": "Сикләнмәгән һаҡлауҙар ғына",
+       "protectedpages-summary": "Бында әлегә мәлдә булған һәм һаҡланыулы биттәр килтерелгән. Исемлекте ҡарау өсөн [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Эҙмә-эҙлекле һаҡлауҙар ғына",
        "protectedpages-noredirect": "Йүнәлтеүҙәрҙе йәшерергә",
        "protectedpagesempty": "Әлеге ваҡытта күрһәтелгән шарттар менән һаҡланған биттәр юҡ.",
        "protectedpages-performer": "Ҡатнашыусыны һаҡлау",
        "protectedpages-params": "Һаҡ параметрҙары",
        "protectedpages-reason": "Сәбәп",
+       "protectedpages-submit": "Биттәрҙе күрһәтеү",
        "protectedpages-unknown-timestamp": "Билдәһеҙ",
        "protectedpages-unknown-performer": "Билдәһеҙ ҡатнашыусы",
        "protectedtitles": "Тыйылған исемдәр",
+       "protectedtitles-summary": "Бында яңынан булдырыуҙан һаҡланған атамалар килтерелгән. Исмелекте ҡарау өсөн: [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Әлеге ваҡытта күрһәтелгән шарттар менән һаҡланған исемдәр юҡ.",
+       "protectedtitles-submit": "Күренгән исем",
        "listusers": "Ҡатнашыусылар исемлеге",
        "listusers-editsonly": "Кәмендә бер үҙгәртеү индергән ҡатнашыусыларҙы ғына күрһәтергә",
        "listusers-creationsort": "Булдырыу көнө буйынса тәртипкә килтерергә",
        "listusers-desc": "Кәмеү буйынса айырырға",
-       "usereditcount": "$1 {{PLURAL:$1|үҙгәртеү}}",
+       "usereditcount": "{{PLURAL:$1|үҙгәртеү}}",
        "usercreated": "$3 ҡулланыусыһының теркәлеү ваҡыты: $1 $2",
        "newpages": "Яңы биттәр",
+       "newpages-submit": "Күрһәтергә",
        "newpages-username": "Ҡатнашыусы:",
        "ancientpages": "Иң иҫке мәҡәләләр",
        "move": "Яңы исем биреү",
        "notargettext": "Һеҙ был ғәмәл өсөн кәрәкле битте йәки ҡатнашыусыны күрһәтмәгәнһегеҙ.",
        "nopagetitle": "Бындай бит юҡ",
        "nopagetext": "Һеҙ күрһәткән бит юҡ.",
-       "pager-newer-n": "{{PLURAL:$1|1=1 яңыраҡ|$1 яңыраҡ}}",
+       "pager-newer-n": "$1{{PLURAL:$1|1=1 яңыраҡ|$1 яңыраҡ}}",
        "pager-older-n": "{{PLURAL:$1|1=1 иҫкерәк|$1 иҫкерәк}}",
        "suppress": "Йәшереү",
        "querypage-disabled": "Был махсус бит һөҙөмтәлелекте арттырыу өсөн ябылған.",
        "apihelp": "API белешмәһе",
        "apihelp-no-such-module": "«$1» модуле табылмаған.",
        "apisandbox": "API һынау урыны",
+       "apisandbox-jsonly": " API-һынап ҡарау урыны өсөн  JavaScript талап ителә.",
        "apisandbox-api-disabled": "Был сайтта API һүндерелгән.",
-       "apisandbox-intro": "''MediaWiki API''' өйрәнеү бите.  API ҡулланыу тураһында белешмә алыу өсөн [//www.mediawiki.org/wiki/API:Main_page API документацияһы]на мөрәжәғәт итегеҙ. Мәҫәләң, [//www.mediawiki.org/wiki/API#A_simple_example Башбит эстәлеген нисек алырға]. Башҡа миҫалдарҙы күреү өсөн ғәмәлде ҡулланығыҙ.",
+       "apisandbox-intro": "Был битте <strong>MediaWiki API</strong> менән тәжрибәләр өсөн ҡулланығыҙ. API ҡулланыуҙа тулыраҡ мәғлүмәт өсөн    [[mw:API:Main page| API документацияһы]] мөрәжәғәт итегеҙ. Мәҫәлән, [//www.mediawiki.org/wiki/API#A_simple_example Баш биттең йөкмәткеһен нисек алырға]. Башҡа миҫалдарҙы ҡарау өсөн ғәмәл һайлағыҙ. Иғтибар, тәжрибәләр өсөн ҡулланылһа ла, был биттә башҡарылған ғәмәлдәр викиға үҙгәрештәр индерә ала.",
+       "apisandbox-fullscreen": "Панелды асырға",
+       "apisandbox-fullscreen-tooltip": "Браузер тәҙрәһен тултырыу өсөн һынап ҡарау панелен асырға.",
+       "apisandbox-unfullscreen": "Битте күрһәтергә",
+       "apisandbox-unfullscreen-tooltip": "MediaWiki навигация һылтанмалары күренһен өсөн һынап ҡарау панелен бәләкәйләтергә.",
        "apisandbox-submit": "Һоратыу яһарға",
        "apisandbox-reset": "Таҙарт",
-       "apisandbox-examples": "Миҫал",
+       "apisandbox-retry": "Ҡабатлау",
+       "apisandbox-loading": " API-модуле өсөн мәғлүмәт тейәү «$1»…",
+       "apisandbox-load-error": "API-модуле өсөн мәғлүмәт тейәгәндә хата китте «$1»: $2",
+       "apisandbox-no-parameters": "API-модуленең параметрҙары юҡ.",
+       "apisandbox-helpurls": "Белешмәгә һылтанма",
+       "apisandbox-examples": "Миҫалдар",
+       "apisandbox-dynamic-parameters": "Өҫтәмә параметрҙар",
+       "apisandbox-dynamic-parameters-add-label": "Параметр өҫтәргә",
+       "apisandbox-dynamic-parameters-add-placeholder": "Параметр исеме",
+       "apisandbox-dynamic-error-exists": " «$1» исемле параметр бар.",
+       "apisandbox-deprecated-parameters": "Иҫкергән параметрҙар",
+       "apisandbox-fetch-token": "Торенды автоматик тултырыу",
+       "apisandbox-submit-invalid-fields-title": "Ҡайһы бер ҡырҙар дөрөҫ түгел",
+       "apisandbox-submit-invalid-fields-message": "Билдәләнгән ҡырҙырҙы тәҙәтегеҙ һәм яңынан эшләр ҡарағыҙ.",
        "apisandbox-results": "Һөҙөмтә",
+       "apisandbox-sending-request": "API-ғариза ебәреү",
+       "apisandbox-loading-results": "API-яуап алыу",
+       "apisandbox-results-error": " API-яуап алғанда хата китте: $1.",
        "apisandbox-request-url-label": "Һоратыуҙың URL-адресы:",
-       "apisandbox-request-time": "Мөрәжәғәт ваҡыты:$1",
+       "apisandbox-request-time": "Мөрәжәғәт ваҡыты:{{PLURAL:$1|$1 мс}}",
+       "apisandbox-results-fixtoken": "Токенды төҙөтегеҙ, ебәреүҙе ҡабатлағыҙ",
+       "apisandbox-results-fixtoken-fail": " «$1» токенына инеп булманы",
+       "apisandbox-alert-page": "Был биттә ҡайһы бер ҡырҙар дөрөҫ түгел.",
+       "apisandbox-alert-field": "Был ҡыр дәүмәле ярамай.",
        "booksources": "Китап сығанаҡтары",
        "booksources-search-legend": "Китап сығанаҡтарын эҙлә",
        "booksources-search": "Эҙләү",
        "booksources-text": "Түбәндәге исемлектә — китаптар һатыу менән шөғөлләнеүсе сайттарға һәм китапханаларҙың эҙләү системаларына һылтанмалар, һәм уларҙа һеҙ эҙләгән китаптар тураһында өҫтәмә мәғлүмәт булыуы мөмкин.",
        "booksources-invalid-isbn": "Күрһәтелгән ISBN номерҙа хата булырға тейеш. Зинһар, номерҙы сығанаҡтан дөрөҫ күсереүегеҙҙе тикшерегеҙ.",
        "specialloguserlabel": "Башҡарыусы:",
-       "speciallogtitlelabel": "Маҡсат (исем йәки ҡулланыусы):",
+       "speciallogtitlelabel": "Маҡсат (исем йәки ҡулланыусы {{ns:user}}):",
        "log": "Журналдар",
+       "logeventslist-submit": "Күрһәтергә",
        "all-logs-page": "Барлыҡ асыҡ журналдар",
        "alllogstext": "{{SITENAME}} проектының дөйөм яҙмалар журналы исемлеге. Һеҙ һөҙөмтәләрҙе журнал төрө буйынса, ҡатаншыусы исеме буйынса (ҙур/бәләкәй хәрефкә һиҙгер) йәки ҡағылған бит исеме буйынса (шулай уҡ ҙур/бәләкәй хәрефкә һиҙгер) һайлап ала алаһығыҙ.",
        "logempty": "Журнал яҙмаларында һайланған юлдар юҡ.",
        "log-title-wildcard": "Керетелгән хәрефтәр менән башланған исемдәрҙе табырға",
        "showhideselectedlogentries": "Журналдың һайланған яҙмаларын күрһәтергә/йәшерергә.",
+       "log-edit-tags": "Журналдағы яҙмала тэгты мөхәррирләргә",
+       "checkbox-select": "Һайланған: $1",
+       "checkbox-all": "Барыһы",
+       "checkbox-none": "Юҡ",
+       "checkbox-invert": "Әйләндерү",
        "allpages": "Бөтә биттәр",
        "nextpage": "Киләһе бит ($1)",
        "prevpage": "Алдағы бит ($1)",
        "cachedspecial-viewing-cached-ts": "Һеҙ биттең кэшланған өлгөһөн ҡарайһығыҙ. Уның хәҙерге өлгөнән бик ныҡ айырылыуы мөмкин.",
        "cachedspecial-refresh-now": "Һуңғы версияны ҡарарға",
        "categories": "Категориялар",
-       "categoriespagetext": "Түбәндәге {{PLURAL:$1|1=категорияла|категорияларҙа}} биттәр йәки файлдар бар.\n[[Special:UnusedCategories|Ҡулланылмаған категориялар]] бында күрһәтелмәгән.\nШулай уҡ [[Special:WantedCategories|кәрәкле категориялар исемлеген]] ҡарағыҙ.",
+       "categories-submit": "Күрһәтергә",
+       "categoriespagetext": "{{PLURAL:$1|1=Был категория}}ла биттәр һәм    медиа-файллардар бар.\nАҫта [[Special:UnusedCategories|ҡулланылмаған категориялар]] күһәтелмәгән.\nШулай уҡ  [[Special:WantedCategories|талап ителгән категориялар]] күһәтелгән.",
        "categoriesfrom": "Ошондай хәрефтәрҙән башланған категорияларҙы күрһәтергә:",
        "special-categories-sort-count": "күләме буйынса тәртипкә килтерергә",
        "special-categories-sort-abc": "алфавит буйынса тәртипкә килтерергә",
        "activeusers-hidebots": "Боттарҙы йәшерергә",
        "activeusers-hidesysops": "Хакимдәрҙе йәшерергә",
        "activeusers-noresult": "Ҡатнашыусылар табылманы",
+       "activeusers-submit": "Әүҙем ҡулланыусыларҙы күрһәтергә",
        "listgrouprights": "Ҡатнашыусылар төркөмө хоҡуҡтары",
        "listgrouprights-summary": "Түбәндә был вики-проектта билдәләнгән ҡатнашыусы төркөмдәре килтерелгән һәм уларҙың хоҡуҡтары күрһәтелгән.\nШәхси хоҡуҡтар тураһында [[{{MediaWiki:Listgrouprights-helppage}}|өҫтәмә мәғлүмәт]] булыуы мөмкин.",
        "listgrouprights-key": "Легенда:\n* <span class=\"listgrouprights-granted\">Бирелгән хоҡуҡтар</span>\n* <span class=\"listgrouprights-revoked\">Алынған хоҡуҡтар</span>",
        "listgrouprights-removegroup-self-all": "Үҙенең иҫәп яҙмаһынан бөтә төркөмдәрҙе юйыу",
        "listgrouprights-namespaceprotection-header": "Исемдәр арауығы сикләүҙәре",
        "listgrouprights-namespaceprotection-namespace": "Исемдәр арауығы",
+       "listgrouprights-namespaceprotection-restrictedto": "Ҡулланыусыға мәхәррирләү мөкинлеген биргән хоҡуҡтар",
+       "listgrants": "Рөхсәттәр",
+       "listgrants-summary": "Түбәндә ҡайһы ҡулланыусы хоҡуҡтарына бәйләнгәнлеген дә күрһәткән рөхсәт итеүҙәр исемлеге килтерелә. Ҡатнашыусылар ҡатнашыусы ҡушымталарға биргән сикле хоҡуҡтар менән ҡушымталарға үҙҙәренең иҫәп яҙмаларын ҡулланырға рөхсәт итә ала. Әммә ҡатнашыусы исеменән ғәмәлдә булған ҡушымта, иҫәп яҙмаһында булмаған хоҡуҡтар менән ҡуллана ала. Айырым хоҡуҡтар тураһында [[{{MediaWiki:Listgrouprights-helppage}}|өҫтәмә мөғлүмәт]] алырға була.",
+       "listgrants-grant": "Рөхсәт",
+       "listgrants-rights": "Хоҡуҡтар",
+       "trackingcategories": "Категорияларҙы күҙәтеү",
+       "trackingcategories-summary": "Был биттә MediaWiki программа тәьминиәте тарафынан автоматик рәүештә тултырылған күҙәтеүсе категориялар күрһәтелгән. Уларҙың исемен {{ns:8}} исемдәр киңлегендәге тейешле система хәбәрҙәрен үҙгәртеп алыштырырға була.",
+       "trackingcategories-msg": "Күҙәтеүсе категория",
        "trackingcategories-name": "Хәбәр исеме",
+       "trackingcategories-desc": "Категорияға индереү критерийҙары",
+       "noindex-category-desc": "Бит эҙләүсе роботтар тарафынан индексацияланмай, сөнки унда \"тылсымлы һүҙ\" <code><nowiki>__NOINDEX__</nowiki></code> бар һәм ул был флаг рөхсәт ителгән исемдәр киңлегендә урынлашҡан.",
+       "index-category-desc": "Биттә «тылсымлы һүҙ» бар<nowiki>__INDEX__</nowiki> (бит рөхсәт ителгән исемдәр арауығында ята), шуға күрә эҙләү системаһында индекслана.",
+       "post-expand-template-inclusion-category-desc": "Барлыҡ ҡалыптарҙы ла күрһәткәндән һуң биттең күләме арта<code>$wgMaxArticleSize</code>, шуға күрә ҡайһы берҙәре тулыһынса күрһәтелмәне.",
+       "post-expand-template-argument-category-desc": "Бит <code>$wgMaxArticleSize</code> ҡалып дәлиле асылғандан һуң ҙурыраҡ була(фигуралы өс йәйә, мәҫәлән<code>({{{Foo}}})</code>).",
+       "expensive-parserfunction-category-desc": "Биттә ресурс һыйҙырышлығы ҙур булған (<code>#ifexist</code> кеүек) функциялар күп ҡулланыла.Тулыраҡ -[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit] битендә.",
+       "broken-file-category-desc": "Был бит булмаған файлға һылтана",
+       "hidden-category-category-desc": "Был категорияла <code><nowiki>__HIDDENCAT__</nowiki></code> тамғаһы бар, был категория бүлегендә битте күрһәтмәй.",
+       "trackingcategories-nodesc": "Тасуирлама юҡ.",
+       "trackingcategories-disabled": "Категория һүндерелгән.",
        "mailnologin": "Хат ебәреү өсөн адрес юҡ",
        "mailnologintext": "Башҡа ҡатнашыусыларға хат ебәреү өсөн, һеҙ [[Special:UserLogin|танылырға]] һәм [[Special:Preferences|көйләүҙәрегеҙҙә]] ысын электрон адрес почтаһы кереткән булырға тейешһегеҙ.",
        "emailuser": "Ҡатнашыусыға хат",
        "mywatchlist": "Күҙәтеү исемлеге",
        "watchlistfor2": "$1 $2 өсөн",
        "nowatchlist": "Һеҙҙең күҙәтеү исемлегегеҙ буш.",
-       "watchlistanontext": "Күҙәтеү исемлеген ҡарау йәки мөхәррирләү өсөн $1 кәрәк.",
+       "watchlistanontext": "Күҙәтеү исемлеген ҡарау йәки мөхәррирләү өсөн  кәрәк.",
        "watchnologin": "Үҙегеҙҙе танытырға кәрәк",
        "addwatch": "Күҙәтеү исемлегенә өҫтәргә",
        "addedwatchtext": "\"[[:$1]]\" бите [[Special:Watchlist|күҙәтеү исемлегегеҙгә]] өҫтәлде.\nБыл биттә һәм уның фекер алышыу битендә буласаҡ бар үҙгәртеүҙәр ундағы исемлектә күрһәтеләсәк.",
+       "addedwatchtext-short": "\"$1\" бите Һеҙҙең күҙәтеү исемлегенә өҫтәлгән",
        "removewatch": "Күҙәтеү исемлегенән сығарырға",
-       "removedwatchtext": "«[[:$1]]» бите [[Special:Watchlist|күҙәтеү исемлегегеҙҙән]] сығарылды.",
+       "removedwatchtext": "«[[:$1]]» мәҡәләһе һәм уның фекер алышыу бите һеҙҙең [[Special:Watchlist|күҙәтеү исемлегенән]] сығарылды.",
+       "removedwatchtext-short": "\"$1\" бите һеҙҙең күҙәтеү исемлегенән алып ташланды.",
        "watch": "Күҙәтергә",
        "watchthispage": "Был битте күҙәтергә",
        "unwatch": "Күҙәтмәҫкә",
        "wlheader-enotif": "Электрон почта аша белдереү индерелгән.",
        "wlheader-showupdated": "Һеҙҙең аҙаҡҡы кереүегеҙҙән һуң үҙгәргән биттәр '''ҡалын''' шрифт менән күрһәтелгән.",
        "wlnote": "Түбәндә $3 $4 ваҡытына тиклем аҙаҡҡы {{PLURAL:$2|1=сәғәт|'''$2''' сәғәт}} эсендә эшләнгән {{PLURAL:$1|1=үҙгәртеү|'''$1''' үҙгәртеү}} күрһәтелгән.",
-       "wlshowlast": "Һуңғы $1 сәғәт $2 көн өсөн күрһәт",
+       "wlshowlast": "Һуңғы $1 сәғәт $2 көн эсендәгеһен күрһәтеү",
+       "watchlist-hide": "Йәшереү",
+       "watchlist-submit": "Күрһәтергә",
+       "wlshowtime": "Күрһәтеү өсөн ваҡыт арауығы",
+       "wlshowhideminor": "Әҙ генә үҙгәрештәр",
+       "wlshowhidebots": "Бот",
+       "wlshowhideliu": "танылған ҡулланыусылар",
+       "wlshowhideanons": "Аноним ҡулланыусылар",
+       "wlshowhidepatr": "Тикшерелгән төҙәтеүҙәр",
+       "wlshowhidemine": "Минең үҙгәртеүҙәр",
+       "wlshowhidecategorization": "Биттәрҙе категориялаштырыу",
        "watchlist-options": "Күҙәтеү исемлеге көйләүҙәре",
        "watching": "Күҙәтеү исемлегенә өҫтәү...",
        "unwatching": "Күҙәтеү исемлегенән сығарыу...",
        "deletepage": "Битте юйырға",
        "confirm": "Раҫларға",
        "excontent": "эстәлеге: \"$1\"",
-       "excontentauthor": "эстәлеге: \"$1\" (һәм берҙән-бер авторы \"[[Special:Contributions/$2|$2]]\" ине)",
+       "excontentauthor": "эстәлеге: \"$1\" (һәм берҙән-бер авторы \"[[Special:Contributions/$2|$2]] ([[User talk:$2|фекер алышыу]])\" ине)",
        "exbeforeblank": "юйыуға тиклемге эсләлеге: \"$1\"",
        "delete-confirm": "$1 — юйырға",
        "delete-legend": "Юйырға",
-       "historywarning": "'''Киҫәтеү:''' һеҙ юйырға йыйынған биттең тарихында яҡынса $1 {{PLURAL:$1|өлгө}} бар:",
+       "historywarning": "<strong>Иғтибар:</strong> һеҙ юйырға йыйынған биттең тарихында яҡынса $1 {{PLURAL:$1|өлгө}} бар:",
+       "historyaction-submit": "Күрһәтергә",
        "confirmdeletetext": "Һеҙ был биттең (йәки рәсемдең) һәм уның мәғлүмәттәр базаһындағы үҙгәртеүҙәр тарихының тулыһынса юйылыуын һоранығыҙ.\nЗинһар, быны эшләргә теләгәнегеҙҙе, үҙ хәрәкәттәрегеҙҙең һөҙөмтәләрен аңлағанығыҙҙы һәм [[{{MediaWiki:Policy-url}}]] бүлегендә белдереп кителгән ҡағиҙәләр буйынса эшләгәнегеҙҙе раҫлағыҙ.",
        "actioncomplete": "Ғәмәл үтәлде",
        "actionfailed": "Ғәмәл үтәлмәне",
        "delete-edit-reasonlist": "Сәбәптәр исемлеген мөхәррирләргә",
        "delete-toobig": "Был биттең үҙгәртеүҙәр тарихы бик оҙон, $1 {{PLURAL:$1|өлгөнән}} күберәк.\n{{SITENAME}} проектының эшмәкәрлеге боҙолмауы маҡсатында бындай биттәрҙе юйыу тыйылған.",
        "delete-warning-toobig": "Был биттең үҙгәртеүҙәр тарихы бик оҙон, $1 {{PLURAL:$1|өлгөнән}} күберәк.\nБитте юйыу {{SITENAME}} проектының эшмәкәрлеге боҙолоуына килтереүе мөмкин, һаҡлыҡ менән эш итегеҙ.",
+       "deleteprotected": "Был бит һаҡланған, уны юйҙыра алмайһығыҙ.",
+       "deleting-backlinks-warning": "<strong>Иҫкәртеү:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|Башҡа ҡатнашыусылар]] һеҙ юйырға теләгән биткә һылтана.",
        "rollback": "Үҙгәртеүҙәрҙе кире ҡайтарырға",
        "rollbacklink": "кире",
        "rollbacklinkcount": "$1 {{PLURAL:$1|1=төҙәтеүҙе|төҙәтеүҙе}} кире алырға",
        "rollback-success": "$1 уҙгәртеүҙәре кире алдынды;\n$2 өлгөһөнә ҡайтыу.",
        "sessionfailure-title": "Сеанс хатаһы",
        "sessionfailure": "Хәҙерге сеанста хаталар килеп сыҡҡан, булырға тейеш;\n\"сеансты баҫып алыу\"ға юл ҡуймау өсөн был ғәмәл үтәлмәне.\nАлдағы биткә кире  ҡайтығыҙ, битте яңыртығыҙ һәм яңынан ҡабатлап ҡарағыҙ.",
+       "changecontentmodel": "Биттең контент моделен мөхәррирләү",
+       "changecontentmodel-legend": "Модель эстәлеген үҙгәртергә",
+       "changecontentmodel-title-label": "Бит исемдәре",
+       "changecontentmodel-model-label": "Эстәлектең яңы моделе",
+       "changecontentmodel-reason-label": "Сәбәп",
+       "changecontentmodel-submit": "Үҙгәртергә",
+       "changecontentmodel-success-title": "Эстәлек моделе үҙгәртелде",
+       "changecontentmodel-success-text": "[[:$1]] эстәлек моделе үҙгәртелде",
+       "changecontentmodel-cannot-convert": "[[:$1]]  эстәлеге $2 тибына үҙгәртелә алмай",
+       "changecontentmodel-nodirectediting": "$1 эстәлеге моделен тураға мөхәррирләп булмай",
+       "log-name-contentmodel": "Эстәлек моделен үҙгәртеүҙәр журналы",
+       "log-description-contentmodel": "Эстәлек моделен үҙгәртеүҙәр менән бәйле ваҡиғалар",
+       "logentry-contentmodel-new": "$1 $3 {{GENDER:$2|}} битен булдырҙы, стандарт булмаған «$5» моделе ҡулланылды.",
+       "logentry-contentmodel-change": "$3 битендәге $1 {{GENDER:$2||}} эстәлек моделен $3  «$4» -тән «$5»-кә үҙгәртте.",
+       "logentry-contentmodel-change-revertlink": "кире алырға",
+       "logentry-contentmodel-change-revert": "кирегә",
        "protectlogpage": "Һаҡлау яҙмалары",
        "protectlogtext": "Түбәндә битте һаҡлауҙы үҙгәртеү яҙмалары килтерелгән.\nҺеҙ шулай уҡ хәҙерге ваҡытта [[Special:ProtectedPages|һаҡланған биттәр исемлеген]] ҡарай алаһығыҙ.",
        "protectedarticle": "«[[$1]]» битен һаҡлаған",
        "protect-locked-blocked": "Һеҙҙең исәп яҙмағыҙ бикләнгән ваҡытта һеҙ биттең һаҡлау дәрәжәһен үҙгәртә алмайһығыҙ.\n'''$1''' битенең хәҙерге һаҡлау көйләүҙәре:",
        "protect-locked-dblock": "Һаҡлау дәрәжәһе үҙгәртелә алмай, сөнки төп мәғлүмәттәр базаһы ваҡытлыса бикле.\n'''$1''' битенең хәҙерге һаҡлау көйләүҙәре:",
        "protect-locked-access": "Биттең һаҡлау дәрәжеһен үҙгәртер өсөн иҫәп яҙыуығыҙҙың хоҡуҡтары етәрле түгел. '''$1''' битенең хәҙерге һаҡлау көйләүҙәре:",
-       "protect-cascadeon": "Был бит һаҡланған, сөнки ул эҙмә-эҙлекле һаҡлау ҡуйылған {{PLURAL:$1|1=биткә|биттәргә}} керә. Һеҙ был биттең һаҡлау дәрәжәһен үҙгәртә алаһығыҙ, ләкин был эҙмә-эҙлекле һаҡлауға йоғонто яһамаясаҡ.",
+       "protect-cascadeon": "Был бит һаҡланған, сөнки ул эҙмә-эҙлекле һаҡлау ҡуйылған {{PLURAL:$1|1=биткә|биттәргә}} керә. Һеҙ был биттең һаҡлауға дәрәжәһен үҙгәртә алаһығыҙ, ләкин был эҙмә-эҙлекле һаҡлауға йоғонто яһамаясаҡ.",
        "protect-default": "Бар ҡулланыусыларға рөхсәт бирергә",
        "protect-fallback": "«$1» хоҡуҡлы ҡатнашыусыларға ғына рөхсәте ителгән",
        "protect-level-autoconfirmed": "Үҙенән-үҙе раҫланған ҡатнашыусыларға ғына рөхсәт ителгән",
        "protect-othertime": "Башҡа ваҡыт:",
        "protect-othertime-op": "башҡа ваҡыт",
        "protect-existing-expiry": "Хәҙерге тамамланыу ваҡыты: $2 $3",
+       "protect-existing-expiry-infinity": "Тамамланыу ваҡыты: сикләнмәгән",
        "protect-otherreason": "Башҡа/өҫтәмә сәбәп:",
        "protect-otherreason-op": "Башҡа сәбәп",
        "protect-dropdown": "*Ғәҙәттәге һаҡлау сәбәптәре:\n** Үтә ныҡлы вандаллыҡ\n** Үтә ныҡлы спам\n** Файҙаһыҙ үҙгәртеүҙәр ярышы\n** Киң танылған бит",
        "namespace": "Исемдәр арауығы:",
        "invert": "Һайланғандарҙы әйләндерергә",
        "tooltip-invert": "Һайланған исемдәр арауығындағы (һәм бәйле исемдәр арауығындағы, әгәр күрһәтелһә) биттәрҙәге үҙгәртеүҙәрҙе йәшерер өсөн был билдәне ҡуйығыҙ.",
+       "tooltip-whatlinkshere-invert": "Был тамғаны һайланған исемдәр арауығындағы һылтанмаларҙы йәшереү өсөн ҡуйығыҙ.",
        "namespace_association": "Бәйле арауыҡ",
        "tooltip-namespace_association": "Һайланған исемдәр арауығы менән бәйле әңгәмә(йәки тема) исем арауыҡтарын ҡушыр өсөн был билдәне ҡуйығыҙ.",
        "blanknamespace": "(Төп)",
        "mycontris": "Башҡарған эштәр",
        "anoncontribs": "Иғәнәләр",
        "contribsub2": "{{GENDER:$3|$1}} башҡарған эше ($2)",
+       "contributions-userdoesnotexist": "«$1» исемле иҫәп яҙыуы юҡ.",
        "nocontribs": "Күрһәтелгән шарттарға яуап биргән үҙгәртеүҙәр табылманы.",
        "uctop": "(ағымдағы)",
        "month": "Айҙан башлап (һәм элегерәк):",
        "sp-contributions-newbies-sub": "Яңы иҫәп яҙмалары өсөн",
        "sp-contributions-newbies-title": "Яңы теркәлгән ҡатнашыусылар башҡарған эш",
        "sp-contributions-blocklog": "блоклау яҙмалары",
+       "sp-contributions-suppresslog": "Ҡулланыусыларҙың юйылған өлөшө",
        "sp-contributions-deleted": "юйылған үҙгәртеүҙәр",
        "sp-contributions-uploads": "тейәүҙәр",
        "sp-contributions-logs": "журналдар",
        "sp-contributions-search": "Башҡарған эште эҙләү",
        "sp-contributions-username": "Ҡулланыусының IP-адресы йәки исеме:",
        "sp-contributions-toponly": "Һуңғы өлгөләрҙе генә күрһәтергә",
+       "sp-contributions-newonly": "Яңы бит яһаған төҙәтеүҙәрҙе генә күрһәтергә",
        "sp-contributions-submit": "Эҙлә",
        "whatlinkshere": "Бында һылтанмалар",
        "whatlinkshere-title": "«$1» битенә һылтанған биттәр",
        "whatlinkshere-hidelinks": "Һылтанмаларҙы $1",
        "whatlinkshere-hideimages": "файл һылтанмаларын $1",
        "whatlinkshere-filters": "Һайлау",
+       "whatlinkshere-submit": "Күсергә",
        "autoblockid": "Автобикләү #$1",
        "block": "Ҡатнашыусыны бикләү",
        "unblock": "Бикләнгән ҡатнашыусыны азат итеү",
-       "blockip": "Ҡатнашыусыны бикләү",
+       "blockip": "{{GENDER:$1|Ҡатнашыусыны}} бикләү",
        "blockip-legend": "Ҡатнашыусыны бикләү",
-       "blockiptext": "Билдәләнгән IP адрестан яҙыу мөмкинлеген бикләү өсөн, түбәндәге форманы ҡулланығыҙ.\nБыл бары тик вандаллыҡҡа юл ҡуймау өсөн генә һәм [[{{MediaWiki:Policy-url}}|ҡағиҙәләр]] буйынса ғына эшләнергә тейеш.\nТүбәндә бикләү сәбәбен күрһәтегеҙ (мәҫәлән, вандаллыҡ эҙҙәре булған бер нисә биттең цитатаһын килтерегеҙ).",
+       "blockiptext": "Билдәләнгән IP адрестан яҙыу мөмкинлеген бикләү өсөн, түбәндәге форманы ҡулланығыҙ.\nБыл бары тик вандаллыҡҡа юл ҡуймау өсөн генә һәм [[{{MediaWiki:Policy-url}}|ҡағиҙәләр]] буйынса ғына эшләнергә тейеш.\nТүбәндә бикләү сәбәбен күрһәтегеҙ (мәҫәлән, вандаллыҡ эҙҙәре булған бер нисә биттең цитатаһын килтерегеҙ).$1 $2",
        "ipaddressorusername": "Ҡатнашыусының IP-адресы йәки исеме:",
        "ipbexpiry": "Тамамлана:",
        "ipbreason": "Сәбәп:",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] бикләнде.<br />\nБиктәрҙе күреү өсөн [[Special:BlockList|бикләнгән IP адрестарҙы]] ҡарағыҙ.",
        "ipb-blockingself": "Һеҙ үҙегеҙҙе бикләргә теләйһегеҙ! Быны эшләүҙе раҫлайһығыҙмы?",
        "ipb-confirmhideuser": "\"Ҡулланыусыны йәшер\" ғәмәлдә саҡта ҡулланыусыны блокларға теләйһегеҙ. Уның исеме исемлектәрҙә һәм журналдарҙа күренмәйәсәк. Быны эшләргә теләүегеҙҙе раҫлайһығыҙмы?",
+       "ipb-confirmaction": "Быны башҡарырға теләһегеҙ түбәндә тамға ҡуйығыҙ «{{int:ipb-confirm}}».",
        "ipb-edit-dropdown": "Бикләү сәбәптәрен мөхәррирләргә",
        "ipb-unblock-addr": "$1 биген алырға",
        "ipb-unblock": "Ҡатнашыусының йәки IP адрестың биген алырға",
        "unblocked": "[[User:$1|$1]] бикләнгән",
        "unblocked-range": "$1 биге сиселде",
        "unblocked-id": "$1 биге алынған",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] блоктан азат ителде",
        "blocklist": "Тыйылған ҡатнашыусылар",
        "ipblocklist": "Тыйылған ҡатнашыусылар",
        "ipblocklist-legend": "Бикләнгән ҡатнашыусыны эҙләү",
        "block-log-flags-hiddenname": "ҡатнашыусы исеме йәшерелгән",
        "range_block_disabled": "Хакимдәргә бикләү арауыҡтарын булдырыу тыйылған.",
        "ipb_expiry_invalid": "Тамамланыу ваҡыты дөрөҫ түгел.",
+       "ipb_expiry_old": "Һаҡлауҙың тамамланыу ваҡыты үткән көнгә ҡуйылған.",
        "ipb_expiry_temp": "Бикләү ваҡытында ҡатнашыусы исеме йәшерелһә, бикләү ваҡыты сикһеҙ булырға тейеш.",
-       "ipb_hide_invalid": "Иҫәп яҙмаһын йәшереү мөмкин түгел, ул бигерәк күп үҙгәртеүҙәр яһаған, булырға тейеш.",
+       "ipb_hide_invalid": "Иҫәп яҙмаһын йәшереү мөмкин түгел,  {{PLURAL:$1|бер|$1 бер нисә}} төҙәтеү эшләнгән.",
        "ipb_already_blocked": "\"$1\" бикләнгән инде.",
        "ipb-needreblock": "$1 бикләнгән инде.\nБикләү көйләүҙәрен үҙгәртергә теләйһегеҙме?",
        "ipb-otherblocks-header": "Башҡа {{PLURAL:$1|1=бикләү|бикләүҙәр}}",
        "move-page": "$1 — исемен үҙгәртеү",
        "move-page-legend": "Биттең исемен үҙгәртеү",
        "movepagetext": "Аҫтағы ҡалыпты ҡулланып, биттең исемен үҙгәртә һәм уның үҙгәртеүҙәр журналын яңы урынға күсерә алаһығыҙ.\nБиттең элекке исеме яңы биткә йүнәлтеү булып ҡаласаҡ.\nҺеҙ элекке исемгә булған йүнәлтеүҙәрҙе автоматик рәүештә яңы исемгә күсерә алаһығыҙ.\nӘгәр быны эшләмәһәгеҙ, [[Special:DoubleRedirects|икеле]] һәм [[Special:BrokenRedirects|өҙөлгән йүнәлтеүҙәр]] барлығын тикшерегеҙ.\nҺылтанмаларҙың кәрәкле урынға күрһәтеүен дауам итеүе өсөн һеҙ яуаплы.\n\nИғтибар итегеҙ: әгәр яңы һайланған исемдәге тағы бер бит бар икән, биттең исеме '''үҙгәртелмәйәсәк'''; ул бит йүнәлтеүсе  йәки буш булһа һәм төҙәтеүҙәр тарихына эйә булмаһа ғына,  был мөмкин.\nТимәк, биттең исемен яңылыш үҙгәртһәгеҙ, битте элекке исеменә кире ҡайтара алаһығыҙ, ләкин булған битте юя алмайһығыҙ.\n\n'''Иҫкәртеү!'''\n\"Популяр\" биттәрҙең исемен үҙгәртеү күләмле һәм көтөлмәгән һөҙөмтәләргә килтерергә мөмкин.\nДауам итерҙән алда, ихтимал булған һөҙөмтәләрҙе аңлауығыҙға ышанығыҙ.",
-       "movepagetext-noredirectfixer": "Аҫтағы форманы ҡулланыу биттең исемен үҙгәртә һәм уның үҙгәртеүҙәр яҙмаһын яңы урынға күсерә.\nБиттең элекке исеме яңы биткә йүнәлтеү булып ҡаласаҡ.\nҺеҙ элекке исемгә булған йүнәлтеүҙәрҙе автоматик рәүештә яңы исемгә күсерә алаһығыз.\nӘгәр быны эшләмәһәгеҙ, [[Special:DoubleRedirects|икеле]] һәм [[Special:BrokenRedirects|өҙөлгән йүнәлтеүҙәрҙе]] тикшерегеҙ.\nҺылтанмаларҙың кәрәкле урынға күрһәтеүҙәренең дауам итеүе өсөн һеҙ яуаплы.\n\nИғтибар итегеҙ, әгәр яңы исемле бит бар икән, биттең исеме '''үҙгәртелмәйәсәк'''; элекке бит йүнәлтеү, буш һәм үҙгәртеү тарихына эйә булмаған осраҡтарҙан башҡа.\nБыл шуны аңлата: бит исемен яңылыш үҙгәртһәгеҙ, битте кире ҡайтара алаһығыҙ, ләкин булған битте юя алмайһығыҙ.\n\n'''Иғтибар!'''\nПопуляр биттәрҙең исемен үҙгәртеү көтмәгән һөҙөмтәләргә килтерүе мөмкин.\nДауам итерҙән алда, бөтә буласаҡ һөҙөмтәләрҙе аңлауығыҙҙы уйлағыҙ.",
+       "movepagetext-noredirectfixer": "Аҫтағы форманы ҡулланыу биттең исемен үҙгәртә һәм уның үҙгәртеүҙәр яҙмаһын яңы урынға күсерә.\nБиттең элекке исеме яңы биткә йүнәлтеү булып ҡаласаҡ.\nҺеҙ элекке исемгә булған йүнәлтеүҙәрҙе автоматик рәүештә яңы исемгә күсерә алаһығыз.\nӘгәр быны эшләмәһәгеҙ, [[Special:DoubleRedirects|икеле]] һәм [[Special:BrokenRedirects|өҙөлгән йүнәлтеүҙәрҙе]] тикшерегеҙ.\nҺылтанмаларҙың кәрәкле урынға күрһәтеүҙәренең дауам итеүе өсөн һеҙ яуаплы.\n\nИғтибар итегеҙ, әгәр яңы исемле бит бар икән, биттең исеме '''үҙгәртелмәйәсәк'''; элекке бит йүнәлтеү, буш һәм үҙгәртеү тарихына эйә булмаған осраҡтарҙан башҡа.\nБыл шуны аңлата: бит исемен яңылыш үҙгәртһәгеҙ, битте кире ҡайтара алаһығыҙ, ләкин булған битте юя алмайһығыҙ.\n\n<strong>Иғтибар:</strong>\nПопуляр биттәрҙең исемен үҙгәртеү көтмәгән һөҙөмтәләргә килтерүе мөмкин.\nДауам итерҙән алда, бөтә буласаҡ һөҙөмтәләрҙе аңлауығыҙҙы уйлағыҙ.",
        "movepagetalktext": "Фекер алышыу битенең исеме лә үҙгәртеләсәк, '''киләһе осраҡтарҙан тыш''':\n*Бындай исемле фекер алышыу бите бар, йәки\n*Аҫтағы юлды билдәләмәгәнһегеҙ.\n\nБындай осраҡтарҙа, кәрәкле булһа, биттәрҙе үҙегеҙҙең күсереүегеҙ йәки исемен үҙгәртеүегеҙ кәрәк буласаҡ.",
-       "moveuserpage-warning": "'''Иғтибар:''' Һеҙ ҡатнашыусы битенең исемен үҙгәртергә йыйынаһығыҙ. Зинһар, биттең генә исеме үҙгәрәсәк, ҡатнашыусы исеме ''үҙгәрмәйәсәк'', икәнен күҙ үңында тотоғоҙ.",
+       "moveuserpage-warning": "'''Иғтибар:''' Һеҙ ҡатнашыусы битенең исемен үҙгәртергә йыйынаһығыҙ. Биттең генә исеме үҙгәрәсәк, ҡатнашыусы исеме ''үҙгәрмәйәсәген'' күҙ үңында тотоғоҙ.",
+       "movecategorypage-warning": "<strong>Иҫкәрмә:</strong> Һеҙ категория битенең атамаһын үҙгәртергә теләйһегеҙ.Зинһар, ошо бит кенә үҙгәртелеүенә иғтибар итегеҙ, ә иҫке категориялағы башҡа биттәр<em>не</em> яңынан категорияланасаҡ.",
        "movenologintext": "Биттең исемен үҙгәртеү өсөн, һеҙ [[Special:UserLogin|танылырға]] тейешһегеҙ.",
        "movenotallowed": "Һеҙҙең бит исемен үҙгәртергә хоҡуғығыҙ юҡ",
        "movenotallowedfile": "Һеҙҙең файл исемен үҙгәртергә хоҡуғығыҙ юҡ",
        "cant-move-user-page": "Һеҙҙең ҡатнашыусы битенең исемен үҙгәртергә хоҡуғығыҙ юҡ",
        "cant-move-to-user-page": "Һеҙҙең битте ҡатнашыусы бите итеп үҙгәртергә хоҡуғығыҙ юҡ (ҡатнашыусы биттәренән тыш).",
-       "newtitle": "Яңы исем",
+       "cant-move-category-page": "Һеҙҙең категория исемен үҙгәртергә хоҡуғығыҙ юҡ",
+       "cant-move-to-category-page": "Һеҙҙең битте категория бите тип төҙәтергә хоҡуғығыҙ юҡ.",
+       "newtitle": "Яңы атама",
        "move-watch": "Был битте күҙәтеү исемлегенә өҫтәргә",
        "movepagebtn": "Биттең исемен үҙгәртергә",
        "pagemovedsub": "Бит исеме үҙгәртелде",
        "movepage-max-pages": "$1 {{PLURAL:$1|биттең}} исеме үҙгәртелде, бынан күберәк биттең исемен автоматик рәүештә үҙгәртеү мөмкин түгел.",
        "movelogpage": "Исем үҙгәртеү яҙмалары",
        "movelogpagetext": "Түбәндә — исемдәре үҙгәртелгән биттәр.",
-       "movesubpage": "{{PLURAL:$1|кергән бит}}",
-       "movesubpagetext": "Был биткә түбәндә килтерелгән $1 {{PLURAL:$1|бит}} кергән.",
+       "movesubpage": "{{PLURAL:$1|ярҙамсы бит}}",
+       "movesubpagetext": "Был биттә $1 {{PLURAL:$1|ярҙамсы бит}}.",
        "movenosubpage": "Был биткә бер бит тә кермәгән.",
        "movereason": "Сәбәп:",
        "revertmove": "кирегә",
-       "delete_and_move_text": "==Юйыу талап ителә==\n[[:$1|«$1»]] исемле бит бар инде. Исем үҙгәртеүҙе дауам итеү өсөн, уны юйырға теләйһегеҙме?",
+       "delete_and_move_text": "[[:$1|«$1»]] исемле бит бар инде. Исем үҙгәртеүҙе дауам итеү өсөн, уны юйырға теләйһегеҙме?",
        "delete_and_move_confirm": "Эйе, битте юйырға",
        "delete_and_move_reason": "Исем үҙгәртеүҙе дауам итеү өсөн юйылды «[[$1]]»",
        "selfmove": "Хәҙерге һәм яңы исемдәр тап килә. Исем үҙгәртеү мөмкин түгел.",
        "export-download": "Файлды һаҡларға",
        "export-templates": "Ҡалыптарҙы индерергә",
        "export-pagelinks": "Бәйле биттәрҙе ошо тәрәнлек менән индерергә:",
+       "export-manual": "Битте ҡулдан өҫтәргә",
        "allmessages": "Система хәбәрҙәре",
        "allmessagesname": "Хәбәр",
        "allmessagesdefault": "Ғәҙәттәге яҙма",
        "thumbnail-temp-create": "Эскиздың ваҡытлыса файлын яһап булмай",
        "thumbnail-dest-create": "Маҡсат урында эскизды һаҡлап булмай",
        "thumbnail_invalid_params": "Шартлы рәсем шарттары дөрөҫ түгел",
+       "thumbnail_toobigimagearea": "Күләме $1 ҙур булған файл",
        "thumbnail_dest_directory": "Кәрәкле директорияны булдырып булмай",
        "thumbnail_image-type": "Был рәсем төрө ҡулланылмай",
        "thumbnail_gd-library": "GD йыйынтығының төҙөлөшө тулы түгел, $1 функцияһы юҡ",
        "thumbnail_image-missing": "$1 файлы юҡ, булырға тейеш",
+       "thumbnail_image-failure-limit": "Был эскизды булдырыу өсөн иң күп маташыу $1 булды. Һуңынан ғабатлап ҡарағыҙ.",
        "import": "Биттәрҙе тейәү",
-       "importinterwiki": "Ð\92ики Ð¿Ñ\80оекÑ\82Ñ\82аÑ\80-аÑ\80а Ð¸Ð½Ð´ереү",
+       "importinterwiki": "баÑ\88ҡа Ð²Ð¸ÐºÐ¸-пÑ\80оекÑ\82Ñ\82ан Ð±Ð¸Ñ\82Ñ\82Ó\99Ñ\80Ò\99е ÐºÒ¯Ñ\81ереү",
        "import-interwiki-text": "Вики проектты һәм тейәлә торған биттең исемен күрһәтегеҙ.\nҮҙгәртеү ваҡыттары һәм автор исемдәре һаҡланасаҡ.\nБөтә вики проекттары-ара тейәүҙәр [[Special:Log/import|тейәү яҙмалары журналында]] теркәлә.",
+       "import-interwiki-sourcewiki": "Сығанаҡ вики-проект:",
        "import-interwiki-sourcepage": "Сығанаҡ бит:",
        "import-interwiki-history": "Был биттең бөтә үҙгәртеү тарихын яҙҙырырға",
        "import-interwiki-templates": "Бөтә ҡалыптарҙы индерергә",
        "import-interwiki-submit": "Тейәргә",
+       "import-mapping-default": "Килешеү буйынса урынлашҡан ергә импортлау",
+       "import-mapping-namespace": "Исемдәр арауығына импортлау",
+       "import-mapping-subpage": "Ярҙамсы бит итеп киләһе биткә импортлау",
        "import-upload-filename": "Файл исеме:",
        "import-comment": "Иҫкәрмә:",
        "importtext": "Зинһар, файлды сығанаҡ викинан [[Special:Export|махсус ҡорал]] ярҙамында сығарығыҙ. Артабан уны компьютерығыҙға һаҡлағыҙ һәм бында тейәгеҙ.",
        "importstart": "Биттәрҙе тейәү...",
        "import-revision-count": "$1 {{PLURAL:$1|1=өлгө|өлгө}}",
        "importnopages": "Тейәү өсөн биттәр юҡ.",
-       "imported-log-entries": "Журналдан $1 {{PLURAL:$1|яҙма}} тейәлде.",
+       "imported-log-entries": "Журналдың {{PLURAL:$1| $1 яҙмаһы импортланды}}",
        "importfailed": "Тейәү хатаһы: <nowiki>$1</nowiki>",
        "importunknownsource": "Сығанаҡ биттең төрө билдәһеҙ",
        "importcantopen": "Тейәлә торған битте асып булмай",
        "import-nonewrevisions": "Бөтә өлгөләр бығаса тейәлгән булған.",
        "xml-error-string": "$2 юлда, $3 урында ($4 байт) $1: $5",
        "import-upload": "XML-мәғлүмәт тейәргә",
-       "import-token-mismatch": "Сессия мәғлүмәттәре юғалған.\nЗинһар, тағы ҡабатлап ҡарағыҙ.",
+       "import-token-mismatch": "Сессия мәғлүмәттәре юғалған.\nЗинһар, тағы ҡабатлап ҡарағыҙ. [[Special:UserLogout|системанан сығырға]]",
        "import-invalid-interwiki": "Күрһәтелгән вики проекттан тейәү мөмкин түгел.",
        "import-error-edit": "«$1» битен импортлап булманы, сөнки һеҙгә ул битте мөхәррирләү тыйылған.",
        "import-error-create": "«$1» битен импортлап булманы, сөнки һеҙгә ул битте яһау тыйылған.",
        "import-error-special": " «$1» бите импортҡа сығарылманы, сөнки ул биттәр яһау мөмкин булмаған исемдәр арауығына ҡарай.",
        "import-error-invalid": "\"$1\" бите яраҡһыҙ исеме өсөн импортланманы.",
        "import-error-unserialize": "«$1» битенең $2 өлгөһөн структуралаштырып (десериаялап) булмай. $4 форматында серияланған $3 эстәлегенең моделеның был өлгөлә ҡулланылыуы тураһында хәбәр алынды.",
+       "import-error-bad-location": "$3 моделе эстәлегендәге $2 төҙәтеүен $1 был викила һаҡлап булмай.",
        "import-options-wrong": "Хаталы {{PLURAL:$2|1=опция|опциялар}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Төп биттең күрһәтелгән исеме яңылыш.",
        "import-rootpage-nosubpage": "Төп биттең \"$1\" исемдәр арауығы эске биттәргә рөхсәт бирмәй.",
        "importlogpage": "Тейәү яҙмалары журналы",
        "importlogpagetext": "Хакимдәр тарафынан башҡа вики проекттарҙан биттәрҙе һәм уларҙың үҙгәртеүҙәр тарихын тейәү.",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|1=өлгө|өлгө}}",
-       "import-logentry-interwiki-detail": "$2 өлгөнән $1 {{PLURAL:$1|1=өлгө|өлгө}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|версия күсерелгән|версиялар күсерелгән}}",
+       "import-logentry-interwiki-detail": "$2-нан $1 {{PLURAL:$1|өлгө импортланған}}",
        "javascripttest": "\nJavaScript тикшереү",
-       "javascripttest-pagetext-noframework": "Был бит JavaScript тикшеренеүҙәре үткәреү өсөн  резервланған.",
-       "javascripttest-pagetext-unknownframework": "Билдәһеҙ тикшеренеүҙәр мөхитнамәһе \"$1\".",
-       "javascripttest-pagetext-frameworks": "Зинһар өсөн киләһе тикшеренеүҙәр мөхитнамәһенең береһен һайлап алығыҙ: $1",
-       "javascripttest-pagetext-skins": "Һынауҙы башлау өсөн тышса һыйлағыҙ.",
+       "javascripttest-pagetext-unknownaction": "$1 ғәмәле билдәһеҙ",
        "javascripttest-qunit-intro": "mediawiki.org адресы буйынса ҡарағыҙ [$1 тест үткәреү документацияһы].",
-       "tooltip-pt-userpage": "Ҡулланыусы битегеҙ",
+       "tooltip-pt-userpage": "{{GENDER:|Һеҙҙең}} ҡатнашыусы бите",
        "tooltip-pt-anonuserpage": "IP адресығыҙ өсөн ҡатнашыусы бите",
-       "tooltip-pt-mytalk": "Фекерләшеү битегеҙ",
+       "tooltip-pt-mytalk": "{{GENDER:|Һеҙҙең}} фекерләшеү битегеҙ",
        "tooltip-pt-anontalk": "IP адресығыҙ өсөн фекер алышыу бите",
-       "tooltip-pt-preferences": "Көйләүҙәрегеҙ",
+       "tooltip-pt-preferences": "{{GENDER:|Һеҙҙең}} көйләүҙәрегеҙ",
        "tooltip-pt-watchlist": "Һеҙ күҙәткән биттәр исемлеге",
-       "tooltip-pt-mycontris": "Кереткән өлөшөгөҙ",
+       "tooltip-pt-mycontris": "{{GENDER:|Һеҙҙең}} төҙәтеүҙәр исемлеге",
+       "tooltip-pt-anoncontribs": "Был IP-адрестан яһалған төҙәтеүҙәр",
        "tooltip-pt-login": "Бында теркәлеү үтергә була, әммә был эш мәжбүри түгел.",
        "tooltip-pt-logout": "Сығырға",
        "tooltip-pt-createaccount": "Мотлаҡ булмаһа ла, Һеҙгә иҫәп яҙмаһы төҙөргө һәм системала танылырға тәҡдим итәбеҙ.",
        "tooltip-feed-rss": "Был бит өсөн RSS-таҫма",
        "tooltip-feed-atom": "Был бит өсөн Atom-таҫма",
        "tooltip-t-contributions": "{{GENDER:$1|Был ҡулланыусының}} кереткән өлөшөн ҡарарға",
-       "tooltip-t-emailuser": "Был ҡулланыусыға хат ебәрергә",
+       "tooltip-t-emailuser": "{{GENDER:$1|был ҡулланыусыға}} хат ебәреү",
+       "tooltip-t-info": "Был бит тураһында ентекләберәк",
        "tooltip-t-upload": "Рәсем йәки тауыш эстәлекле файлдарҙы тейәргә",
        "tooltip-t-specialpages": "Барлыҡ махсус биттәр исемлеге",
        "tooltip-t-print": "Был биттең ҡағыҙға баҫыу өлгөһө",
        "tooltip-undo": "\"Кире ал\" төҙәтеүҙе кире ала һәм төҙәтеү формаһын \"алдан байҡау\"ҙа күрһәтә. Һәм кире алыуҙың сәбәбен белдерергә була.",
        "tooltip-preferences-save": "Көйләүҙәрҙе һаҡларға",
        "tooltip-summary": "Ҡыҫҡаса тасуирлама керетегеҙ",
-       "anonymous": "{{SITENAME}} проектының танылмаған {{PLURAL:$1|1=ҡатнашыусыһы|ҡатнашыусылары}}",
+       "anonymous": "{{PLURAL:$1|1=Аноним ҡатнашыусы|Аноним ҡатнашыусылар}} {{grammar:genitive|{{SITENAME}}}}",
        "siteuser": "{{SITENAME}} проектының ҡатнашыусыһы $1",
        "anonuser": "{{SITENAME}} проектының танылмаған ҡатнашыусыһы $1",
        "lastmodifiedatby": "Был бит һуңғы тапҡыр $1 $2 $3 тарафынан үҙгәртелгән.",
        "othercontribs": "Мөхәррирләүҙә ҡатнаштылар: $1.",
        "others": "башҡалар",
-       "siteusers": "{{SITENAME}} {{PLURAL:$2|1=ҡатнашыусы|ҡатнашыусылары}} $1",
-       "anonusers": "{{SITENAME}} проектының танылмаған {{PLURAL:$2|1=ҡатнашыусыһы|ҡатнашыусылары}} $1",
+       "siteusers": "{{PLURAL:$2|1={{GENDER:$1|ҡатнашыусы}}|ҡатнашыусылар}} {{grammar:genitive|{{SITENAME}}}} $1",
+       "anonusers": "{{PLURAL:$2|1=аноним ҡатнашыусы|аноним ҡатнашыусылар}} {{grammar:genitive|{{SITENAME}}}} $1",
        "creditspage": "Рәхмәт белдереү",
        "nocredits": "Был мәҡәләне мөхәррирләүҙә ҡатнашыусылар исемлеге юҡ.",
        "spamprotectiontitle": "Спамдан һаҡлау",
        "pageinfo-length": "Бит оҙонлоғо (байттарҙа)",
        "pageinfo-article-id": "Бит идентификаторы",
        "pageinfo-language": "Бит эстәлегенең теле",
+       "pageinfo-content-model": "Бит эстәлегенең моделе",
        "pageinfo-robot-policy": "Эҙләү роботтары тарафынан индексацияланыу",
        "pageinfo-robot-index": "Рөхсәт ителгән",
        "pageinfo-robot-noindex": "Рөхсәт ителмәй",
        "pageinfo-watchers": "Битте күҙәтеүселәр һаны",
-       "pageinfo-few-watchers": "Күп тигәндә $1 {{PLURAL:$1|күҙәтеүсе}}",
+       "pageinfo-visiting-watchers": "Битте күҙәтеүсе һәм һуңғы үҙгәртеүҙәрҙе күреүсе ҡатнашыусылар һаны",
+       "pageinfo-few-watchers": "$1 әҙерәк {{PLURAL:$1|күҙәтеүсе}}",
+       "pageinfo-few-visiting-watchers": "Битте күҙәтеүсе һәм һуңғы үҙгәртеүҙәрҙе күреүсе ҡатнашыусылар булыуы ла, булмауы ла ихтимал",
        "pageinfo-redirects-name": "Был биткә йүнәлтеүҙәр һаны",
        "pageinfo-subpages-name": "Был биттең эске биттәре",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|йүнәлтеү}}; $3 {{PLURAL:$3|ябай}})",
        "pageinfo-authors": "Төрлө авторҙар һаны",
        "pageinfo-recent-edits": "Һуңғы ваҡыттағы төҙәтеүҙәр ($1 эсендә)",
        "pageinfo-recent-authors": "Төрлө авторҙарҙың һуңғы һаны",
-       "pageinfo-magic-words": "Тылсымлы {{PLURAL:$1|1=һүҙ|һүҙҙәр}} ($1)",
-       "pageinfo-hidden-categories": "Йәшерен {{PLURAL:$1|1=категория|категориялар}} ($1)",
-       "pageinfo-templates": "Ҡулланылған {{PLURAL:$1|1=ҡалып|ҡалыптар}} ($1)",
+       "pageinfo-magic-words": "{{PLURAL:$1|1=Тылсымлы һүҙ|Тылсымлы һүҙҙәр}} ($1)",
+       "pageinfo-hidden-categories": "{{PLURAL:$1|1=Йәшерен категория|Йәшерен категориялар}} ($1)",
+       "pageinfo-templates": "{{PLURAL:$1|1=Ҡалып|Ҡалыптар}} ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|Индерелгән биттәр}} ($1)",
        "pageinfo-toolboxlink": "Бит мәғлүмәттәре",
        "pageinfo-redirectsto": "Йүнәлтеү",
        "pageinfo-protect-cascading-yes": "Эйе",
        "pageinfo-protect-cascading-from": "Бынан башлап һикәлтәле һаҡлау",
        "pageinfo-category-info": "Категория тураһында мәғлүмәт",
+       "pageinfo-category-total": "Ағзаларҙың дөйөм һаны",
        "pageinfo-category-pages": "Биттәр һаны",
        "pageinfo-category-subcats": "Категория бүлемдәре һаны",
        "pageinfo-category-files": "Файлдар һаны",
        "markaspatrolleddiff": "Тикшерелгән, тип билдәләргә",
        "markaspatrolledtext": "Бил битте тикшерелгән, тип билдәләргә",
+       "markaspatrolledtext-file": "Был өлөгөнө патрулләнгән тип ҡуйырға",
        "markedaspatrolled": "Тикшерелгән тип билдәнгән",
        "markedaspatrolledtext": "[[:$1]] битенең һайланған өлгөһө тикшерелгән тип билдәләнгән.",
        "rcpatroldisabled": "Һуңғы үҙгәртеүҙәрҙе тикшереү рөхсәт ителмәй",
        "patrol-log-page": "Тикшереү яҙмалары журналы",
        "patrol-log-header": "Был — тикшерелгән өлгөләр яҙмалары журналы.",
        "log-show-hide-patrol": "тикшереү яҙмалары журналын $1",
+       "log-show-hide-tag": "$1 билдәләр журналы",
        "deletedrevision": "Иҫке $1 өлгөһө юйылды",
        "filedeleteerror-short": "Файлды юйыу хатаһы: $1",
        "filedeleteerror-long": "Файлды юйыу ваҡытында хаталар килеп сыҡты:\n\n$1",
        "mediawarning": "'''Иғтибар''': был төр файлда зыян килтереүсе программа коды булыуы мөмкин.\nУны башҡарған саҡта һеҙҙең системағыҙға хәүеф янауы мөмкин.",
        "imagemaxsize": "Рәсем дәүмәле өсөн сик: <br />''(файл тасуирламаһы биттәре өсөн)''",
        "thumbsize": "Шартлы рәсем дәүмәле:",
-       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|бит}}",
+       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3 бит}}",
        "file-info": "файлдың дәүмәле: $1, MIME төрө: $2",
        "file-info-size": "$1 × $2 нөктә, файлдың дәүмәле: $3, MIME төрө: $4",
-       "file-info-size-pages": "$1 × $2 пиксель, файл күләме: $3, MIME төр: $4, $5 {{PLURAL:$5|бит}}",
+       "file-info-size-pages": "$1 × $2 пиксель, файл күләме: $3, MIME-тибы: $4, $5 {{PLURAL:$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-preview": "Байҡау ваҡытындағы күләм: $1.",
+       "show-big-image-preview-differ": " $3-превью размеры  $2-файлы өсөн: $1.",
        "show-big-image-other": "{{PLURAL:$2|1=Башҡа сиселеш|Башҡа сиселештәр}}: $1.",
        "show-big-image-size": "$1 × $2 пиксель",
        "file-info-gif-looped": "әйләнешле",
-       "file-info-gif-frames": "$1 {{PLURAL:$1|фрейм}}",
+       "file-info-gif-frames": "$1 {{PLURAL:$1|фрейм|фреймдар}}",
        "file-info-png-looped": "әйләнешле",
        "file-info-png-repeat": "$1 {{PLURAL:$1|тапҡыр}} уйнала",
-       "file-info-png-frames": "$1 {{PLURAL:$1|фрейм}}",
+       "file-info-png-frames": "$1 {{PLURAL:$1|кадр}}",
        "file-no-thumb-animation": "\n'''Иғтибар: Техник сикләүҙәр арҡаһында, был файлдың бәләкәй рәсемдәре анимацияланмаясаҡ.'''",
        "file-no-thumb-animation-gif": "'''Иғтибар: Техник сикләүҙәр арҡаһында, бының һымаҡ юғары асыҡлыҡтағы GIF рәсемдәрҙең бәләкәй рәсемдәре анимацияланмаясаҡ.'''",
        "newimages": "Яңы файлдар йыйылмаһы",
        "newimages-summary": "Был махсус бит һуңғы тейәлгән файлдарҙы күрһәтә.",
        "newimages-legend": "Һайлау",
        "newimages-label": "Файл исеме (йәки өлөшө):",
+       "newimages-showbots": "Роботтан тейегәнде күрһәтергә",
+       "newimages-hidepatrolled": "Патрулләнгән күсереүҙәрҙе йәшерергә",
        "noimages": "Рәсемдәр юҡ.",
        "ilsubmit": "Эҙләү",
        "bydate": "булдырыу көнө буйынса",
        "sp-newimages-showfrom": "$1 $2 ваҡытынан башлап яңы файлдарҙы күрһәтергә",
-       "seconds": "{{PLURAL:$1|1=$1 секунд|$1 секунд}}",
-       "minutes": "{{PLURAL:$1|1=$1 минут|$1 минут}}",
-       "hours": "{{PLURAL:$1|1=$1 сәғәт|$1 сәғәт}}",
-       "days": "{{PLURAL:$1|1=$1 көн|$1 көн}}",
+       "seconds": "{{PLURAL:$1|$1 секунд|$1 секундтар|$1 секунд}}",
+       "minutes": "{{PLURAL:$1|$1 минут}}",
+       "hours": "{{PLURAL:$1|$1 сәғәт}}",
+       "days": "{{PLURAL:$1|1=$1 көн}}",
        "weeks": "{{PLURAL:$1|$1 аҙна}}",
        "months": "{{PLURAL:$1|$1 ай}}",
        "years": "{{PLURAL:$1|$1 йыл}}",
        "ago": "$1 элек",
        "just-now": "яңы ғына",
-       "hours-ago": "$1 {{PLURAL:$1|сәғәт}} элек",
-       "minutes-ago": "$1 {{PLURAL:$1|минут}} элек",
-       "seconds-ago": "$1 {{PLURAL:$1|секунд}} элек",
+       "hours-ago": "$1 {{PLURAL:$1сәғәт}} элек",
+       "minutes-ago": "$1 {{PLURAL:$1|минут}} алда",
+       "seconds-ago": "$1 {{PLURAL:$1|секунд}} алда",
        "monday-at": "дүшәмбе $1",
        "tuesday-at": "шишәмбе $1",
        "wednesday-at": "шаршамбы $1",
        "exif-compression-4": "CCITT Group 4, факслы кодлау",
        "exif-copyrighted-true": "Авторлыҡ хоҡуҡтары менән һаҡлана",
        "exif-copyrighted-false": "Авторлыҡ-хоҡуҡи статус индерелмәгән",
+       "exif-photometricinterpretation-1": "Ҡара һәм аҡ (ҡара — 0)",
        "exif-unknowndate": "Билдәһеҙ көн",
        "exif-orientation-1": "Ғәҙәти",
        "exif-orientation-2": "X күсәре буйынса сағылдырылған",
        "confirm-watch-top": "Был битте күҙәтеү исемлегенә өҫтәргәме?",
        "confirm-unwatch-button": "Тамам",
        "confirm-unwatch-top": "Был битте күҙәтеү исемлегенән сығарырғамы?",
+       "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← алдағы бит",
        "imgmultipagenext": "киләһе бит →",
        "imgmultigo": "Күсеү!",
        "imgmultigoto": "$1 биткә күсеү",
+       "img-lang-default": "(килешеү буйынса тел)",
+       "img-lang-info": "Был рәсемде $1 $2 телдәрендә күрһәтергә",
+       "img-lang-go": "Күсергә",
        "ascending_abbrev": "үҫеүгә табан",
        "descending_abbrev": "кәмеүгә табан",
        "table_pager_next": "Киләһе бит",
        "autosumm-replace": "Биттең эстәлеге \"$1\" менән алыштырылған",
        "autoredircomment": "[[$1]] битенә йүнәлтелгән",
        "autosumm-new": "\"$1\" исемле яңы бит булдырылған",
+       "autosumm-newblank": "Буш бит булдырылған",
        "lag-warn-normal": "$1 {{PLURAL:$1|секундтан}} кәмерәк ваҡыт элек эшләнгән үҙгәртеүҙәр был исемлектә күрһәтелә алмай.",
        "lag-warn-high": "Мәғлүмәттәр базаларын синхронлаштырыуҙың күпкә артта ҡалыуы сәбәпле, $1 {{PLURAL:$1|секундтан}} кәмерәк ваҡыт элек эшләнгән үҙгәртеүҙәр был исемлектә күрһәтелә алмай.",
        "watchlistedit-normal-title": "Күҙәтеү исемлеген мөхәррирләү",
        "watchlistedit-raw-done": "Һеҙҙең күҙәтеү исемлеге яңырҙы.",
        "watchlistedit-raw-added": "{{PLURAL:$1|1=1 яҙма|$1 яҙма}} өҫтәлде:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1=1 яҙма|$1 яҙма}} юйылды:",
+       "watchlistedit-clear-title": "Күҙәтеүҙәр исемлеген таҙартыу",
+       "watchlistedit-clear-legend": "Күҙәтеүҙәр исемлеген таҙартыу",
+       "watchlistedit-clear-explain": "Күҙәтеү битендәге бөтә яҙмалар юйыласаҡ",
+       "watchlistedit-clear-titles": "Башлыҡ:",
+       "watchlistedit-clear-submit": "Күһәтеү исемлеген юйырға (кире ҡайтарып бумаясаҡ)",
+       "watchlistedit-clear-done": "Күҙәтеү исемлеге таҙартылған",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|юйылды}} $1 {{PLURAL:$1|яҙма}}:",
+       "watchlistedit-too-many": "Бында күрһәтеү өсөн биттәр бик күп",
+       "watchlisttools-clear": "Күҙәтеүҙәр исемлеген таҙартыу",
        "watchlisttools-view": "Исемлектәге биттәрҙәге үҙгәрештәр",
        "watchlisttools-edit": "Күҙәтеү исемлеген ҡарарға/төҙәтергә",
        "watchlisttools-raw": "Текст һымаҡ үҙгәртеү",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|әңгәмә]])",
+       "timezone-local": "Локаль",
        "duplicate-defaultsort": "'''Иҫкәртеү:''' \"$2\" ғәҙәттәге тәпртипкә килтереү асҡысы элекке \"$1\" ғәҙәттәге тәртипкә килтереү асҡысын үҙгәртә.",
+       "duplicate-displaytitle": "<strong>Иғтибар:</strong> Күрһәтелгән «$2» алдағы «$1» исемде ҡабатлай.",
+       "invalid-indicator-name": "<strong>Хата:</strong> Биттең торошон күрһәтеүсе атрибут индикаторы <code>name</code> буш була алмай.",
        "version": "MediaWiki өлгөһө",
        "version-extensions": "Ҡуйылған киңәйтеүҙәр",
        "version-skins": "Күренештәр",
        "version-hook-name": "Эләктереп алыусы исеме",
        "version-hook-subscribedby": "Яҙҙырылған",
        "version-version": "($1)",
-       "version-license": "Рөхсәтнамә",
+       "version-no-ext-name": "[исеме юҡ]",
+       "version-license": "MediaWiki лицензияһы",
+       "version-ext-license": "Лицензия",
+       "version-ext-colheader-name": "Киңәйтеү",
+       "version-skin-colheader-name": "Күренеш",
+       "version-ext-colheader-version": "Версия",
+       "version-ext-colheader-license": "Лицензия",
+       "version-ext-colheader-description": "Тасуирлама",
+       "version-ext-colheader-credits": "Автор",
+       "version-license-title": "$1 өсөн лицензия",
+       "version-license-not-found": "Был ҡушымта өсөн оҡшаған лицензиялар юҡ",
+       "version-credits-title": "$1 авторҙар исемлеге",
+       "version-credits-not-found": "Был ҡушымта өсөн  авторҙар тураһында мәғлүмәт юҡ",
        "version-poweredby-credits": "Был вики проект '''[https://www.mediawiki.org/ MediaWiki]''' нигеҙендә эшләй, copyright © 2001-$1 $2.",
        "version-poweredby-others": "башҡалар",
        "version-poweredby-translators": "translatewiki.net тәржемәселәре",
        "version-entrypoints": "Инеш өсөн URL адрестар",
        "version-entrypoints-header-entrypoint": "Инеш урыны",
        "version-entrypoints-header-url": "URL",
+       "version-libraries": "Урынлаштырылған китапханалар",
+       "version-libraries-library": "Китапхана",
+       "version-libraries-version": "Версия",
+       "version-libraries-license": "Лицензия",
+       "version-libraries-description": "Тасуирлама",
+       "version-libraries-authors": "Авторҙар",
        "redirect": "Файлдан, файҙаланыусынан йә версияның тиңләштереүсеһенән артабан йүнәлтеү",
-       "redirect-legend": "Файлға йәки биткә йүнәлтеү",
        "redirect-summary": "Был махсус бит файлға (файлдың исеменән), биткә (версияның тиңләштереүсеһенән) йәки ҡатнашыусының битенә (ҡатнашыусының һанлы тиңләштереүсеһенән) йүнәлтә.",
        "redirect-submit": "Күсергә",
        "redirect-lookup": "Эҙләү",
        "redirect-value": "Мәғәнәһе:",
        "redirect-user": "Ҡатнашыусының тиңләштереүсеһе",
+       "redirect-page": "Бит идентификаторы",
        "redirect-revision": "Биттең версияһы",
        "redirect-file": "Файлдың исеме",
+       "redirect-logid": "ID журнал",
        "redirect-not-exists": "Мәғәнәһе табылманы",
        "fileduplicatesearch": "Бер иш файлдарҙы эҙләү",
        "fileduplicatesearch-summary": "Бер иш файлдарҙы хэш-кодтары буйынса эҙләү.",
        "fileduplicatesearch-result-n": "\"$1\" файлы менән $2 {{PLURAL:$2|файл}} тап килә.",
        "fileduplicatesearch-noresults": "\"$1\" исемле файл табылманы",
        "specialpages": "Махсус биттәр",
+       "specialpages-note-top": "Легенда",
        "specialpages-note": "* Ябай махсус биттәр.\n* <span class=\"mw-specialpagerestricted\">Сикле махсус биттәр.</span>\n* <span class=\"mw-specialpagecached\">Кешланған махсус биттәр (иҫкергән булыуы мөмкин).</span>",
        "specialpages-group-maintenance": "Техник хеҙмәтләндереү хисапламалары",
        "specialpages-group-other": "Башҡа махсус биттәр",
        "tags-tag": "Билдә исеме",
        "tags-display-header": "Үҙгәртеүҙәр исемлегендә күрһәтеү",
        "tags-description-header": "Мәғәнәһенең тулы тасуирламаһы",
+       "tags-source-header": "Сығанаҡ",
        "tags-active-header": "Әүҙемме?",
        "tags-hitcount-header": "Билдәләнгән үҙгәртеүҙәр",
+       "tags-actions-header": "Ғәмәлдәр",
        "tags-active-yes": "Эйе",
        "tags-active-no": "Юҡ",
+       "tags-source-extension": "Ҡушымта билдәләй",
+       "tags-source-manual": "Ҡатнашыусы йәки робот ҡулдан индерә",
+       "tags-source-none": "Башҡа ҡулланылмай",
        "tags-edit": "үҙгәртергә",
+       "tags-delete": "юйырға",
+       "tags-activate": "активлаштырырға",
+       "tags-deactivate": "һүндерергә",
        "tags-hitcount": "$1 {{PLURAL:$1|1=үҙгәртеү|үҙгәртеү}}",
+       "tags-manage-no-permission": "Тамға исемен үҙгәртергә хоҡуғығыҙ юҡ",
+       "tags-manage-blocked": "Һеҙгә блок ҡуйылған, тамғалар менән идара итә алмайһығыҙ.",
+       "tags-create-heading": "Яңы тамға булдырырға",
+       "tags-create-explanation": "яңы булдырылған билдәләр боттар һәм ҡатнашыусылар ҡуллана алырлыҡ итеп эшләнәсәк",
+       "tags-create-tag-name": "Тамға исеме",
+       "tags-create-reason": "Сәбәп:",
+       "tags-create-submit": "Яһау",
+       "tags-create-no-name": "Тамға исемен яҙығыҙ",
+       "tags-create-invalid-chars": "Тамға исемдәрендә өтөр (<code>,</code>) йәки һыҙыҡ  (<code>/</code>) булмаҫҡа тейеш.",
+       "tags-create-invalid-title-chars": "Билдә исемдәрендә бит атамаларында файҙаланып булмаған символдар булмаҫҡа тейеш",
+       "tags-create-already-exists": "$1 тамғаһы бар инде.",
+       "tags-create-warnings-above": "«$1» билдәһен яһарға тырышҡанда асыҡлана{{PLURAL:$2|о киләһе иҫкәрмә|ы киләһе иҫкәрмә}}:",
+       "tags-create-warnings-below": "Тамға булдырыуҙы дауам итергә теләйһегеҙме?",
+       "tags-delete-title": "Тамғаны юйырға",
+       "tags-delete-explanation-initial": " «$1» тамғаһын мәғлүмәттәр базаһынан юйырға теләйһегеҙме?",
+       "tags-delete-explanation-in-use": "Ул әлеге ваҡытта ҡулланылған {{PLURAL:$2|$2 версияһынан йәки журналдағы яҙманан|барлыҡ $2 версияһынан йәки журналдағы яҙмаларҙан}}  юйыласаҡ",
+       "tags-delete-explanation-warning": "Был ғәмәл <strong> кире ҡайтарылғыһыҙ</strong> һәм <strong>мәғлүмәттәр базаһы хакимдары тарафынан да үҙгәртелә алмай</strong>. Һеҙ ысынлап та был билдәне юйырға теләүегеҙгә инанырға тейешһегеҙ.",
+       "tags-delete-explanation-active": "<strong> «$1» билдәһе элеккесә актив һәм киләсәктә лә ҡулланыласаҡ.</strong> Шулай булыуын теләмәйһегеҙ икән, билдәне ҡулланыу урынына күсеп, уны һүндерегеҙ.",
+       "tags-delete-reason": "Сәбәп:",
+       "tags-delete-submit": "Тамғаны кире ҡайтарылмаҫлыҡ итеп юйырға.",
+       "tags-delete-not-allowed": "Ҡушымталағы тамғалар юйылмай, әгәр ҡушымта асыҡ рөхсәт бирмәһә.",
+       "tags-delete-not-found": "$1 тамғаһы юҡ.",
+       "tags-delete-too-many-uses": " «$1» тамғаһы $2 {{PLURAL:$2|өлгөлә}} артығыраҡ ҡулланыла, был юйылмаясаҡ тигәнде аңлата.",
+       "tags-delete-warnings-after-delete": " «$1» тамғаһы юйылды, әммә {{PLURAL:$2|түбәндәге киҫәтеүҙәр алында}}:",
+       "tags-activate-title": "Тамғаны активлаштырырға",
+       "tags-activate-question": "«$1» тамғаһын активлыштырырға теләйһегеҙме?",
+       "tags-activate-reason": "Сәбәп:",
+       "tags-activate-not-allowed": "«$1» тамғаһын активлаштырып булмай.",
+       "tags-activate-not-found": "$1 тамғаһы юҡ.",
+       "tags-activate-submit": "активлаштырырға",
+       "tags-deactivate-title": "Тамғаны активлаштырырға",
+       "tags-deactivate-question": "«$1» тамғаһын һүндерергә теләйһегеҙме?",
+       "tags-deactivate-reason": "Сәбәп:",
+       "tags-deactivate-not-allowed": "«$1» тамғаһын һүндереп булмай.",
+       "tags-deactivate-submit": "һүндерергә",
+       "tags-apply-no-permission": "Һеҙҙең үҙгәртеү тамғаһы ҡуйыу хоҡуғы юҡ.",
+       "tags-apply-blocked": "Үҙгәртеүҙәргә тамға ҡуфырға һеҙҙең хоҡуҡ юҡ, һеҙ бикләнгән.",
+       "tags-apply-not-allowed-one": " «$1» тамғаһын ҡулдан файҙаланып булмай",
+       "tags-apply-not-allowed-multi": "Ҡулдан {{PLURAL:$2|түбәндәге тамғаны өҫтәп булмай}}: $1",
+       "tags-update-no-permission": "Һеҙҙең айырым өлгөләрҙә һәм журнал яҙмаларында тамға йәки үҙгәртеү тамғаһы ҡуйырға хоҡуғығыҙ юҡ.",
+       "tags-update-blocked": "Һеҙгә блок ҡуйылған, үҙһәртеү тамғалары менән идара итә алмайһығыҙ.",
+       "tags-update-add-not-allowed-one": " «$1» тамғаһын ҡулдан файҙаланып булмай",
+       "tags-update-add-not-allowed-multi": "{{PLURAL:$2|түбәндәге тег}} ҡулдан өҫтәлмәй: $1",
+       "tags-update-remove-not-allowed-one": " «$1» тамғаһын юйып булмай",
+       "tags-update-remove-not-allowed-multi": "Ҡулдан {{PLURAL:$2|түбәндәге тамғаны юйып булмай}}: $1",
+       "tags-edit-title": "Тамғаны мөхәррирләү",
+       "tags-edit-manage-link": "Тамғаларҙы идаралау",
+       "tags-edit-revision-selected": "{{PLURAL:$1|Һайланған версия}} [[:$2]]:",
+       "tags-edit-logentry-selected": "Журналда {{PLURAL:$1|1=Һайланған яҙма}}:",
+       "tags-edit-revision-legend": "{{PLURAL:$1|1=Был өлгөлә}} өҫтәргә йәки юйырға",
+       "tags-edit-logentry-legend": "{{PLURAL:$1|this log entry|all $1 log entries}} тамғаны өҫтәргә йәки юйырға",
+       "tags-edit-existing-tags": "Булған тамға:",
+       "tags-edit-existing-tags-none": "<em>Юҡ</em>",
+       "tags-edit-new-tags": "Яңы тамғалар:",
+       "tags-edit-add": "Был тамғаларҙы өҫтәргә",
+       "tags-edit-remove": "Был билдәне юйырғамы?",
+       "tags-edit-remove-all-tags": "(бөтә тамғаны юйырға)",
+       "tags-edit-chosen-placeholder": "Бер йәки бер нисә тэг һайлағыҙ",
+       "tags-edit-chosen-no-results": "Тап килгән тамғалар табылманы",
+       "tags-edit-reason": "Сәбәп:",
+       "tags-edit-revision-submit": "Был {{PLURAL:$1|өлгөгә}} ҡулланырға",
+       "tags-edit-logentry-submit": "Үҙгәртеһгә {{PLURAL:$1|журналдағы яҙма}} ҡулланырға",
+       "tags-edit-success": "Үҙгәртеүҙәр ҡабул ителде",
+       "tags-edit-failure": "Үҙгәртеүҙәрҙе ҡабул итеп булманы $1",
+       "tags-edit-nooldid-title": "Маҡсат версия билдәләнмәгән",
+       "tags-edit-nooldid-text": "Һеҙ маҡсат версияһын күрһәтмәнегеҙ, йәки ул версия ғәмәлдә юҡ.",
+       "tags-edit-none-selected": "Бер йәки артығыраҡ тег һайлағыҙ.",
        "comparepages": "Биттәрҙе сағыштырыу",
        "compare-page1": "Беренсе бит",
        "compare-page2": "Икенсе бит",
        "htmlform-chosen-placeholder": "Вариант һайлағыҙ",
        "htmlform-cloner-create": "Тағы өҫтәргә",
        "htmlform-cloner-delete": "Юйырға",
+       "htmlform-cloner-required": "Кәм тигәндә бер дәүмәл кәрәк",
+       "htmlform-title-badnamespace": "[[:$1]] исемдәр арауығында түгел «{{ns:$2}}».",
+       "htmlform-title-not-creatable": "«$1» — бит исеме, быны булдырып булмай",
+       "htmlform-title-not-exists": "$1 юҡ",
+       "htmlform-user-not-exists": "<strong>$1</strong> ғәмәлдә юҡ",
+       "htmlform-user-not-valid": "<strong>$1</strong> — ярамаған иҫәп яҙмаһы",
        "sqlite-has-fts": "$1, тулы текст буйынса эҙләү мөмкинлеге менән",
        "sqlite-no-fts": "$1, тулы текст буйынса эҙләү мөмкинлекһеҙ",
        "logentry-delete-delete": "$1 $3 битен {{GENDER:$2|юйҙы}}",
        "revdelete-uname-unhid": "ҡатнашыусы исеме күрһәтелде",
        "revdelete-restricted": "хакимдәргә ҡаршы ҡулланылған сикләүҙәр",
        "revdelete-unrestricted": "хакимдәрҙән алынған сикләүҙәр",
+       "logentry-block-block": "$1 блокланы{{GENDER:$2||}} {{GENDER:$4|$3}}  $5 $6",
+       "logentry-block-unblock": "$1 блоктан азат итте{{GENDER:$2||а}} {{GENDER:$4|$3}}",
+       "logentry-block-reblock": "Блоклау ваҡытын $1 {{GENDER:$2|үҙгәртте}}  {{GENDER:$4|$3}}  $5 $6",
+       "logentry-suppress-block": "$1 блокланы{{GENDER:$2||}} {{GENDER:$4|$3}}  $5 $6",
+       "logentry-suppress-reblock": "$1 бикләү ваҡытын {{GENDER:$2|үҙгәртте}}  {{GENDER:$4|$3}}  $5 $6",
+       "logentry-import-upload": "Файл тейәү ысулы менән $1 импортиртланы {{GENDER:$2||а}} $3",
+       "logentry-import-upload-details": "Файл тейәү ысулы менән $1 импортланы {{GENDER:$2||а}} $3 ($4 {{PLURAL:$4|версияһын}})",
+       "logentry-import-interwiki": "$1 башҡа викинан{{GENDER:$2||а}} $3 импортланы",
+       "logentry-import-interwiki-details": "$1 {{GENDER:$2||а}} $3  $5 импортланы ($4 {{PLURAL:$4|версиларын}})",
+       "logentry-merge-merge": "$1 берләштерҙе{{GENDER:$2||а}} $3  $4 ($5 версияһына тиклем)",
        "logentry-move-move": "$1  $3 битенең исемен {{GENDER:$2| үҙгәртте}}. Яңы исеме: $4",
        "logentry-move-move-noredirect": "$1 $3 битенең исемен йүнәлтеү ҡуймайынса {{GENDER:$2|үҙгәртте}}. Яңы исеме: $4",
        "logentry-move-move_redir": "$1 $3 битенең исемен йүнәлтеү өҫтөнән {{GENDER:$2|үҙгәртте}}. Яңы исеме: $4",
        "logentry-newusers-create2": "$1 {{GENDER:$2|ҡатнашыусы}} $3 иҫәп яҙмаһын булдырҙы",
        "logentry-newusers-byemail": "$1 {{GENDER:$2|}} $3 иҫәп яҙмаһын булдырҙы һәм серһүҙ электрон почта аша ебәрелде",
        "logentry-newusers-autocreate": "Автоматик рәүештә {{GENDER:$2| ҡатнашыусының}} $1 иҫәп яҙмаһы яһалды",
+       "logentry-protect-move_prot": "$1 һаҡлау көйәләүен $4 $3 {{GENDER:$2|күсерҙе}}",
+       "logentry-protect-unprotect": "$1 $3-нан һаҡлауҙы  {{GENDER:$2||алды}}",
+       "logentry-protect-protect": "$1 һаҡланы{{GENDER:$2||а}} $3 $4",
+       "logentry-protect-protect-cascade": "$1 һаҡланы{{GENDER:$2||}} $3 $4 [каскадлы]",
+       "logentry-protect-modify": "$1$ һаҡлау кимәлен {{GENDER:$2||үҙгәртте}} $3 $4",
+       "logentry-protect-modify-cascade": "$1 һаҡлау кимәлен{{GENDER:$2||үҙгәртте}}  $3 $4 [каскадлы]",
        "logentry-rights-rights": "$1  $3 файҙаланыусының төркөмдәрҙәге ағзалығын $4 урынына $5 тип {{GENDER:$2|үҙгәртте}}",
        "logentry-rights-rights-legacy": "$1  $3 өсөн төркөмдәрҙәге ағзалыҡты {{GENDER:$2|үҙгәртте}}",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|}} автоматик рәүештә {{GENDER:$2|}} $4 урынына $5 ителде.",
        "logentry-upload-upload": "$1 $3 {{GENDER:$2|күсерҙе}}",
+       "logentry-upload-overwrite": "$1 яңы өлгә{{GENDER:$2||тейәне}} $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2||тейәне}} $3",
+       "log-name-managetags": "Тамғалар менән идара итеү журналы",
+       "log-description-managetags": "Был биттә  [[Special:Tags|метками]] идара итеү мәсьәләләре килтерелгән. Журналда администратор ҡулдан эшләгән ғәмәл генә бар. Тамғаларыҙа, журналға яҙмайынса ғына, вики-программалар ярҙамында ҡуйырға йәки юйырға мөмкин.",
+       "logentry-managetags-create": "$1 «$4» тамғаһын {{GENDER:$2||булдырҙы}}",
+       "logentry-managetags-delete": "$1 «$4» тамғаһын {{GENDER:$2||юйҙы}}  ($5 {{PLURAL:$5|журнал яҙмаһынан}} юйылды)",
+       "logentry-managetags-activate": "$1 «$4» тамғаһын{{GENDER:$2||активлаштырҙы}}, ҡатнашыусылар һәм роботтар ҡуллана торған тамға.",
+       "logentry-managetags-deactivate": "$1 «$4» тамғаһы өсөн{{GENDER:$2||һүндерҙе}} ҡатнашыусылар һәм роботтар ҡуллана торған тамғаны",
+       "log-name-tag": "Тамғалар журналы",
+       "log-description-tag": "Был биттә ҡасан ҡатнашыусылар айырым өлгөләрҙә һәм журналдарҙы  [[Special:Tags|тамғалар]] ҡуйғаны һәм юйғаны күренә. Үҙгәртеү, юйыу һәм шуға оҡшаған ғәмәлдәргә ҡуйылған тамға күренмәй.",
+       "logentry-tag-update-add-revision": "$1 {{GENDER:$2||}} {{PLURAL:$7|тамғаһын}} өҫтәне $6  $4 өлгөһөнә $3 битенә",
+       "logentry-tag-update-add-logentry": "$1 {{GENDER:$2||}} {{PLURAL:$7|тамғаһын}} өҫтәне$6  $5 журнал яҙмаһына $3 битендә",
+       "logentry-tag-update-remove-revision": "$1 {{GENDER:$2||}} {{PLURAL:$9|тамғаһын}} юйҙы $8  $4 өлгөһөнә $3 битенә",
+       "logentry-tag-update-remove-logentry": "$1 {{GENDER:$2||}} {{PLURAL:$9|тамғаһын}} юйҙы $8  $5 өлгөһөнә $3 битенә",
+       "logentry-tag-update-revision": "$1 {{GENDER:$2||яңыртты}}  $4 өлгөһөнөң тамғаларын $3 битендә ({{PLURAL:$7|өҫтәне}} $6; {{PLURAL:$9|юйылған}} $8)",
+       "logentry-tag-update-logentry": "$1 {{GENDER:$2||а}}журналда билдәләнгән яҙмаларҙы яңыртты $5 биттәр $3 (өҫтәлгән{{PLURAL:$7|а|ы}} $6; юйылған{{PLURAL:$9|а|ы}} $8)",
        "rightsnone": "(юҡ)",
        "revdelete-summary": "үҙгәртеүҙәр тасуирламаһы",
        "feedback-adding": "Биткә кире белдереү өҫтәлә",
+       "feedback-back": "Артҡа",
        "feedback-bugcheck": "Шәп! Тик [$1 билдәле хаталар] исемлегендә оҡшаш белдереүҙең булмауына иғтибар итегеҙ.",
        "feedback-bugnew": "Тикшерҙем. Яңы хата тураһында белдерергә",
        "feedback-bugornote": "Әгәр Һеҙ техник проблеманы ентекле рәүештә аңлатырға теләһәгеҙ, зинһар, [$1 хата тураһында белдерегеҙ].\nБашҡа осраҡта, ошо ябай форманы ҡуллана алаһығыҙ. Комментарийығыҙ «[$3 $2]» битенә ҡулланыусы исемегеҙ һәм браузер мәғлүмәте менән өҫтәләсәк.",
        "feedback-cancel": "Кире алырға",
        "feedback-close": "Әҙер",
+       "feedback-external-bug-report-button": "Техник эш еберергә",
+       "feedback-dialog-title": "Баһалама ебәрергә",
+       "feedback-dialog-intro": "Баһалама ебәреү өсөн түбәндәге форманы файҙаланығыҙ. Һеҙҙең исем менән комментарий «$1» битендә буласаҡ.",
        "feedback-error-title": "Хата",
        "feedback-error1": "Хата: API-нан беленмәгән хата",
        "feedback-error2": "Хата: Мөхәррирләү хатаһы",
        "feedback-error3": "Хата: API-нан яуап юҡ",
+       "feedback-error4": "Хата: Баһаламала был баш һүҙ аҫтындағы яҙманы урынлаштырап булмай.",
        "feedback-message": "Хәбәр:",
        "feedback-subject": "Тема:",
-       "feedback-submit": "Кире белдереү ебәрергә",
+       "feedback-submit": "Ебәрергә",
+       "feedback-terms": "Ҡатнашыусы агенты мәғлүмәтендә минең браузер һәм операцион система турыһанда мәғлүмәт булыуы миңә билдәле, минең баһаламала был мәғлүмәт асыҡ буласаҡ.",
+       "feedback-termsofuse": "Минең Ҡулланыу шарттары буйынса кире бәйленеш булдырырға риза.",
        "feedback-thanks": "Рәхмәт! Һеҙҙең фекерегеҙ «[$2 $1]» битенә өҫтәлде.",
+       "feedback-thanks-title": "Рәхмәт!",
+       "feedback-useragent": "Браузер:",
        "searchsuggest-search": "Эҙләү",
        "searchsuggest-containing": "эстәлегендә...",
        "api-error-badaccess-groups": "Һеҙгә был викиға файлдар күсереү рөхсәт ителмәй",
        "api-error-overwrite": "Булған файлды алыштырыу рөхсәт ителмәй.",
        "api-error-stashfailed": "Эске хата: сервер ваҡытлыса файлды һаҡлай алманы.",
        "api-error-publishfailed": "Эске хата: сервер ваҡытлыса файлды һаҡлай алманы.",
+       "api-error-stasherror": "Файлы һаҡлағысҡа тейәгән ваҡытта хата китте.",
+       "api-error-stashedfilenotfound": "Ваҡытлыса һаҡлағыстан файлы тейәгән ваҡытта сығанаҡ файл табылманы.",
+       "api-error-stashpathinvalid": "Ваҡытлыса һаҡлағыста урынлашҡан файл юлы дөрөҫ түгел.",
+       "api-error-stashfilestorage": "Файлды һаҡлағысҡа тейәгән ваҡытта хата китте.",
+       "api-error-stashzerolength": "Сервер файлды ваҡытлыса һаҡлағыста һаҡлау алмай, сөнкт оҙонлоғо 0.",
+       "api-error-stashnotloggedin": "Файлды ваҡытлыса һаҡлағысҡа урынлаштырыу өсөн һеҙ системаҡа инергә тейешһегеҙ.",
+       "api-error-stashwrongowner": "Ваҡытлыса һаҡлағыстағы файлда асырға теләнегеҙ, был файл һеҙҙеке түгел",
+       "api-error-stashnosuchfilekey": "Ваҡытлыса һаҡлағыста һеҙ асырға теләгән файлдың асҡысы юҡ.",
        "api-error-timeout": "Көтөлгән ваҡыт эсендә сервер яуып бирмәне.",
        "api-error-unclassified": "Билдәһеҙ хата барлыҡҡа килде.",
        "api-error-unknown-code": "Билдәһеҙ хата: «$1»",
        "duration-seconds": "$1 {{PLURAL:$1|1=секунд|секунд}}",
        "duration-minutes": "$1 {{PLURAL:$1|1=минут|минут}}",
        "duration-hours": "$1 {{PLURAL:$1|1=сәғәт|сәғәт}}",
-       "duration-days": "$1 {{PLURAL:$1|1=көн|көн}}",
-       "duration-weeks": "$1 {{PLURAL:$1|аҙна|аҙналар|аҙна}}",
-       "duration-years": "$1 {{PLURAL:$1|1=йыл|йылдар}}",
-       "duration-decades": "$1 {{PLURAL:$1|1=Ñ\83н ÐºÓ©Ð½Ð»Ó©Ðº|Ñ\83н ÐºÓ©Ð½Ð»Ó©ÐºÑ\82Ó\99р}}",
+       "duration-days": "$1 {{PLURAL:$1|көн}}",
+       "duration-weeks": "$1 {{PLURAL:$1|аҙна}}",
+       "duration-years": "$1 {{PLURAL:$1|йыл}}",
+       "duration-decades": "$1 {{PLURAL:$1|1=Ñ\83н Ð¹Ñ\8bллÑ\8bÒ¡|Ñ\83н Ð¹Ñ\8bллÑ\8bÒ¡Ñ\82ар}}",
        "duration-centuries": "$1 {{PLURAL:$1|1=быуат|быуаттар}}",
        "duration-millennia": "$1 {{PLURAL:$1|1=меңйыллыҡ|меңйыллыҡтар}}",
        "rotate-comment": "Рәсем сәғәт йөрөшө буйынса $1{{PLURAL:$1|}} градусҡа боролдо",
        "expand_templates_input": "Сығанаҡ текст:",
        "expand_templates_output": "Һөҙөмтә",
        "expand_templates_xml_output": "XML һөҙөмтә",
+       "expand_templates_html_output": "HTML-сығарыу",
        "expand_templates_ok": "Тамам",
        "expand_templates_remove_comments": "Аңлатмаларҙы юйырға",
        "expand_templates_remove_nowiki": "Һөҙөмтәлә <nowiki> билдәләрен йәшерергә",
        "expand_templates_generate_xml": "XML уҡыу ағасын күрһәтергә",
+       "expand_templates_generate_rawhtml": "Күрһәтергә HTML",
        "expand_templates_preview": "Ҡарап сығыу",
+       "expand_templates_preview_fail_html": "'''Ҡыҙғанысҡа ҡаршы, һеҙҙең ултырыш мәғлүмәттәрегеҙ юғалды. Һөҙөмтәлә, сервер үҙгәрештерегеҙҙе ҡабул итә алмай.'''\n\n''{{SITENAME}} тик таҙа HTML ҡулланыуҙы ғына рөхсәт итә; алдан ҡарау, JavaScript-атакаларҙан һаҡланыу маҡсаты менән ябылған.''\n\n'''Әгәр һеҙ үҙгәртеүҙе яҡшы ниәт менән башҡараһағыҙ икән, тағы бер тапҡыр ҡабатлап ҡарағыҙ. Хата ҡабатланһа, сайттан [[Special:UserLogout|сығығыҙ]] һәм яңынан керегеҙ.'''",
+       "expand_templates_preview_fail_html_anon": "<em>Сайт {{SITENAME}}  «һоро» HTML исемлегендә, һеҙ танылманығыҙ, шуға алдан ҡарау JavaScript-атакаһынан һаҡланыу сараһы буларыҡ йәшерелгән</em>\n\n<strong> [[Special:UserLogin|Танылығыҙ]] һәм тағы бер мәртәбә эшләп ҡарағыҙ.",
+       "expand_templates_input_missing": "Һеҙ ниндәй ҙә булһа һөйләм ҡуйырға тейешһегеҙ",
+       "pagelanguage": "Биттең телен үҙгәртеү",
+       "pagelang-name": "Бит",
+       "pagelang-language": "Тел",
+       "pagelang-use-default": "Ҡуйылған тел ҡулланырға",
+       "pagelang-select-lang": "Тел һайлау:",
+       "pagelang-submit": "Ебәрергә",
+       "right-pagelang": "Биттең телен үҙгәртеү",
+       "action-pagelang": "Биттең телен үҙгәртеү",
+       "log-name-pagelang": "Телде үҙгәртеү дәфтәре",
+       "log-description-pagelang": "Был бит телдәрендә үҙгәреүҙәр дәфтәре",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|үҙгәртте}} язык страницы $3 биттең телен $4-тән $5-кә.",
+       "default-skin-not-found": "Уп-па! Викиҙы биҙәү темаһы рөхсәт ителмәгән <code>$wgDefaultSkin</code>, <code>$1</code>.\n\nҺеҙең ҡоролмала {{PLURAL:$4|түбәндәге}} биҙәү темалары бар.  [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration]  {{PLURAL:$4|Килешеү буйынса тема һайларға}}.\n\n$2\n\n; Әгәр яңы ғына MediaWiki урынлаштарған булһығыҙ:\n:Һеҙ быны Git-тан йәки сығанаҡ кодтан башға ысул ҡулланып эшләгәнһегеҙ.  Ул ваҡытта был мөмкин. Ҡайһы бер темаларҙы урынлаштырып ҡарағыҙ[https://www.mediawiki.org/wiki/Category:All_skins сайт биҙәү өсөн каталог mediawiki.org]:\n:* [https://www.mediawiki.org/wiki/Download урынлаштырырға йүнәлеш биреүсе файлдар архивын] тейәп алып <code>skins/</code> папкаһының күсермәһен алығыҙ;\n:* биҙәү өсөн айырым темалар архивын [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org];\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins  Git-ты ҡулланып тейәргә].\n: Git, MediaWiki-ны эшләүсе булһағыҙ һеҙҙең репозиторға зыян килтерергә тейеш түгел.  [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration] килешеү буйынса тема һайлау тарыһында мәғлүмәт.\n; MediaWiki-ны әле генә яңыртҡан булһағыҙ:\n: MediaWiki версиһында 1.24 автоматик яүыртыу булмаясаҡ. ([https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]).\n{{PLURAL:$5|Түбендәге юлды}} ҡуйығыҙ <code>LocalSettings.php</code>,  {{PLURAL:$5|урынлаштырылған темаларҙы}} биҙәү өсөн: \n\n<pre dir=\"ltr\">$3</pre>\n\n;Әгәр яңы ғына үҙгәрткән булһағыҙ <code>LocalSettings.php</code>:\n: Тема исемендә хата булмаһын, тикшерегеҙ.",
+       "default-skin-not-found-no-skins": "Уп-па! Викины биҙәү темаһы рөхсәт ителмәгән <code>$wgDefaultSkin</code>, <code>$1</code>.\n\nҺеҙең ҡоролмала түбәндәге биҙәү темалары бар.  [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration]  \n\n\n; Әгәр яңы ғына MediaWiki урынлаштарған булһығыҙ:\n:Һеҙ быны Git-тан йәки сығанаҡ кодтан башҡа ысул ҡулланып эшләгәнһегеҙ.  Ул ваҡытта был мөмкин. Ҡайһы бер темаларҙы урынлаштырып ҡарағыҙ[https://www.mediawiki.org/wiki/Category:All_skins сайт биҙәү өсөн каталог mediawiki.org]:\n:* [https://www.mediawiki.org/wiki/Download урынлаштырырға йүнәлеш биреүсе файлдар архивын] тейәп алып <code>skins/</code> папкаһының күсермәһен алығыҙ;\n:* биҙәү өсөн айырым темалар архивын [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org];\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins  Git-ты ҡулланып тейәргә].\n: Git, MediaWiki-ны эшләүсе булһағыҙ һеҙҙең репозиторға зыян килтерергә тейеш түгел.  [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual:Skin configuration] килешеү буйынса тема һайлау тарыһында мәғлүмәт.\n; MediaWiki-ны әле генә яңыртҡан булһағыҙ:\n: MediaWiki версиһында 1.24 автоматик яүыртыу булмаясаҡ. ([https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Skin autodiscovery]).\n \n\n\n;Әгәр яңы ғына үҙгәрткән булһағыҙ <code>LocalSettings.php</code>:\n: Тема исемендә хата булмаһын, тикшерегеҙ.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (рөхсәт ителгән)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>рөхсәт ителмәгән</strong>)",
+       "mediastatistics": "Медиа-статистика",
+       "mediastatistics-summary": "Тейәләгән файлдар тибы тураһында статистика. Файлдың һуңғы версия тураһында мәғлүмәт бар. Иҫке һәм юйылған файлдар иҫәпкә алынмай.",
+       "mediastatistics-nbytes": "$1 байт{{PLURAL:$1|}} ($2; $3%)",
+       "mediastatistics-bytespertype": "Был бүлек өсөн файлдың дөйөм күләме: $1 байт{{PLURAL:$1|}} ($2; $3%).",
+       "mediastatistics-allbytes": "Бөтә файлдар күләме: $1 байт{{PLURAL:$1|}} ($2).",
+       "mediastatistics-table-mimetype": "MIME-төрҙәре",
+       "mediastatistics-table-extensions": "Рөхсәт ителгән ҡушылмалар",
+       "mediastatistics-table-count": "Биттәр һаны",
+       "mediastatistics-table-totalbytes": "Дөйөм күләме",
+       "mediastatistics-header-unknown": "Билдәһеҙ",
+       "mediastatistics-header-bitmap": "Растр рәсем",
+       "mediastatistics-header-drawing": "Рәсемдәр (вектор рәсем)",
+       "mediastatistics-header-audio": "Аудио",
+       "mediastatistics-header-video": "Видео",
+       "mediastatistics-header-multimedia": "Мультимедиа",
+       "mediastatistics-header-office": "Офис",
+       "mediastatistics-header-text": "Текст",
+       "mediastatistics-header-executable": "Башҡарылыусы",
+       "mediastatistics-header-archive": "Ҡыҫылған формат",
+       "mediastatistics-header-total": "Барлыҡ файлдар",
+       "json-warn-trailing-comma": "$1 {{PLURAL:$1|һөйләм аҙаҡында артыҡ өтөр юйылды}} JSON",
+       "json-error-unknown": "JSON менән проблемалар бар. Хата: $1",
+       "json-error-depth": "Стек өсөн максималь тәрәнлек артып киткән.",
+       "json-error-state-mismatch": "Ярамаған йәки дөрөҫ төҙөлмәгән JSON",
+       "json-error-ctrl-char": "Идара символында хата, кодировка дөрөҫ төҙөлмәгән булыуы ихтимал.",
+       "json-error-syntax": "Синтаксик хата",
+       "json-error-utf8": "Хаталы UTF-8 символдары, кодировка дөрөҫ булмауы изтимал.",
+       "json-error-recursion": "Бер йәки бер нисә рекурсив һылтанма кодланҡан булырға тейеш.",
+       "json-error-inf-or-nan": "Бер йәки бер нисә NAN- йәки INF-дәүмәле код ҡуйылған булырға тейеш.",
+       "json-error-unsupported-type": "Код ҡуйып булмаҫлыҡ дәүмәл бирелгән.",
+       "headline-anchor-title": "Был бүлеккә һылтанма",
        "special-characters-group-latin": "Латин",
        "special-characters-group-latinextended": "Латин (киңәйтелгән)",
        "special-characters-group-ipa": "ХАФӘ (IPA)",
        "special-characters-group-symbols": "Тамғалар",
        "special-characters-group-greek": "Грек",
+       "special-characters-group-greekextended": "Грек телендә киңәйтелгән",
        "special-characters-group-cyrillic": "Кириллик",
        "special-characters-group-arabic": "Ғәрәп",
        "special-characters-group-arabicextended": "Ғәрәп (киңәйтелгән)",
        "special-characters-group-khmer": "Кһмер",
        "special-characters-title-endash": "уртаса һыҙыҡ",
        "special-characters-title-emdash": "оҙон һыҙыҡ",
-       "special-characters-title-minus": "минус билдәһе"
+       "special-characters-title-minus": "минус билдәһе",
+       "mw-widgets-dateinput-no-date": "Дата һайланмаған",
+       "mw-widgets-titleinput-description-new-page": "Был бит юҡ",
+       "mw-widgets-titleinput-description-redirect": "$1 йүнәлтеү",
+       "api-error-blacklisted": "Башҡа аңлайышлы исем һайлағыҙ.",
+       "sessionmanager-tie": "Бер юлы бер нисә ғаризаның төп нөсхәһен тикшереп булмай: $1.",
+       "sessionprovider-generic": "$1 сессия",
+       "sessionprovider-mediawiki-session-cookiesessionprovider": "куки нигеҙендә сессиялар",
+       "sessionprovider-nocookies": "Ярҙам кәрәкме?",
+       "randomrootpage": "Ярҙам кәрәкме?",
+       "log-action-filter-block": "Блоклау төрө:",
+       "log-action-filter-delete": "Юйҙырыу төрө:",
+       "log-action-filter-patrol": "Патруль төрө:",
+       "log-action-filter-protect": "Һаҡлау төрө:",
+       "log-action-filter-upload": "Күсереү төрө:",
+       "log-action-filter-all": "Барыһы",
+       "log-action-filter-block-block": "Бикләргә",
+       "log-action-filter-block-reblock": "Бикте үҙгәртеү",
+       "log-action-filter-block-unblock": "Бикте алырға",
+       "log-action-filter-delete-delete": "Битте юйыуҙар",
+       "log-action-filter-delete-restore": "Битте тергеҙеү",
+       "log-action-filter-delete-event": "Журналды юйыу",
+       "log-action-filter-delete-revision": "Версияны алып ташларға",
+       "log-action-filter-patrol-patrol": "Ҡулдан патруль яһау",
+       "log-action-filter-patrol-autopatrol": "Автоматик патруль",
+       "log-action-filter-protect-protect": "Һаҡлау",
+       "log-action-filter-protect-modify": "Яңынан тейәү",
+       "log-action-filter-protect-unprotect": "Һаҡты алып ташлау",
+       "log-action-filter-upload-upload": "Яңы күсереү",
+       "log-action-filter-upload-overwrite": "Ҡабаттан тейәү"
 }
index 78f9716..747176c 100644 (file)
        "noemail": "{{GENDER:$1|Удзельнік «$1» не пазначыў|Удзельніца «$1» не пазначыла}} ніякага адрасу электроннай пошты.",
        "noemailcreate": "Вы павінны пазначыць слушны адрас электроннай пошты",
        "passwordsent": "Новы пароль быў дасланы на адрас электроннай пошты ўдзельніка «$1».\nКалі ласка, увайдзіце ў сыстэму пасьля яго атрыманьня.",
-       "blocked-mailpassword": "З Вашага IP-адрасу забароненыя рэдагаваньні, а таму таксама для прадухіленьня шкоды недаступная функцыя аднаўленьня паролю.",
+       "blocked-mailpassword": "З Вашага IP-адрасу забароненыя рэдагаваньні. Каб пазьбегнуць злоўжываньняў, з гэтага IP-адрасу забаронена аднаўляць пароль.",
        "eauthentsent": "Пацьверджаньне было дасланае на пазначаны адрас электроннай пошты.\nУ лісьце ўтрымліваюцца інструкцыі, па выкананьні якіх Вы зможаце пацьвердзіць, што адрас сапраўды належыць Вам, і на гэты адрас будзе дасылацца пошта адсюль.",
        "throttled-mailpassword": "Ліст пра скіданьне паролю ўжо было даслана за {{PLURAL:$1|$1 апошнюю гадзіну|$1 апошнія гадзіны|$1 апошніх гадзінаў}}.\nДля прадухіленьня злоўжываньняў напамін будзе дасылацца не часьцей як аднойчы ў $1 {{PLURAL:$1|гадзіну|гадзіны|гадзінаў}}.",
        "mailerror": "Памылка пры адпраўцы электроннай пошты: $1",
        "newpassword": "Новы пароль:",
        "retypenew": "Паўтарыце новы пароль:",
        "resetpass_submit": "Захаваць пароль і ўвайсьці",
-       "changepassword-success": "Ð\92аÑ\88 Ð¿Ð°Ñ\80олÑ\8c Ð±Ñ\8bÑ\9e Ð¿Ð°Ñ\81Ñ\8cпÑ\8fÑ\85ова Ð·Ñ\8cмененÑ\8b!",
+       "changepassword-success": "Ваш пароль быў зьменены!",
        "changepassword-throttled": "Вы зрабілі зашмат спробаў увайсьці ў сыстэму.\nКалі ласка, пачакайце $1 перад наступнай спробай.",
        "botpasswords": "Паролі робатаў",
        "botpasswords-summary": "<em>Паролі робатаў</em> дазваляюць доступ да рахунку ўдзельніка праз API без выкарыстаньня лагіну і паролю асноўнага рахунку. Правы ўдзельніка пры выкарыстаньні паролю робата могуць быць абмежаваныя.\n\nКалі вы ня ведаеце, навошта вам гэта, мабыць, не рабіце гэтага. Ніхто не павінен прасіць вас згенэраваць такі пароль і перадаць гэты пароль яму.",
        "botpasswords-insert-failed": "Не атрымалася дадаць робата зь імем «$1». Магчыма, ён ужо быў дададзены?",
        "botpasswords-update-failed": "Не атрымалася абнавіць робата зь імем «$1». Магчыма, ён быў выдалены?",
        "botpasswords-created-title": "Пароль робата створаны",
-       "botpasswords-created-body": "Пароль робата «$1» быў пасьпяхова створаны.",
+       "botpasswords-created-body": "Пароль робата для робата з назвай «$1» удзельніка «$2» быў створаны.",
        "botpasswords-updated-title": "Пароль робата абноўлены",
-       "botpasswords-updated-body": "Пароль робата «$1» быў пасьпяхова абноўлены.",
+       "botpasswords-updated-body": "Пароль робата для робата «$1» удзельніка «$2» быў абноўлены.",
        "botpasswords-deleted-title": "Пароль робата выдалены",
-       "botpasswords-deleted-body": "Пароль робата «$1» быў выдалены.",
+       "botpasswords-deleted-body": "Пароль робата для робата «$1» удзельніка «$2» быў выдалены.",
        "botpasswords-newpassword": "Новы пароль для ўваходу пад <strong>$1</strong> — <strong>$2</strong>. <em>Калі ласка, запішыце яго для далейшага выкарыстаньня.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider недаступны.",
        "botpasswords-restriction-failed": "Уваход ня выкананы праз абмежаваньні на пароль робата",
        "resetpass-no-info": "Для непасрэднага доступу да гэтай старонкі Вам неабходна ўвайсьці ў сыстэму.",
        "resetpass-submit-loggedin": "Зьмяніць пароль",
        "resetpass-submit-cancel": "Скасаваць",
-       "resetpass-wrong-oldpass": "Няслушны часовы альбо цяперашні пароль.\nМагчыма Вы ўжо пасьпяхова зьмянілі Ваш пароль альбо запыталі новы часовы пароль.",
+       "resetpass-wrong-oldpass": "Няслушны часовы альбо цяперашні пароль.\nМагчыма, Вы ўжо пасьпяхова зьмянілі Ваш пароль альбо запыталі новы часовы пароль.",
        "resetpass-recycled": "Калі ласка, зьмяніце ваш пароль на нешта адрознае ад вашага цяперашняга паролю.",
        "resetpass-temp-emailed": "Вы ўвашлі з дапамогай часовага коду, які быў дасланы праз электронную пошту.\nКаб завершыць уваход, вы мусіце ўвесьці новы пароль:",
        "resetpass-temp-password": "Часовы пароль:",
        "revdelete-unsuppress": "Зьняць абмежаваньні з адноўленых вэрсіяў",
        "revdelete-log": "Прычына:",
        "revdelete-submit": "Ужыць для {{PLURAL:$1|1=выбранай вэрсіі|выбраных вэрсіяў}}",
-       "revdelete-success": "'''Бачнасьць вэрсіі пасьпяхова абноўленая.'''",
+       "revdelete-success": "Бачнасьць вэрсіі абноўленая.",
        "revdelete-failure": "'''Немагчыма абнавіць бачнасьць вэрсіі:'''\n$1",
-       "logdelete-success": "'''Бачнасьць падзеі пасьпяхова зьмененая.'''",
+       "logdelete-success": "Бачнасьць падзеі ўсталяваная.",
        "logdelete-failure": "'''Немагчыма ўстанавіць бачнасьць у журнале:'''\n$1",
        "revdel-restore": "Зьмяніць бачнасьць",
        "pagehist": "Гісторыя старонкі",
        "revertmerge": "Разьяднаць",
        "mergelogpagetext": "Ніжэй знаходзіцца сьпіс апошніх аб'яднаньняў гісторыяў старонак.",
        "history-title": "$1 — гісторыя зьменаў",
-       "difference-title": "$1: розьніца паміж вэрсіямі",
+       "difference-title": "Розьніца паміж вэрсіямі «$1»",
        "difference-title-multipage": "«$1» і «$2» — розьніца паміж старонкамі",
        "difference-multipage": "(Розьніца паміж старонкамі)",
        "lineno": "Радок $1:",
        "userrights-changeable-col": "Групы, якія Вы можаце мяняць",
        "userrights-unchangeable-col": "Групы, якія Вы ня можаце мяняць",
        "userrights-conflict": "Канфлікт пры зьмене правоў удзельнікаў! Калі ласка, праверце і захавайце вашыя зьмены.",
-       "userrights-removed-self": "Вы пасьпяхова пазбавілі сябе ўласных правоў. З гэтай прычыны вы больш ня маеце доступу да гэтай старонкі.",
+       "userrights-removed-self": "Вы пазбавілі сябе ўласных правоў. З гэтай прычыны вы больш ня маеце доступу да гэтай старонкі.",
        "group": "Група:",
        "group-user": "Удзельнікі",
        "group-autoconfirmed": "Аўтаматычна пацьверджаныя ўдзельнікі",
        "right-applychangetags": "дадаваць [[Special:Tags|меткі]] пры рэдагаваньні",
        "right-changetags": "дадаваць і выдаляць адвольныя [[Special:Tags|меткі]] да асобных вэрсіяў і запісаў у журнале падзеяў",
        "grant-generic": "Набор правоў «$1»",
-       "grant-group-page-interaction": "Узаемадзеньне з старонкамі",
+       "grant-group-page-interaction": "Узаемадзеяньне з старонкамі",
        "grant-group-file-interaction": "Узаемадзеяньне з мэдыяфайламі",
        "grant-group-watchlist-interaction": "Узаемадзеяньне з вашым сьпісам назіраньня",
        "grant-group-email": "Адпраўка лістоў электроннай пошты",
        "grant-rollback": "Адкат зьменаў старонак",
        "grant-sendemail": "Адпраўка лістоў электроннай пошты іншым удзельнікам",
        "grant-uploadeditmovefile": "Загрузка, замена і перайменаваньне файлаў",
+       "grant-uploadfile": "Загрузка новых файлаў",
+       "grant-basic": "Асноўныя правы",
+       "grant-viewdeleted": "Прагляд выдаленых файлаў і старонак",
+       "grant-viewmywatchlist": "Прагляд вашага сьпісу назіраньня",
        "newuserlogpage": "Журнал стварэньня рахункаў",
        "newuserlogpagetext": "Гэта журнал стварэньня рахункаў удзельнікаў і ўдзельніц.",
        "rightslog": "Журнал правоў удзельнікаў",
        "action-createpage": "стварэньне старонак",
        "action-createtalk": "стварэньне старонак абмеркаваньняў",
        "action-createaccount": "стварэньне гэтага рахунку ўдзельніка",
+       "action-autocreateaccount": "аўтаматычнае стварэньне гэтага рахунку вонкавага ўдзельніка",
        "action-history": "прагляд гісторыі гэтай старонкі",
        "action-minoredit": "пазначэньне гэтай праўкі як дробнай",
        "action-move": "перанос гэтай старонкі",
        "recentchangeslinked-page": "Назва старонкі:",
        "recentchangeslinked-to": "Замест гэтага паказваць зьмены на старонках, што спасылаюцца на гэтую старонку",
        "recentchanges-page-added-to-category": "[[:$1]] дададзеная да катэгорыі",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] і яшчэ {{PLURAL:$2|$2 старонка была дададзеная|$2 старонкі былі дададзеныя|$2 старонак былі дададзеныя}} да катэгорыі",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] і яшчэ [[Special:WhatLinksHere/$1|{{PLURAL:$2|$2 старонка была дададзеная|$2 старонкі былі дададзеныя|$2 старонак былі дададзеныя}}]] да катэгорыі",
        "recentchanges-page-removed-from-category": "[[:$1]] выдаленая з катэгорыі",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] і яшчэ $2 {{PLURAL:$2|старонка была выдаленая|старонкі былі выдаленыя|старонак былі выдаленыя}} з катэгорыі",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] і яшчэ [[Special:WhatLinksHere/$1|$2 {{PLURAL:$2|старонка была выдаленая|старонкі былі выдаленыя|старонак былі выдаленыя}}]] з катэгорыі",
        "autochange-username": "Аўтаматычная зьмена MediaWiki",
        "upload": "Загрузіць файл",
        "uploadbtn": "Загрузіць файл",
        "uploaded-script-svg": "У загружаным SVG-файле знойдзены небясьпечны элемэнт з падтрымкай сцэнароў «$1».",
        "uploaded-hostile-svg": "Знойдзены небясьпечны CSS у элемэнце стылю загружанага SVG-файла.",
        "uploaded-event-handler-on-svg": "Усталёўваць атрыбуты апрацоўніка падзеяў <code>$1=\"$2\"</code> не дазволена для SVG-файлаў.",
+       "uploaded-href-attribute-svg": "href-атрыбутам у SVG-файлах дазволена весьці толькі на http:// ці https://, знойдзена <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploaded-href-unsafe-target-svg": "У загружаным SVG-файле знойдзеная спасылка на небясьпечныя зьвесткі: URI-мэты <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploaded-animate-svg": "У загружаным SVG-файле знойдзены тэг «animate», які можа зьмяняць спасылку з дапамогай атрыбуту «from» <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploaded-setting-event-handler-svg": "Усталёўка атрыбутаў апрацоўкі падзеяў заблякаваная, у загружаным SVG-файле знойдзены код <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "upload-too-many-redirects": "URL-адрас утрымлівае зашмат перанакіраваньняў",
        "upload-http-error": "Узьнікла памылка HTTP: $1",
        "upload-copy-upload-invalid-domain": "Капіяваньне загрузак не дазволенае ў гэтым дамэне.",
+       "upload-foreign-cant-upload": "Гэтая вікі не наладжаная для загрузкі файлаў у запытанае вонкавае сховішча файлаў.",
        "upload-dialog-title": "Загрузка файла",
        "upload-dialog-button-cancel": "Адмяніць",
        "upload-dialog-button-done": "Зроблена",
        "uploadstash-summary": "Гэтая старонка прадстаўляе доступ да файлаў, якія загружаныя (ці знаходзяцца ў працэсе загрузкі), але яшчэ не апублікаваныя ў {{GRAMMAR:месны|{{SITENAME}}}}. Гэтыя файлы нябачныя нікому, акрамя ўдзельнікаў, якія іх загрузілі.",
        "uploadstash-clear": "Ачысьціць схаваныя файлы",
        "uploadstash-nofiles": "Вы ня маеце схаваных файлаў.",
-       "uploadstash-badtoken": "Немагчыма выканаць гэтае дзеяньне, верагодна скончыўся тэрмін дзеяньня Вашага дазволу на рэдагаваньне. Паспрабуйце зноў.",
-       "uploadstash-errclear": "Немагчыма ачысьціць файлы.",
+       "uploadstash-badtoken": "Не атрымалася выканаць гэтае дзеяньне. Верагодна, скончыўся тэрмін дзеяньня вашых уліковых зьвестак. Калі ласка, паспрабуйце зноў.",
+       "uploadstash-errclear": "Не атрымалася ачысьціць файлы.",
        "uploadstash-refresh": "Абнавіць сьпіс файлаў.",
+       "uploadstash-thumbnail": "прагляд мініятуры",
        "invalid-chunk-offset": "Няслушнае зрушэньне фрагмэнту",
        "img-auth-accessdenied": "Доступ забаронены",
        "img-auth-nopathinfo": "Адсутнічае PATH_INFO.\nВаш сэрвэр не ўстаноўлены на пропуск гэтай інфармацыі.\nМагчма, ён працуе праз CGI і не падтрымлівае img_auth.\nГлядзіце https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "apihelp": "Даведка API",
        "apihelp-no-such-module": "Модуль «$1» ня знойдзены.",
        "apisandbox": "Пясочніца API",
+       "apisandbox-jsonly": "Для выкарыстаньня API-пясочніцы патрэбны JavaScript.",
        "apisandbox-api-disabled": "API забаронены на гэтым сайце.",
        "apisandbox-intro": "Выкарыстоўвайце гэтую старонку для экспэрымэнтаў з <strong>API вэб-сэрвісу MediaWiki</strong>.\nЗьвяртайцеся да [[mw:API:Main page|дакумэнтацыі API]] для дадатковай інфармацыі па выкарыстаньні API. Напрыклад, [//www.mediawiki.org/wiki/API#A_simple_example як атрымаць зьмест галоўнай старонкі]. Абярыце дзеяньне, каб пабачыць болей узораў.\n\nЗьвярніце ўвагу, што нягледзячы на тое, што гэта пясочніца, вашыя дзеяньні могуць унесьці зьмены ў вікі.",
+       "apisandbox-fullscreen": "Разгарнуць панэль",
+       "apisandbox-fullscreen-tooltip": "Разгарнуць панэль пясочніцы, каб запоўніць акно браўзэра.",
+       "apisandbox-unfullscreen": "Паказаць старонку",
+       "apisandbox-unfullscreen-tooltip": "Паменшыць панэль пясочніцы, каб былі даступныя навігацыйныя спасылкі MediaWiki.",
        "apisandbox-submit": "Зрабіць запыт",
        "apisandbox-reset": "Ачысьціць",
+       "apisandbox-retry": "Паўтарыць",
+       "apisandbox-loading": "Загрузка інфармацыі для API-модуля «$1»…",
+       "apisandbox-load-error": "Пры загрузцы інфармацыі для API-модуля «$1» адбылася памылка: $2",
+       "apisandbox-no-parameters": "Гэты API-модуль ня мае парамэтраў.",
        "apisandbox-examples": "Прыклады",
        "apisandbox-results": "Вынікі",
        "apisandbox-request-url-label": "URL-адрас запыту:",
        "log-title-wildcard": "Шукаць назвы, якія пачынаюцца з гэтага тэксту",
        "showhideselectedlogentries": "Паказаць/схаваць выбраныя запісы ў журнале",
        "log-edit-tags": "Рэдагаваць меткі да абраных запісаў у журнале падзеяў",
-       "checkbox-all": "Усе",
+       "checkbox-select": "Выбраць: $1",
+       "checkbox-all": "усе",
+       "checkbox-none": "нічога",
+       "checkbox-invert": "адваротна",
        "allpages": "Усе старонкі",
        "nextpage": "Наступная старонка ($1)",
        "prevpage": "Папярэдняя старонка ($1)",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|вэрсія імпартаваная|вэрсіі імпартаваныя|вэрсіяў імпартаваныя}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|вэрсія імпартаваная|вэрсіі імпартаваныя|вэрсіяў імпартаваныя}} з $2",
        "javascripttest": "Тэставаньне JavaScript",
-       "javascripttest-pagetext-noframework": "Гэтая старонка трымаецца для правядзеньня тэстаў JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Невядомая бібліятэка тэставаньня «$1».",
        "javascripttest-pagetext-unknownaction": "Невядомае дзеяньне «$1».",
-       "javascripttest-pagetext-frameworks": "Калі ласка, выберыце адну з прапанаваных бібліятэка тэставаньня: $1",
-       "javascripttest-pagetext-skins": "Выберыце афармленьне для тэставаньня:",
        "javascripttest-qunit-intro": "Глядзіце [$1 дакумэнтацыю па тэставаньні] на mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Вашая ўласная}} старонка",
        "tooltip-pt-anonuserpage": "Старонка ўдзельніка для IP-адрасу, зь якога Вы рэдагуеце",
        "version-libraries-description": "Апісаньне",
        "version-libraries-authors": "Аўтары",
        "redirect": "Перанакіраваньне да файла, удзельніка, старонкі, вэрсіі або журнала",
-       "redirect-legend": "Перанакіраваньне да файла або старонкі",
        "redirect-summary": "Гэтая спэцыяльная старонка перанакіруе да файла (паводле імя файла), старонкі (паводле нумару вэрсіі або старонкі), старонкі ўдзельніка (паводле нумару ўдзельніка) або запісу ў журнале падзеяў (паводле нумару ў журнале). Ужываньне: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]],[[{{#Special:Redirect}}/user/101]] або [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Перайсьці",
        "redirect-lookup": "Шукаць паводле:",
        "tags-delete-not-allowed": "Меткі, вызначаныя пашырэньнем, ня могуць быць выдаленыя, акрамя выпадку, калі пашырэньне дазваляе гэта.",
        "tags-delete-not-found": "Метка «$1» не існуе.",
        "tags-delete-too-many-uses": "Метка «$1» выкарыстаная ў больш чым $2 {{PLURAL:$2|вэрсіі|вэрсіях}}, адпаведна, яна ня можа быць выдаленая.",
-       "tags-delete-warnings-after-delete": "Ð\9cеÑ\82ка Â«$1» Ð±Ñ\8bла Ð¿Ð°Ñ\81Ñ\8cпÑ\8fÑ\85ова Ð²Ñ\8bдаленаÑ\8f, Ð°Ð»Ðµ {{PLURAL:$2|1=аÑ\82Ñ\80Ñ\8bманае Ð½Ð°Ñ\81Ñ\82Ñ\83пнае Ð¿Ð°Ð¿Ñ\8fÑ\80Ñ\8dджанÑ\8cне|аÑ\82Ñ\80Ñ\8bманÑ\8bÑ\8f Ð½Ð°Ñ\81Ñ\82Ñ\83пнÑ\8bÑ\8f Ð¿Ð°Ð¿Ñ\8fÑ\80Ñ\8dджанÑ\8cнÑ\96}}:",
+       "tags-delete-warnings-after-delete": "Метка «$1» была выдаленая, але {{PLURAL:$2|1=атрыманае наступнае папярэджаньне|атрыманыя наступныя папярэджаньні}}:",
        "tags-activate-title": "Актываваць метку",
        "tags-activate-question": "Вы зьбіраецеся актываваць метку «$1».",
        "tags-activate-reason": "Прычына:",
        "tags-edit-reason": "Прычына:",
        "tags-edit-revision-submit": "Дастасаваць зьмены да {{PLURAL:$1|1=гэтай вэрсіі|$1 вэрсіяў}}",
        "tags-edit-logentry-submit": "Дастасаваць зьмены да {{PLURAL:$1|$1 журнальнага запісу|$1 журнальных запісаў}}",
-       "tags-edit-success": "Ð\97Ñ\8cменÑ\8b Ð±Ñ\8bлÑ\96 Ð¿Ð°Ñ\81Ñ\8cпÑ\8fÑ\85ова Ð´Ð°Ñ\81Ñ\82аÑ\81аванÑ\8bÑ\8f.",
+       "tags-edit-success": "Зьмены былі дастасаваныя.",
        "tags-edit-failure": "Гэтыя зьмены ня могуць быць дастасаваныя:\n$1",
        "tags-edit-nooldid-title": "Няслушная мэтавая вэрсія",
        "tags-edit-nooldid-text": "Вы або не пазначылі мэтавую вэрсію для выкананьня гэтай функцыі, або пазначаная вэрсія не існуе.",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|абараніў|абараніла}} $3 $4 [каскадна]",
        "logentry-protect-modify": "$1 {{GENDER:$2|зьмяніў узровень|зьмяніла ўзровень}} абароны для $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|зьмяніў узровень|зьмяніла ўзровень}} абароны для $3 $4 [каскадна]",
-       "logentry-rights-rights": "$1 {{GENDER:$1|зьмяніў|зьмяніла}} прыналежнасьць $3 да групы з $4 на $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} прыналежнасьць {{GENDER:$3|$3}} да групы з $4 на $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$1|зьмяніў|зьмяніла}} прыналежнасьць $3 да групаў",
        "logentry-rights-autopromote": "$1 {{GENDER:$1|быў аўтаматычна пераведзены|была аўтаматычна пераведзеная}} з групы $4 ў $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|загрузіў|загрузіла}} $3",
index fed9035..2fbe6cc 100644 (file)
@@ -25,7 +25,8 @@
                        "Artificial123",
                        "Macofe",
                        "Matma Rex",
-                       "Goshaproject"
+                       "Goshaproject",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Падкрэсліваць спасылкі:",
        "botpasswords-insert-failed": "Не ўдалося дадаць робату назву \"$1\". Магчыма, яна ўжо дададзена?",
        "botpasswords-update-failed": "Не ўдалося змяніць робату назву \"$1\". Можа, яна сцёртая?",
        "botpasswords-created-title": "Пароль робата створаны",
-       "botpasswords-created-body": "Пароль для робата \"$1\" паспяхова створаны.",
+       "botpasswords-created-body": "Пароль для робата \"$1\" удзельніка \"$2\" паспяхова створаны.",
        "botpasswords-updated-title": "Пароль робата абноўлены",
-       "botpasswords-updated-body": "Пароль для робата \"$1\" паспяхова абноўлены.",
+       "botpasswords-updated-body": "Пароль для робата \"$1\" удзельніка \"$2\" паспяхова абноўлены.",
        "botpasswords-deleted-title": "Пароль робата сцёрты",
-       "botpasswords-deleted-body": "Пароль для робата \"$1\" паспяхова сцёрты.",
+       "botpasswords-deleted-body": "Пароль для робата \"$1\" удзельніка \"$2\" паспяхова сцёрты.",
+       "botpasswords-newpassword": "Новы пароль для ўваходу пад <strong>$1</strong> — <strong>$2</strong>. <em>Калі ласка, запішыце яго для выкарыстання ў будучыні.</em>",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider недаступны.",
+       "botpasswords-restriction-failed": "Уваход не выкананы з-за абмежаванняў на пароль робата.",
+       "botpasswords-invalid-name": "Паказанае імя ўдзельніка не ўтрымлівае падзяляльнік паролю робата (\"$1\").",
+       "botpasswords-not-exist": "Удзельнік \"$1\" не мае паролю для робата з назвай \"$2\".",
        "resetpass_forbidden": "Не дазволена мяняць паролі",
        "resetpass-no-info": "Трэба ўвайсці ў сістэму, каб звяртацца да гэтай старонкі наўпрост.",
        "resetpass-submit-loggedin": "Змяніць пароль",
        "anoneditwarning": "<strong>Увага!</strong> Вы не аўтарызаваліся на сайце. Ваш IP-адрас будзе публічна бачным, калі вы будзеце ўносіць любыя праўкі. Калі вы <strong>[$1 ўвойдзеце]</strong> ці <strong>[$2 створыце ўліковы запіс]</strong>, праўкі замест гэтага будуць звязаны з вашым імем карыстальніка, а таксама ў вас з'явяцца іншыя перавагі.",
        "anonpreviewwarning": "''Вы не прайшлі ідэнтыфікацыю Захаванне будзе запісана з вашым IP адрасам у гісторыі правак гэтай старонкі.''",
        "missingsummary": "<strong>Нагадваем:</strong> вы не ўпісалі тлумачэння для сваёй праўкі. Калі націснуць \"{{int:savearticle}}\" яшчэ раз, праўка будзе замацавана без тлумачэння.",
+       "selfredirect": "<strong>Увага:</strong> Вы перанакіроўваеце старонку на самую сябе.\nМагчыма, вы ўказалі няправільную мэту перанакіравання, ці правіце не тую старонку.\nКалі націсніце \"{{int:savearticle}}\" ізноў, перанакіраванне ўсё ж будзе створана.",
        "missingcommenttext": "Калі ласка, увядзіце ніжэй каментарый.",
        "missingcommentheader": "'''Напамінанне:''' вы нічога не ўпісалі ў тэму/загаловак гэтай заўвагі.\nПры паўторным націсканні кнопкі '{{int:savearticle}}' ваша праўка будзе запісана з пустым загалоўкам.",
        "summary-preview": "Перадпаказ апісання:",
        "subject-preview": "Перадпаказ тэмы/загалоўка:",
+       "previewerrortext": "Здарылася памылка пры спробе папярэдняга прагляду вашых змяненняў.",
        "blockedtitle": "Удзельнік заблакаваны",
        "blockedtext": "'''Ваша імя ўдзельніка або адрас IP былі пастаўлены пад блок.'''\n\nБлок быў пастаўлены ўдзельнікам: $1. Пададзеная прычына: ''$2''.\n\n* Блок пастаўлены: $8\n* Блок канчаецца: $6\n* Атрымальнік блока: $7\n\nВы можаце звярнуцца да $1 або да аднаго з іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб паразмаўляць пра гэты блок.\nВы не зможаце дзеля гэтага карыстацца функцыяй ''{{:{{ns:mediawiki}}:emailuser/be}}'', калі гэта вам забаронена, або калі вы не наставілі правільнага пацверджанага адрасу эл.пошты ў сваіх [[Special:Preferences|настаўленнях]].\nВаш адрас IP: $3, нумар блоку: #$5. Падавайце ўсе гэтыя звесткі ў кожным сваім звароце адносна гэтага блоку.",
        "autoblockedtext": "Ваш адрас IP быў аўтаматычна заблакаваны, таму што ім карыстаўся ўдзельнік, заблакаваны адміністратарам $1.\nПададзеная прычына блоку:\n\n:''$2''\n\n* Блок пастаўлены: $8\n* Блок канчаецца: $6\n* Атрымальнік блоку: $7\n\nВы можаце звярнуцца да $1 або да аднаго з іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб паразмаўляць пра гэты блок.\n\nВы не зможаце дзеля гэтага карыстацца функцыяй ''{{:{{ns:mediawiki}}:emailuser/be}}'', калі гэта вам забаронена, або калі вы не наставілі правільнага пацверджанага адрасу эл.пошты ў сваіх [[Special:Preferences|настаўленнях]].\n\nВаш адрас IP: $3. Ваш нумар блоку: $5. Падавайце ўсе гэтыя звесткі ў кожным сваім звароце адносна гэтага блоку.",
        "previewnote": "<strong>Памятайце, гэта толькі папярэдні паказ.</strong> Праўкі яшчэ не замацаваныя!",
        "continue-editing": "Працягнуць рэдагаванне",
        "previewconflict": "Гэта папярэдні паказ магчымага выніку замацоўвання актуальнага стану крынічнага тэксту ў верхнім тэкставым полі.",
-       "session_fail_preview": "'''Не ўдалося апрацаваць вашу праўку, таму што сервер згубіў звесткі аб вашым сеансе.\nПаспрабуйце, калі ласка, ізноў.\nКалі і тады не атрымаецца, паспрабуйце [[Special:UserLogout|выйсці з сістэмы]] і зайсці ізноў.'''",
-       "session_fail_preview_html": "'''Не ўдалося апрацаваць вашу праўку з-за таго, што згубіліся даныя аб сеансе.'''\n\n''Перадпаказ не зроблены, бо на пляцоўцы {{SITENAME}} дазволены сыры код HTML, што робіць магчымымі атакі праз Яваскрыпт.''\n\n'''Калі гэта нармальная спроба праўкі, паспрабуйце паўтарыць запісванне. Калі і гэта не дапаможа, паспрабуйце [[Special:UserLogout|выйсці з сістэмы]] і ўвайсці ізноў.'''",
+       "session_fail_preview": "Не ўдалося апрацаваць вашу праўку, таму што сервер згубіў звесткі аб вашым сеансе.\n\nМагчыма, вы выйшлі з сістэмы. <strong>Калі ласка, праверце, што вы ўвайшлі ў сістэму і паспрабуйце яшчэ раз.</strong>\nКалі і тады не атрымаецца, паспрабуйце [[Special:UserLogout|выйсці з сістэмы]] і зайсці ізноў, таксама праверце, што ваш браўзер дазваляе кукі з гэтага сайта.",
+       "session_fail_preview_html": "Не ўдалося апрацаваць вашу праўку з-за таго, што згубіліся даныя аб сеансе.\n\n<em>Перадпаказ не зроблены, бо на пляцоўцы {{SITENAME}} дазволены сыры код HTML, што робіць магчымымі атакі праз Яваскрыпт.</em>\n\n<strong>Калі гэта нармальная спроба праўкі, паспрабуйце паўтарыць запісванне.</strong>\nКалі і гэта не дапаможа, паспрабуйце [[Special:UserLogout|выйсці з сістэмы]] і ўвайсці ізноў, таксама праверце, што ваш браўзер дазваляе кукі з гэтага сайта.",
        "token_suffix_mismatch": "'''Ваша праўка была адхілена, каб пазбегнуць сапсавання тэксту старонкі, таму што ваш браўзер папсаваў знакі прыпынку ў квітку праўкі.\nМагчыма, прычына ў выкарыстанні вамі ананімнага проксі-сервера, праграмы якога працуюць некарэктна.'''",
        "edit_form_incomplete": "'''Некаторыя часткі формы рэдагавання не дасягнулі сервера. Упэўніцеся, што Вашыя рэдагаванні не пашкоджаныя і паспрабуйце зноў.'''",
        "editing": "Правім $1",
        "yourdiff": "Адрозненні",
        "copyrightwarning": "Заўважце, што ўсе ўклады на {{SITENAME}} лічацца выданымі на ўмовах $2 (бач падрабязнасці на $1). Калі вы не жадаеце, каб вашыя матэрыялы бязлітасна правіліся, і свабодна распаўсюджваліся, то і не аддавайце іх сюды.<br />\nТаксама вы нам абяцаеце, што напісалі гэта самі, або скапіравалі з рэсурсу, які знаходзіцца ў публічнай уласнасці, або з аналагічнага свабоднага рэсурсу.\n'''НЕ КЛАДЗІЦЕ СЮДЫ, БЕЗ АДПАВЕДНАГА ДАЗВОЛУ, МАТЭРЫЯЛУ, ЯКІ АХОЎВАЕЦЦА АЎТАРСКІМ ПРАВАМ!'''",
        "copyrightwarning2": "Заўважце, што кожны ўклад на {{SITENAME}} можа быць папраўлены, зменены або выдалены іншымі ўдзельнікамі. Калі вы не жадаеце, каб вашыя матэрыялы бязлітасна правіліся, то і не давайце іх сюды.<br />\nТаксама вы нам абяцаеце, што напісалі гэта самі, або скапіравалі з рэсурсу, які знаходзіцца ў публічнай уласнасці, або з аналагічнага свабоднага рэсурсу (бач падрабязнасці на $1).\n'''НЕ КЛАДЗІЦЕ СЮДЫ, БЕЗ АДПАВЕДНАГА ДАЗВОЛУ, МАТЭРЫЯЛУ, ЯКІ АХОЎВАЕЦЦА АЎТАРСКІМ ПРАВАМ!'''",
+       "editpage-cannot-use-custom-model": "Мадэль зместу гэтай старонкі не можа быць зменена.",
        "longpageerror": "'''Памылка: Аб’ём тэксту, які Вы спрабуеце запісаць складае $1 {{PLURAL:$1|кілабайт|кілабайты|кілабайтаў}}, што болей устаноўленага абмежавання на $2 {{PLURAL:$2|кілабайт|кілабайты|кілабайтаў}}.'''\nСтаронка не можа быць захаваная.",
-       "readonlywarning": "<strong>Увага: Ð·Ð°Ñ\80аз Ð²Ñ\8b Ð½Ðµ Ð¼Ð¾Ð¶Ð°Ñ\86е Ð·Ð°Ð¿Ñ\96Ñ\81аÑ\86Ñ\8c Ñ\81вае Ð¿Ñ\80аÑ\9eкÑ\96, Ñ\82амÑ\83 Ñ\88Ñ\82о Ð±Ð°Ð·Ð° Ð·Ð²ÐµÑ\81Ñ\82ак Ð·Ð°Ñ\87Ñ\8bнена Ð½Ð° Ð°Ð±Ñ\81лÑ\83гоÑ\9eванне.</strong>\nÐ\9cагÑ\87Ñ\8bма, Ð²Ð°Ñ\80Ñ\82а Ð¿ÐµÑ\80анеÑ\81Ñ\86Ñ\96 Ð²Ð°Ñ\88 Ñ\82Ñ\8dкÑ\81Ñ\82 Ñ\83 Ð°Ñ\81обнÑ\8b Ñ\84айл Ñ\96 Ð·Ð°Ð¿Ñ\96Ñ\81аÑ\86Ñ\8c Ð½Ð° Ð¿Ð¾Ñ\82Ñ\8bм.\n\nÐ\90дміністратар, які зачыніў базу, растлумачыў гэта так: $1",
+       "readonlywarning": "<strong>Увага: Ð·Ð°Ñ\80аз Ð²Ñ\8b Ð½Ðµ Ð¼Ð¾Ð¶Ð°Ñ\86е Ð·Ð°Ð¿Ñ\96Ñ\81аÑ\86Ñ\8c Ñ\81вае Ð¿Ñ\80аÑ\9eкÑ\96, Ñ\82амÑ\83 Ñ\88Ñ\82о Ð±Ð°Ð·Ð° Ð·Ð²ÐµÑ\81Ñ\82ак Ð·Ð°Ñ\87Ñ\8bнена Ð½Ð° Ð°Ð±Ñ\81лÑ\83гоÑ\9eванне.</strong>\nÐ\9cагÑ\87Ñ\8bма, Ð²Ð°Ñ\80Ñ\82а Ð¿ÐµÑ\80анеÑ\81Ñ\86Ñ\96 Ð²Ð°Ñ\88 Ñ\82Ñ\8dкÑ\81Ñ\82 Ñ\83 Ð°Ñ\81обнÑ\8b Ñ\84айл Ñ\96 Ð·Ð°Ð¿Ñ\96Ñ\81аÑ\86Ñ\8c Ð½Ð° Ð¿Ð¾Ñ\82Ñ\8bм.\n\nСÑ\96Ñ\81Ñ\82Ñ\8dмнÑ\8b Ð°дміністратар, які зачыніў базу, растлумачыў гэта так: $1",
        "protectedpagewarning": "'''УВАГА: старонка пастаўлена пад ахову, таму яе могуць правіць толькі адміністратары.'''\nНіжэй паказаны апошні запіс з адпаведнага журнала:",
        "semiprotectedpagewarning": "'''Увага:''' старонка пастаўлена пад ахову, таму яе могуць правіць толькі зарэгістраваныя ўдзельнікі («паў-ахова»). Ніжэй паказаны апошні запіс з адпаведнага журнала:",
-       "cascadeprotectedwarning": "'''Увага:''' гэтая старонка ахоўваецца, таму яе могуць правіць толькі ўдзельнікі з правамі адміністратара. Прычына аховы: улучэнне гэтай старонкі ў {{PLURAL:$1|старонку, якая стаіць|старонкі, якія стаяць}} пад каскаднай аховай:",
+       "cascadeprotectedwarning": "<strong>Увага:</strong> гэтая старонка ахоўваецца, таму яе могуць правіць толькі ўдзельнікі з правамі адміністратара. Прычына аховы: улучэнне гэтай старонкі ў {{PLURAL:$1|старонку, якая стаіць|старонкі, якія стаяць}} пад каскаднай аховай:",
        "titleprotectedwarning": "'''УВАГА: старонка пастаўлена пад ахову, таму яе могуць ствараць толькі ўдзельнікі з [[Special:ListGroupRights|адмысловымі правамі]].'''\nНіжэй паказаны апошні запіс з адпаведнага журнала:",
        "templatesused": "Шабло{{PLURAL:$1|н|ны}} на гэтай старонцы:",
        "templatesusedpreview": "Шабло{{PLURAL:$1|н у|ны ў}} гэтым перадпаказе:",
        "permissionserrors": "Памылка доступу",
        "permissionserrorstext": "Вам не дазволена гэтага рабіць, з наступн{{PLURAL:$1|ай прычыны|ых прычын}}:",
        "permissionserrorstext-withaction": "Вам не дазволена $2, з-за наступ{{PLURAL:$1|най прычыны|ных прычын}}:",
+       "contentmodelediterror": "Вы не можаце правіць гэту версію, таму што яе мадэль зместу — <code>$1</code>, што адрозніваецца ад цяперашняй мадэлі зместу старонкі, <code>$2</code>.",
        "recreate-moveddeleted-warn": "<strong>Увага: Вы аднаўляеце старонку, якая раней была сцёрта.</strong>\n\nТрэба падумаць, ці варта далей працаваць з гэтай старонкай.\nВось журнал сціранняў і пераносаў для гэтай старонкі:",
        "moveddeleted-notice": "Гэтая старонка была сцёртая.\nНіжэй паказаны журнал сціранняў і пераносаў для гэтай старонкі.",
+       "moveddeleted-notice-recent": "Выбачайце, гэта старонка была нядаўна сцёрта (цягам апошніх 24 гадзін).\nЖурналы сціранняў і пераносаў для гэтай старонкі пададзены ніжэй для даведкі.",
        "log-fulllog": "Паглядзець поўны лог",
        "edit-hook-aborted": "Праўка спынена хукам (hook).\nТлумачэнняў не было.",
        "edit-gone-missing": "Не ўдалося абнавіць старонку.\nЗдаецца, што яна была сцёртая.",
        "content-model-css": "CSS",
        "content-json-empty-object": "Пусты аб'ект",
        "content-json-empty-array": "Пусты масіў",
+       "duplicate-args-warning": "<strong>Увага:</strong> [[:$1]] выклікае [[:$2]] з больш чым адным значэннем для параметра \"$3\". Толькі апошняе з пададзеных значэнняў будзе ўжытае.",
+       "duplicate-args-category": "Старонкі, якія выкарыстоўваюць задубляваныя параметры ў шаблонах",
+       "duplicate-args-category-desc": "Старонка ўтрымлівае шаблоны з задубляванымі параметрамі, напрыклад, <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> або <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "Увага: На старонцы занадта шмат працаёмістых зваротаў да парсера.\n\nТрэба, каб зваротаў было меней за $2, а зараз ёсць $1.<!--In this particular lingual case, there's no need for plurals at all, so let's make checker happy by adding commented out {{PLURAL:$2|call|calls}} and {{PLURAL:$1|is now $1 call|are now $1 calls}}-->",
        "expensive-parserfunction-category": "Старонкі, дзе шмат працаёмістых зваротаў да парсера",
        "post-expand-template-inclusion-warning": "Увага: аб'ём улучанага шаблона занадта вялікі.\nНекаторыя шаблоны не будуць улучаныя.",
        "history-feed-description": "Гісторыя версій гэтай старонкі",
        "history-feed-item-nocomment": "$1 на $2",
        "history-feed-empty": "Не знойдзена такая старонка.\nМагчыма, яна была сцёртая або названая іначай.\nПаспрабуйце [[Special:Search|пашукаць яе на гэтай Вікі]] сярод новых старонак.",
+       "history-edit-tags": "Правіць біркі абраных версій",
        "rev-deleted-comment": "(выдаленае кароткае апісанне змен)",
        "rev-deleted-user": "(удзельнік выдалены)",
        "rev-deleted-event": "(падрабязнасці з журнала сцёртыя)",
        "mergehistory-empty": "Няма версій, якія можна аб'яднаць.",
        "mergehistory-done": "$3 {{PLURAL:$3|версія|версій}} $1 паспяхова аб'яднаныя ў склад [[:$2]].",
        "mergehistory-fail": "Немагчыма аб'яднаць гісторыі, праверце зададзеныя назву і час.",
+       "mergehistory-fail-bad-timestamp": "Недапушчальная пазнака часу.",
+       "mergehistory-fail-invalid-source": "Недапушчальная старонка-крыніца.",
+       "mergehistory-fail-invalid-dest": "Недапушчальная старонка-мэта.",
+       "mergehistory-fail-no-change": "Пры аб'яднанні гісторыі ніводная версія не была аб'яднана. Калі ласка, праверце параметры старонкі і часу.",
+       "mergehistory-fail-permission": "Недастаткова правоў для аб'яднання гісторыі.",
+       "mergehistory-fail-self-merge": "Крынічная старонка і старонка-прызначэнне супадаюць.",
+       "mergehistory-fail-timestamps-overlap": "Крынічныя версіі перакрываюць або ідуць пасля версій прызначэння.",
        "mergehistory-fail-toobig": "Немагчыма аб'яднаць гісторыі правак, бо для гэтага трэба перанесці больш за ліміт у $1 {{PLURAL:$1|версію|версіі|версій}}.",
        "mergehistory-no-source": "Не існуе крынічная старонка $1.",
        "mergehistory-no-destination": "Не існуе мэтавая старонка $1.",
        "notextmatches": "Нічога не знойдзена ў тэкстах старонак",
        "prevn": "папярэдн. {{PLURAL:$1|$1}}",
        "nextn": "наступ. {{PLURAL:$1|$1}}",
+       "prev-page": "папярэдняя старонка",
+       "next-page": "наступная старонка",
        "prevn-title": "Папярэдні{{PLURAL:$1| вынік|я $1 вынікі(аў)}}",
        "nextn-title": "Наступны{{PLURAL:$1| вынік|я $1 вынікі(аў)}}",
        "shown-title": "Паказваць $1 {{PLURAL:$1|вынік|вынікі(аў)}} на старонку",
        "search-result-category-size": "{{PLURAL:$1|$1 элемент|$1 элемента|$1 элементаў}} ({{PLURAL:$2|$2 падкатэгорыя|$2 падкатэгорыі|$2 падкатэгорый}}, {{PLURAL:$3|$3 файл|$3 файла|$3 файлаў}})",
        "search-redirect": "(перасылка $1)",
        "search-section": "(падраздзел $1)",
+       "search-category": "(катэгорыя $1)",
        "search-file-match": "(адпавядае змесціву файла)",
        "search-suggest": "Ці хацелі вы сказаць: $1",
+       "search-rewritten": "Паказаны вынікі для $1. Замест гэтага шукаць $2.",
        "search-interwiki-caption": "Сумежныя праекты",
        "search-interwiki-default": "Вынікі з $1:",
        "search-interwiki-more": "(яшчэ)",
        "showingresultsinrange": "Ніжэй паказаны да {{PLURAL:$1|<strong>1</strong> выніку|<strong>$1</strong> вынікаў}} у дыяпазоне ад #<strong>$2</strong> да #<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|Вынік <strong>$1</strong> з <strong>$3</strong>|Вынікі <strong>$1 — $2</strong> з <strong>$3</strong>}}",
        "search-nonefound": "Нічога не было знойдзена.",
+       "search-nonefound-thiswiki": "Няма вынікаў, якія б адпавядалі такому запыту на гэтым сайце.",
        "powersearch-legend": "Падрабязны пошук",
        "powersearch-ns": "Шукаць у прасторах назваў:",
        "powersearch-togglelabel": "Пазначыць:",
        "prefs-personal": "Удзельнік",
        "prefs-rc": "{{:{{ns:mediawiki}}:Recentchanges/be}}",
        "prefs-watchlist": "Спіс назірання",
+       "prefs-editwatchlist": "Правіць спіс назірання",
+       "prefs-editwatchlist-label": "Правіць запісы ў вашым спісе назірання:",
+       "prefs-editwatchlist-edit": "Прагляд і сціранне старонак з вашага спісу назірання",
+       "prefs-editwatchlist-raw": "Правіць нефарматаваны спіс назірання",
+       "prefs-editwatchlist-clear": "Ачысціць ваш спіс назірання",
        "prefs-watchlist-days": "За колькі дзён паказваць змяненні ў назіраным:",
        "prefs-watchlist-days-max": "(найбольш $1 {{PLURAL:$1|дзень|дні|дзён}})",
        "prefs-watchlist-edits": "Колькасць правак для паказу ў разгорнутым выглядзе:",
        "prefs-help-recentchangescount": "Гэта ўключае ў сябе апошнія змены, гісторыі старонак, журналы.",
        "prefs-help-watchlist-token2": "Гэта сакрэтны ключ к сеціўнай стужцы з вашага спіса назірання.\nКожны, хто ведае гэты ключ, будзе мець магчымасць чытаць ваш спіс назірання, таму не дзяліцеся ім.\nКалі трэба, можна [[Special:ResetTokens|скінуць яго]].",
        "savedprefs": "Настройкі замацаваныя.",
+       "savedrights": "Дазволы {{GENDER:$1|ўдзельніка|ўдзельніцы}} $1 захаваныя.",
        "timezonelegend": "Часавы пояс:",
        "localtime": "Мясцовы час:",
        "timezoneuseserverdefault": "Карыстацца настаўленнямі серверу ($1)",
        "prefs-tokenwatchlist": "Токен",
        "prefs-diffs": "Розніцы",
        "prefs-help-prefershttps": "Гэта настройка пачне дзейнічаць па наступным уваходзе ў сістэму.",
+       "prefswarning-warning": "Вы зрабілі змены ў сваіх настройках, якія яшчэ не былі запісаныя.\nКалі вы закрыеце гэту старонку, не націснуўшы \"$1\", вашы настройкі не будуць абноўлены.",
        "prefs-tabs-navigation-hint": "Падказка: Вы можаце карыстацца клавішамі са стрэлкамі ўлева і ўправа для навігацыі паміж карткамі ў спісе картак.",
        "userrights": "Распараджэнне правамі ўдзельніка",
        "userrights-lookup-user": "Распараджацца групамі ўдзельнікаў",
        "right-createpage": "Ствараць старонкі (не размоўныя)",
        "right-createtalk": "Ствараць размоўныя старонкі",
        "right-createaccount": "Ствараць новыя рахункі ўдзелу",
+       "right-autocreateaccount": "Аўтаматычны ўваход у сістэму з вонкавага ўліковага запісу ўдзельніка",
        "right-minoredit": "Азначаць праўкі як дробныя",
        "right-move": "Пераносіць старонкі",
        "right-move-subpages": "Пераносіць старонкі разам з пад-старонкамі",
        "right-protect": "Мяняць узроўні аховы і правіць старонкі пад каскаднай аховай",
        "right-editprotected": "Правіць старонкі пад аховай \"{{int:protect-level-sysop}}\"",
        "right-editsemiprotected": "Правіць старонкі, што пад аховай \"{{int:protect-level-autoconfirmed}}\"",
+       "right-editcontentmodel": "Рэдагаваць мадэль змесціва старонкі",
        "right-editinterface": "Правіць карыстальніцкі інтэрфейс",
        "right-editusercssjs": "Правіць файлы CSS і JS іншых удзельнікаў",
        "right-editusercss": "Правіць файлы CSS іншых удзельнікаў",
        "right-override-export-depth": "Экспартаваць старонкі, у тым ліку звязаныя, да глыбіні спасылак 5.",
        "right-sendemail": "Адпраўляць электронныя лісты іншым удзельнікам",
        "right-passwordreset": "Бачыць электронныя лісты аб змяненні пароля",
+       "right-managechangetags": "Ствараць і выдаляць [[Special:Tags|біркі]] з базы даных",
+       "right-applychangetags": "Прымяняць [[Special:Tags|біркі]] са сваімі праўкамі",
+       "right-changetags": "Дадаваць і выдаляць адвольныя [[Special:Tags|біркі]] да асобных версій і запісаў у журнале падзей",
+       "grant-generic": "Набор дазволаў \"$1\"",
+       "grant-group-page-interaction": "Узаемадзейнічаць з старонкамі",
+       "grant-group-file-interaction": "Узаемадзейнічаць з медыяфайламі",
+       "grant-group-watchlist-interaction": "Узаемадзейнічаць з вашым спісам назірання",
+       "grant-group-email": "Адпраўляць эл. пошту",
+       "grant-group-high-volume": "Выконваць вялікі аб'ём дзейнасці",
+       "grant-group-customization": "Настройкі і перавагі",
+       "grant-group-administration": "Выконваць адміністрацыйныя дзеянні",
+       "grant-group-other": "Розная актыўнасць",
+       "grant-blockusers": "Блакаваць і разблакаваць удзельнікаў",
+       "grant-createaccount": "Ствараць уліковыя запісы",
+       "grant-createeditmovepage": "Ствараць, правіць і пераносіць старонкі",
+       "grant-delete": "Сціраць старонкі, версіі і запісы ў журналах",
+       "grant-editinterface": "Правіць прасторы назваў МедыяВікі і CSS/JavaScript удзельніка",
+       "grant-editmycssjs": "Правіць ваш CSS/JavaScript",
+       "grant-editmyoptions": "Змяняць вашы настройкі",
+       "grant-editmywatchlist": "Правіць ваш спіс назірання",
+       "grant-editpage": "Правіць наяўныя старонкі",
+       "grant-editprotected": "Правіць абароненыя старонкі",
+       "grant-highvolume": "Вялікі аб'ём рэдагавання",
+       "grant-oversight": "Утойваць удзельнікаў і версіі старонак",
+       "grant-patrol": "Патруляваць змены старонак",
+       "grant-protect": "Ахоўваць і здымаць ахову старонак",
+       "grant-rollback": "Адкатваць змяненні старонак",
+       "grant-sendemail": "Адпраўляць электронную пошту іншым удзельнікам",
+       "grant-uploadeditmovefile": "Загружаць, замяняць і пераносіць файлы",
+       "grant-uploadfile": "Укладаць новыя файлы",
+       "grant-basic": "Асноўныя правы",
+       "grant-viewdeleted": "Праглядаць сцёртыя файлы і старонкі",
+       "grant-viewmywatchlist": "Бачыць ваш спіс назірання",
        "newuserlogpage": "Журнал рэгістрацыі ўдзельнікаў",
        "newuserlogpagetext": "Гэта журнал рэгістрацыі новых удзельнікаў.",
        "rightslog": "Журнал правоў удзельнікаў",
        "action-createpage": "ствараць старонкі",
        "action-createtalk": "ствараць размоўныя старонкі",
        "action-createaccount": "ствараць гэты рахунак удзельніка",
+       "action-autocreateaccount": "аўтаматычна ствараць гэты вонкавы ўліковы запіс удзельніка",
        "action-history": "глядзець гісторыю гэтай старонкі",
        "action-minoredit": "значыць гэтую праўку як дробную",
        "action-move": "пераносіць гэтую старонку",
        "action-viewmywatchlist": "глядзець свой спіс назірання",
        "action-viewmyprivateinfo": "бачыць свае асабістыя звесткі",
        "action-editmyprivateinfo": "правіць свае асабістыя звесткі",
+       "action-editcontentmodel": "правіць мадэль змесціва старонкі",
+       "action-managechangetags": "ствараць і выдаляць біркі з базы даных",
+       "action-applychangetags": "прымяняць біркі з сваімі праўкамі",
+       "action-changetags": "дадаваць і выдаляць адвольныя біркі да асобных версій і запісаў у журнале падзей",
        "nchanges": "$1 {{PLURAL:$1|змена|змены|змен}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|з часу апошняга наведвання}}",
        "enhancedrc-history": "гісторыя",
        "recentchanges-label-plusminus": "Аб'ём старонкі змяніўся на гэтую лічбу байтаў",
        "recentchanges-legend-heading": "<strong>Легенда:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (гл. асобна [[Special:NewPages|новыя старонкі]])",
+       "recentchanges-submit": "Паказаць",
        "rcnotefrom": "Ніжэй {{PLURAL:$5|паказана змяненне|паказаны змены}} з <strong>$3, $4</strong> (не больш за <strong>$1</strong>).",
        "rclistfrom": "Паказаць змены з $3 $2",
        "rcshowhideminor": "$1 дробныя праўкі",
        "rcshowhidemine": "$1 уласныя праўкі",
        "rcshowhidemine-show": "Паказаць",
        "rcshowhidemine-hide": "Схаваць",
+       "rcshowhidecategorization": "$1 катэгарызацыю старонак",
+       "rcshowhidecategorization-show": "Паказаць",
+       "rcshowhidecategorization-hide": "Схаваць",
        "rclinks": "Паказаць апошнія $1 змен за мінулыя $2 дзён<br />$3",
        "diff": "розн.",
        "hist": "гіст.",
        "recentchangeslinked-summary": "Гэта пералік нядаўніх змяненняў старонак, на якія спасылаецца азначаная старонка, або змяненняў складнікаў азначанай катэгорыі.\nСтаронкі, якія ўваходзяць у [[Special:Watchlist|лік назіраных вамі]], выдзелены <strong>стылем</strong>.",
        "recentchangeslinked-page": "Назва старонкі:",
        "recentchangeslinked-to": "Паказваць, замест гэтага, змяненні на старонках, што спасылаюцца сюды",
+       "recentchanges-page-added-to-category": "[[:$1]] дададзена ў катэгорыю",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] і яшчэ [[Special:WhatLinksHere/$1|{{PLURAL:$2|адна старонка дададзена|$2 старонкі дададзены|$2 старонак дададзена}}]] ў катэгорыю",
+       "recentchanges-page-removed-from-category": "[[:$1]] выдалена з катэгорыі",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] і яшчэ {{PLURAL:$2|адна старонка выдалена|$2 старонкі выдалены|$2 старонак выдалена}} з катэгорыі",
+       "autochange-username": "Аўтаматычная змена MediaWiki",
        "upload": "Укласці файл",
        "uploadbtn": "Укласці файл",
        "reuploaddesc": "Спыніць укладанне і вярнуцца да пачатковага фармуляра.",
        "uploaddisabledtext": "Не дазваляюцца ўкладанні файлаў.",
        "php-uploaddisabledtext": "Укладанне файлаў не дазволена ў асяроддзі PHP. Праверце настаўленне file_uploads.",
        "uploadscripted": "У файле ўтрымліваецца код HTML або Яваскрыпту, які можа быць памылкова апрацаваны браўзерам.",
+       "upload-scripted-pi-callback": "Немагчыма ўкласці файл, які ўтрымлівае інструкцыі апрацоўкі табліцы стыляў XML.",
+       "uploaded-script-svg": "У ўкладзеным SVG-файле знойдзены небяспечны элемент з падтрымкай скрыптаў \"$1\".",
+       "uploaded-hostile-svg": "У ўкладзеным SVG файле знойдзены небяспечны CSS у элеменце стылю.",
+       "uploaded-event-handler-on-svg": "Устаноўка атрыбутаў апрацоўшчыка падзей <code>$1=\"$2\"</code> у SVG файле не дазваляецца.",
+       "uploaded-href-attribute-svg": "у SVG файлах атрыбутам href дазволены толькі мэты віду http:// або https://, знойдзена <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-href-unsafe-target-svg": "У ўкладзеным SVG файле знойдзена спасылка на небяспечныя звесткі: URI мэты <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-animate-svg": "У ўкладзеным SVG файле знойдзены тэг \"animate\", здольны змяніць спасылку з дапамогай атрыбута \"from\" <code>&lt;$1 $2=\"$3\"&gt;</code>.",
        "uploadscriptednamespace": "Гэты файл SVG утрымлівае недапушчальную прастору імёнаў \"$1\".",
        "uploadinvalidxml": "Немагчыма прааналізаваць XML ва ўкладзеным файле.",
        "uploadvirus": "Файл утрымлівае вірус! Падрабязнасці: $1",
        "upload-options": "Магчымасці ўкладання",
        "watchthisupload": "Назіраць за файлам",
        "filewasdeleted": "Файл з такою назвай быў раней укладзены сюды, а потым сцёрты. Варта паглядзець у $1 перад тым, як укладаць яго нанова.",
+       "filename-thumb-name": "Выглядае як назва мініяцюры. Калі ласка, не загружайце мініяцюры назад у тую ж вікі. Калі вам неабходны гэты файл, выпраўце назву на больш асэнсаваную, каб яна не ўтрымлівала прэфікс мініяцюры.",
        "filename-bad-prefix": "Назва файла, які вы ўкладаеце, пачынаецца з <strong>\"$1\"</strong>, што падобна на аўтаматычныя, неінфарматыўныя назвы файлаў, якія робяць лічбавыя фотаапараты. Калі ласка, змяніце назву на больш зразумелую.",
        "upload-proto-error": "Няправільны пратакол",
        "upload-proto-error-text": "Укладанне файла зводдаль патрабуе URL, які пачынаецца з <code>http://</code> або <code>ftp://</code>.",
        "upload-too-many-redirects": "Занадта шмат перасылак за гэтым адрасам (URL)",
        "upload-http-error": "Памылка HTTP: $1",
        "upload-copy-upload-invalid-domain": "Капіраванне загрузак не дазволенае ў гэтым дамене.",
+       "upload-foreign-cant-upload": "Гэта вікі не настроена для ўкладання файлаў у запытанае старонняе сховішча файлаў.",
+       "upload-dialog-title": "Укласці файл",
+       "upload-dialog-button-cancel": "Нічога",
+       "upload-dialog-button-done": "Гатова",
+       "upload-dialog-button-save": "Запісаць",
+       "upload-dialog-button-upload": "Укласці",
+       "upload-form-label-infoform-title": "Падрабязнасці",
+       "upload-form-label-infoform-name": "Назва",
+       "upload-form-label-infoform-name-tooltip": "Унікальны апісальны загаловак для файла, які будзе служыць яго назвай. Можаце выкарыстоўваць звычайную мову з прабеламі. Не дадавайце канчатак назвы файла.",
        "upload-form-label-infoform-description": "Апісанне",
+       "upload-form-label-infoform-description-tooltip": "Коратка апішыце ўсё значнае пра гэту працу.\nДля фатаграфіі ўкажыце галоўныя аб'екты, нагоду або месца.",
+       "upload-form-label-usage-title": "Выкарыстанне",
+       "upload-form-label-usage-filename": "Назва файла",
+       "foreign-structured-upload-form-label-own-work": "Гэта мая ўласная праца",
+       "foreign-structured-upload-form-label-infoform-categories": "Катэгорыі",
        "foreign-structured-upload-form-label-infoform-date": "Дата",
+       "foreign-structured-upload-form-label-own-work-message-local": "Я пацвярджаю, што ўкладваю гэты файл згодна з правіламі і ліцэнзійнай палітыкай {{GRAMMAR:родны|{{SITENAME}}}}.",
+       "foreign-structured-upload-form-label-not-own-work-message-local": "Калі вы не можаце ўкладваць гэты файл згодна з правіламі пляцоўкі {{SITENAME}}, калі ласка, закрыйце гэта акно і паспрабуйце іншы метад.",
+       "foreign-structured-upload-form-label-not-own-work-local-local": "Вы таксама можаце паспрабаваць [[Special:Upload|прадвызначаную старонку ўкладвання]].",
+       "foreign-structured-upload-form-label-own-work-message-default": "Я разумею, што ўкладваю гэты файл у агульнае сховішча. Я пацвярджаю, што раблю гэта ў адпаведнасці з умовамі выкарыстання і ліцэнзійнай палітыкай.",
+       "foreign-structured-upload-form-label-not-own-work-message-default": "Калі вы не можаце ўкладваць гэты файл згодна з правіламі агульнага сховішча, калі ласка, закрыйце гэта акно і паспрабуйце іншы метад.",
+       "foreign-structured-upload-form-label-not-own-work-local-default": "Вы таксама можаце паспрабаваць скарыстацца [[Special:Upload|старонкай укладанняў пляцоўкі {{SITENAME}}]], калі гэты файл можна укладваць туды згодна з іх палітыкай.",
        "backend-fail-stream": "Не атрымалася трансляваць файл $1.",
        "backend-fail-backup": "Немагчыма зрабіць рэзервную копію $1.",
        "backend-fail-notexists": "Файл $1 не існуе.",
        "listfiles-delete": "сцерці",
        "listfiles-summary": "Гэтая службовая старонка паказвае ўсе загружаныя файлы.",
        "listfiles_search_for": "Знайсці назву выявы:",
+       "listfiles-userdoesnotexist": "Уліковы запіс удзельніка \"$1\" не зарэгістраваны.",
        "imgfile": "файл",
        "listfiles": "Усе файлы",
        "listfiles_thumb": "Драбніца",
        "randomincategory-nopages": "Няма старонак у катэгорыі [[:Category:$1|$1]].",
        "randomincategory-category": "Катэгорыя:",
        "randomincategory-legend": "Выпадковая старонка ў катэгорыі",
+       "randomincategory-submit": "Перайсці",
        "randomredirect": "Выпадковая перасылка",
        "randomredirect-nopages": "Няма перасылак у прасторы назваў \"$1\".",
        "statistics": "Статыстыка",
        "mostrevisions": "Артыкулы з найбольшай колькасцю версій",
        "prefixindex": "Старонкі з назвамі на ўзор",
        "prefixindex-namespace": "Усе старонкі з прэфіксам ( $1 прастора імёнаў)",
+       "prefixindex-submit": "Паказаць",
        "prefixindex-strip": "Прыбраць прэфікс у пераліку",
        "shortpages": "Старонкі малога аб'ёму",
        "longpages": "Старонкі вялікага аб'ёму",
        "protectedpages-performer": "Паставіў ахову",
        "protectedpages-params": "Тыпы аховы",
        "protectedpages-reason": "Прычына",
+       "protectedpages-submit": "Паказаць старонкі",
        "protectedpages-unknown-timestamp": "Невядома",
        "protectedpages-unknown-performer": "Нявызначаны ўдзельнік",
        "protectedtitles": "Назвы пад аховай",
        "protectedtitles-summary": "На гэтай старонцы пералічаны назвы, якія зараз абаронены ад стварэння. Спіс існых старонак пад аховай гл. [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Няма назваў, якія зараз бы ахоўваліся з такімі параметрамі.",
+       "protectedtitles-submit": "Паказаць назвы",
        "listusers": "Усе ўдзельнікі",
        "listusers-editsonly": "Толькі ўдзельнікі, якія маюць праўкі",
        "listusers-creationsort": "У парадку датаў стварэння",
        "usereditcount": "$1 {{PLURAL:$1|праўка|праўкі|правак}}",
        "usercreated": "\t{{GENDER:$3|Зарэгістраваўся|Зарэгістравалася}} $1 у $2",
        "newpages": "Новыя старонкі",
+       "newpages-submit": "Паказаць",
        "newpages-username": "Імя ўдзельніка:",
        "ancientpages": "Найстарэйшыя старонкі",
        "move": "Перанесці",
        "querypage-disabled": "Гэта адмысловая старонка адключана для павышэння прадукцыйнасці.",
        "apihelp": "Даведка па API",
        "apihelp-no-such-module": "Модуль \"$1\" не знойдзены.",
+       "apisandbox": "Пясочніца API",
+       "apisandbox-jsonly": "Каб выкарыстоўваць пясочніцу API, патрэбен JavaScript.",
+       "apisandbox-api-disabled": "API адключаны на гэтым сайце.",
+       "apisandbox-fullscreen": "Разгарнуць панэль",
+       "apisandbox-fullscreen-tooltip": "Разгарнуць панэль пясочніцы, каб запоўніць акно браўзера.",
+       "apisandbox-unfullscreen": "Паказаць старонку",
+       "apisandbox-submit": "Зрабіць запыт",
        "apisandbox-reset": "Ачысціць",
        "apisandbox-retry": "Паўтарыць",
+       "apisandbox-no-parameters": "Гэты модуль API не мае параметраў.",
+       "apisandbox-helpurls": "Спасылкі на даведку",
        "apisandbox-examples": "Прыклады",
        "apisandbox-dynamic-parameters": "Дадатковыя параметры",
        "apisandbox-dynamic-parameters-add-label": "Дадаць параметр:",
+       "apisandbox-dynamic-parameters-add-placeholder": "Назва параметра",
+       "apisandbox-dynamic-error-exists": "Параметр з назвай \"$1\" ужо існуе.",
+       "apisandbox-deprecated-parameters": "Састарэлыя параметры",
+       "apisandbox-results": "Вынікі",
+       "apisandbox-alert-page": "Палі на гэтай старонцы недапушчальныя.",
+       "apisandbox-alert-field": "Значэнне гэтага поля недапушчальнае.",
        "booksources": "Кнігі",
        "booksources-search-legend": "Знайсці, дзе купіць кнігі",
        "booksources-search": "Пошук",
        "booksources-text": "Ніжэй паказаны пералік спасылак на іншыя сеціўныя пляцоўкі, якія прадаюць новыя і б/у кнігі, і, магчыма, маюць больш звестак пра кнігі, якіх вы шукаеце:",
        "booksources-invalid-isbn": "Гэты ISBN не выглядае правільным; праверце правільнасць капіравання з арыгіналу.",
        "specialloguserlabel": "Выканаўца:",
-       "speciallogtitlelabel": "Мэта (назва ці ўдзельнік):",
+       "speciallogtitlelabel": "Мэта (назва ці {{ns:user}}:імя_ўдзельніка для ўдзельніка):",
        "log": "Журналы",
+       "logeventslist-submit": "Паказаць",
        "all-logs-page": "Усе публічныя журналы",
        "alllogstext": "Супольны паказ усіх магчымых журналаў на пляцоўцы {{SITENAME}}.\nМожна звузіць аб'ём паказу, выбіраючы тып журнала, імя ўдзельніка (з улікам рэгістру літар) або старонкі (таксама з улікам рэгістру).",
        "logempty": "Нічога адпаведнага ў журнале не знойдзена.",
        "log-title-wildcard": "Знайсці назвы, якія пачынаюцца з гэтага тэксту",
        "showhideselectedlogentries": "Паказаць/схаваць выбраныя запісы журнала",
+       "log-edit-tags": "Правіць біркі да выбраных запісаў журнала",
+       "checkbox-select": "Выбраць: $1",
        "checkbox-all": "Усе",
        "allpages": "Усе старонкі",
        "nextpage": "Наступная старонка ($1)",
        "cachedspecial-viewing-cached-ts": "Вы праглядаеце кэшаваную версію старонкі, якая можа быць не зусім актуальнай.",
        "cachedspecial-refresh-now": "Глядзець найноўшую.",
        "categories": "Катэгорыі",
+       "categories-submit": "Паказаць",
        "categoriespagetext": "Наступн{{PLURAL:$1|ая катэгорыя ўтрымлівае|ыя $1 катэгорыі(-й) утрымліваюць}} старонкі або мультымедыю.\nТут не паказаныя [[Special:UnusedCategories|катэгорыі без складнікаў]].\nГл. таксама [[Special:WantedCategories|патрэбныя катэгорыі]].",
        "categoriesfrom": "Паказаць катэгорыі, пачынаючы з:",
        "special-categories-sort-count": "пд. колькасці",
        "activeusers-hidebots": "Без робатаў",
        "activeusers-hidesysops": "Без адміністратараў",
        "activeusers-noresult": "Няма такіх удзельнікаў.",
+       "activeusers-submit": "Паказаць актыўных удзельнікаў",
        "listgrouprights": "Дазволы для груп удзельнікаў",
        "listgrouprights-summary": "Гэты пералік вызначаных у гэтай вікі груп удзельнікаў, разам з прыпісанымі ім дазволамі.\nДаведацца больш пра асабістыя дазволы можна на старонцы [[{{MediaWiki:Listgrouprights-helppage}}]].",
        "listgrouprights-key": "Легенда:\n* <span class=\"listgrouprights-granted\">Дадзены дазвол</span>\n* <span class=\"listgrouprights-revoked\">Адкліканы дазвол</span>",
        "wlheader-showupdated": "Старонкі, якія былі зменены пасля вашага апошняга наведвання, паказаны <strong>абрысам шрыфту</strong>.",
        "wlnote": "Ніжэй {{PLURAL:$1|паказана апошняя <strong>$1</strong> змена|паказаны апошнія <strong>$1</strong> змены|паказаны апошнія <strong>$1</strong> змен}} за {{PLURAL:$2|апошнюю|апошнія|апошнія}} <strong>$2</strong> {{PLURAL:$2|гадзіну|гадзіны|гадзін}}, на момант часу $3 $4.",
        "wlshowlast": "Паказваць апошнія $1 гадз. $2 дзён",
+       "watchlist-hide": "Схаваць",
+       "watchlist-submit": "Паказаць",
+       "wlshowtime": "Перыяд часу для паказу:",
+       "wlshowhideminor": "дробныя праўкі",
+       "wlshowhidebots": "робатаў",
+       "wlshowhideliu": "пазнаных удзельнікаў",
+       "wlshowhideanons": "ананімных удзельнікаў",
+       "wlshowhidepatr": "ухваленыя праўкі",
+       "wlshowhidemine": "мае праўкі",
+       "wlshowhidecategorization": "катэгарызацыю старонак",
        "watchlist-options": "Магчымасці назірання",
        "watching": "Дапісваецца ў спіс назірання...",
        "unwatching": "Спыняем назіранне...",
        "deletepage": "Сцерці старонку",
        "confirm": "Пацвердзіць",
        "excontent": "тэкст быў: '$1'",
-       "excontentauthor": "тэкст быў: '$1' (і адзіны аўтар: '[[Special:Contributions/$2|$2]]')",
+       "excontentauthor": "тэкст быў: '$1' (і адзіны аўтар: \"[[Special:Contributions/$2|$2]]\" ([[User talk:$2|размовы]]))",
        "exbeforeblank": "змесціва перад ачысткаю было: '$1'",
        "delete-confirm": "Сцерці \"$1\"",
        "delete-legend": "Сцерці",
        "historywarning": "<strong>Увага:</strong> Старонка, якую вы хочаце сцерці, мае гісторыю з прыблізна $1 {{PLURAL:$1|праўкі|правак}}:",
+       "historyaction-submit": "Паказаць",
        "confirmdeletetext": "Вы збіраецеся сцерці старонку разам з цэлай яе гісторыяй правак.\nПацвердзіце свой намер зрабіць гэта, сваё разуменне наступстваў, і што вы робіце гэта ў адпаведнасці з [[{{MediaWiki:Policy-url}}|палітыкай (асноўнымі правіламі)]].",
        "actioncomplete": "Завершана аперацыя",
        "actionfailed": "Памылка дзеяння",
        "rollback-success": "Адкочаны праўкі $1; вернута апошняя версія $2.",
        "sessionfailure-title": "Памылка сеансу",
        "sessionfailure": "Магчыма, ёсць праблемы з вашым сеансам працы ў сістэме. Таму вам было адмоўлена ў выкананні дзеяння, каб засцерагчыся ад захопу сеанса.\n\nВярніцеся на папярэднюю старонку, перазагрузіце яе і тады паспрабуйце зноў.",
+       "changecontentmodel-title-label": "Назва старонкі",
+       "changecontentmodel-model-label": "Новая мадэль змесціва",
+       "changecontentmodel-reason-label": "Прычына:",
+       "changecontentmodel-submit": "Змяніць",
+       "logentry-contentmodel-change-revertlink": "адкаціць",
+       "logentry-contentmodel-change-revert": "адкат",
        "protectlogpage": "Журнал аховы",
        "protectlogtext": "Ніжэй прыведзены журнал змен абароны старонкі.\nВы можаце таксама прагледзець [[Special:ProtectedPages|пералік старонак пад аховай]].",
        "protectedarticle": "пад аховай «[[$1]]»",
        "protect-othertime": "Іншы час:",
        "protect-othertime-op": "іншы час",
        "protect-existing-expiry": "Вызначаны час сканчэння: $3, $2",
+       "protect-existing-expiry-infinity": "Наяўны тэрмін дзеяння: бясконца",
        "protect-otherreason": "Іншая ці дадатковая прычына:",
        "protect-otherreason-op": "Іншая прычына",
        "protect-dropdown": "*Звычайныя прычыны пастаноўкі аховы\n** Празмерны ўзровень вандалізму\n** Празмерны ўзровень спаму\n** Шкодная вайна правак\n** Старонка з высокай наведвальнасцю",
        "ipb-unblock": "Разблакіраваць удзельніка ці IP-адрас",
        "ipb-blocklist": "Паказаць наяўныя блокі",
        "ipb-blocklist-contribs": "Уклад {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "засталося $1",
        "unblockip": "Зняць блок з удзельніка",
        "unblockiptext": "З дапамогай формы ніжэй можна вярнуць дазвол на праўкі для раней заблакіраванага IP-адраса або ўдзельніка.",
        "ipusubmit": "Зняць гэты блок",
        "unblocked": "[[User:$1|$1]] быў адблакаваны",
        "unblocked-range": "$1 быў разблакаваны.",
        "unblocked-id": "Блок $1 быў зняты",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] быў разблакіраваны.",
        "blocklist": "Заблакаваныя ўдзельнікі",
        "ipblocklist": "Заблакаваныя ўдзельнікі",
        "ipblocklist-legend": "Знайсці заблакаванага ўдзельніка",
        "block-log-flags-hiddenname": "схаванае імя ўдзельніка",
        "range_block_disabled": "Не дазволена адміністратарская магчымасць ставіць блокі на адрасныя дыяпазоны.",
        "ipb_expiry_invalid": "Некарэктны час сканчэння.",
+       "ipb_expiry_old": "Час сканчэння — у мінулым.",
        "ipb_expiry_temp": "Скрытыя блокі на імёны ўдзельнікаў мусяць быць сталымі.",
        "ipb_hide_invalid": "Немагчыма заглушыць гэты рахунак; для яго маецца больш за {{PLURAL:$1|адну праўку|$1 праўкі|$1 правак}}.",
        "ipb_already_blocked": "\"$1\" ужо знаходзіцца пад блокам",
        "cant-move-to-user-page": "Вам не дазволена пераносіць старонку ў старонку карыстальніка (не лічачы пад-старонак карыстальніка).",
        "cant-move-category-page": "Вам не дазволена пераносіць старонкі катэгорый.",
        "cant-move-to-category-page": "Вам не дазволена пераносіць старонку ў старонку катэгорыі.",
-       "newtitle": "Ð\9fад Ð½Ð¾Ð²Ñ\83Ñ\8e Ð½Ð°Ð·Ð²Ñ\83:",
+       "newtitle": "Ð\9dоваÑ\8f Ð½Ð°Ð·Ð²Ð°:",
        "move-watch": "Назіраць за старонкай",
        "movepagebtn": "Перанесці старонку",
        "pagemovedsub": "Паспяховы перанос",
        "move-leave-redirect": "Пакінуць перасылку са старой назвы",
        "protectedpagemovewarning": "<strong>Папярэджанне:</strong> Гэта старонка была змешчана пад ахову; пераназваць яе могуць толькі ўдзельнікі з паўнамоцтвамі адміністратараў.\nНіжэй для даведкі прыведзена апошні запіс журнала:",
        "semiprotectedpagemovewarning": "<strong>Заўвага:</strong> Гэта старонка была змешчана пад ахову; пераносіць яе пад іншую назву могуць толькі зарэгістраваныя ўдзельнікі.\nНіжэй для даведкі прыведзена апошні запіс журнала:",
-       "move-over-sharedrepo": "== Файл існуе ==\nФайл з назвай [[:$1]] ёсць у агульным сховішчы. Файл, перанесены пад такую назву, будзе перамагаць файл з агульнага сховішча.",
+       "move-over-sharedrepo": "Файл з назвай [[:$1]] ёсць у агульным сховішчы. Файл, перанесены пад такую назву, будзе перамагаць файл з агульнага сховішча.",
        "file-exists-sharedrepo": "Такая назва файла ўжо выкарыстана ў агульным сховішчы.\nВыберыце іншую назву.",
        "export": "Экспартаваць старонкі",
        "exporttext": "Тут можна экспартаваць тэкст і гісторыю правак пэўнай старонкі або збору старонак, з наступным абгортваннем у адмысловы код XML. Такое потым можна імпартаваць у іншую Вікі на аснове пакету MediaWiki праз [[Special:Import|старонку імпартавання]].\n\nКаб экспартаваць старонкі, упішыце іх назвы, адну на радок, у тэкставым полі, што ніжэй, і абазначце, ці жадаеце актуальныя версіі разам са старымі версіямі і з гісторыяй правак, ці толькі актуальныя з інфармацыяй пра апошнюю праўку.\n\nУ апошнім выпадку можна карыстацца адмысловай формай спасылкі ў выглядзе, напр., [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] для \"[[{{MediaWiki:Mainpage}}]]\".",
        "thumbnail_image-missing": "Хутчэй за ўсё, адсутнічае файл $1",
        "thumbnail_image-failure-limit": "Занадта шмат нядаўніх няўдалых спроб ($1 ці болей) стварыць гэту мініяцюру. Калі ласка, паспрабуйце пазней.",
        "import": "Імпартаваць старонкі",
-       "importinterwiki": "Імпарт Transwiki",
-       "import-interwiki-text": "Ð\92Ñ\8bбаÑ\80 Ð²Ñ\96кÑ\96 Ñ\96 Ð½Ð°Ð·Ð²Ñ\8b Ñ\81Ñ\82аÑ\80онкÑ\96 Ð´Ð·ÐµÐ»Ñ\8f Ñ\96мпаÑ\80Ñ\82Ñ\83.\nÐ\94аÑ\82Ñ\8b Ð²ÐµÑ\80Ñ\81Ñ\96й і імёны аўтараў будуць захаваныя.\nУсе транс-вікавыя імпарты запісваюцца ў [[Special:Log/import|журнале імпартаў]].",
+       "importinterwiki": "Імпарт з іншай вікі",
+       "import-interwiki-text": "Ð\92Ñ\8bбеÑ\80Ñ\8bÑ\86е Ð²Ñ\96кÑ\96 Ñ\96 Ð½Ð°Ð·Ð²Ñ\83 Ñ\81Ñ\82аÑ\80онкÑ\96 Ð´Ð»Ñ\8f Ñ\96мпаÑ\80Ñ\82Ñ\83.\nÐ\94аÑ\82Ñ\8b Ð¿Ñ\80авак і імёны аўтараў будуць захаваныя.\nУсе транс-вікавыя імпарты запісваюцца ў [[Special:Log/import|журнале імпартаў]].",
        "import-interwiki-sourcewiki": "Крынічная вікі:",
        "import-interwiki-sourcepage": "Крынічная старонка:",
        "import-interwiki-history": "Капіраваць усе гістарычныя версіі гэтай старонкі",
        "import-interwiki-templates": "Разам з усімі шаблонамі",
        "import-interwiki-submit": "Імпартаваць",
+       "import-mapping-default": "Імпартаваць у прадвызначанае месца",
+       "import-mapping-namespace": "Імпартаваць у прастору назваў:",
+       "import-mapping-subpage": "Імпартаваць як падстаронкі наступнай старонкі:",
        "import-upload-filename": "Назва файла:",
        "import-comment": "Каментарый:",
        "importtext": "Калі ласка, экспартуйце файл з крынічнай вікі з дапамогай [[Special:Export|прылады экспарту]].\nЗахавайце яго на свой камп'ютар, а потым загрузіце сюды.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|версія|версіі|версій}} імпартавана",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версія|версіі|версій}} імпартавана з $2",
        "javascripttest": "JavaScript-тэсты",
-       "javascripttest-pagetext-noframework": "Гэта старонка зарэзервавана для запуску тэстаў JavaScript",
-       "javascripttest-pagetext-unknownframework": "Невядомая бібліятэка тэставання «$1».",
-       "javascripttest-pagetext-frameworks": "Калі ласка, выберыце адну з прапанаваных бібліятэк тэставання: $1",
-       "javascripttest-pagetext-skins": "Выберыце афармленне для тэставання:",
+       "javascripttest-pagetext-unknownaction": "Невядомае дзеянне \"$1\".",
        "javascripttest-qunit-intro": "Глядзіце [$1 дакументацыю па тэставанні] на mediawiki.org.",
        "tooltip-pt-userpage": "Ваша ўласная старонка",
        "tooltip-pt-anonuserpage": "Старонка ўдзельніка для таго IP, з якога вы зараз працуеце",
        "tooltip-feed-rss": "RSS-струмень гэтай старонкі",
        "tooltip-feed-atom": "Струмень навін Atom для гэтай старонкі",
        "tooltip-t-contributions": "Пералік укладаў {{GENDER:$1|гэтага ўдзельніка|гэтай удзельніцы}}",
-       "tooltip-t-emailuser": "Адаслаць удзельніку ліст эл.пошты",
+       "tooltip-t-emailuser": "Адаслаць {{GENDER:$1|удзельніку|удзельніцы}} ліст эл.пошты",
+       "tooltip-t-info": "Больш звестак пра гэту старонку",
        "tooltip-t-upload": "Укласці файлы",
        "tooltip-t-specialpages": "Пералік усіх адмысловых старонак",
        "tooltip-t-print": "Друкавальная версія гэтай старонкі",
        "lastmodifiedatby": "Апошняе змяненне старонкі адбылося $2, $1 аўтарства $3.",
        "othercontribs": "На аснове працы $1.",
        "others": "іншае",
-       "siteusers": "{{PLURAL:$2|удзельнік|удзельнікі}} з пляцоўкі {{SITENAME}} - $1",
+       "siteusers": "{{PLURAL:$2|{{GENDER:$1|удзельнік|удзельніца}}|удзельнікі}} з пляцоўкі {{SITENAME}} - $1",
        "anonusers": "ананімны{{PLURAL:$2| ўдзельнік|я ўдзельнікі}} {{SITENAME}} - $1",
        "creditspage": "Аўтарства старонкі",
        "nocredits": "Няма звестак пра аўтараў гэтай старонкі.",
        "pageinfo-robot-index": "Дазволена",
        "pageinfo-robot-noindex": "Не дазволена",
        "pageinfo-watchers": "Колькасць назіральнікаў старонкі",
+       "pageinfo-visiting-watchers": "Колькасць удзельнікаў, якія назіраюць за старонкай і бачылі апошнія змены",
        "pageinfo-few-watchers": "Менш чым $1 {{PLURAL:$1|назіральнік|назіральнікі|назіральнікаў}}",
+       "pageinfo-few-visiting-watchers": "Могуць быць, а можа і не быць удзельнікаў, якія назіраюць за старонкай і бачылі апошнія змены",
        "pageinfo-redirects-name": "Колькасць перасылак на гэту старонку",
        "pageinfo-subpages-name": "Колькасць падстаронак гэтай старонкі",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|перасылка|перасылкі|перасылак}}; $3 {{PLURAL:$3|прамая спасылка|прамыя спасылкі|прамых спасылак}})",
        "pageinfo-protect-cascading-yes": "Да",
        "pageinfo-protect-cascading-from": "Каскадная ахова ад",
        "pageinfo-category-info": "Звесткі аб катэгорыі",
+       "pageinfo-category-total": "Агульная колькасць членаў",
        "pageinfo-category-pages": "Колькасць старонак",
        "pageinfo-category-subcats": "Колькасць падкатэгорый",
        "pageinfo-category-files": "Колькасць файлаў",
        "markaspatrolleddiff": "Пазначыць як ухваленае",
        "markaspatrolledtext": "Пазначыць старонку як ухваленую",
+       "markaspatrolledtext-file": "Пазначыць версію файла як ухваленую",
        "markedaspatrolled": "Пазначана як ухваленае",
        "markedaspatrolledtext": "Азначаная версія [[:$1]] пазначана як ухваленая.",
        "rcpatroldisabled": "Не працуе Ухваленне Нядаўніх Правак",
        "patrol-log-page": "Журнал ухваленых",
        "patrol-log-header": "Журнал ухваленых версій",
        "log-show-hide-patrol": "$1 журнал ухваленняў",
+       "log-show-hide-tag": "$1 журнал бірак",
        "deletedrevision": "Сцёрта старая версія $1",
        "filedeleteerror-short": "Памылка пры сціранні файла: $1",
        "filedeleteerror-long": "Памылкі пры спробе сцірання файла:\n\n$1",
        "svg-long-error": "Няспраўны файл SVG: $1",
        "show-big-image": "Арыгінальны файл",
        "show-big-image-preview": "Памер пры папярэднім праглядзе: $1.",
+       "show-big-image-preview-differ": "Памер гэтага $3-прагляду для $2-файла: $1.",
        "show-big-image-other": "{{PLURAL:$2|Іншы дазвол|Іншыя дазволы}}: $1.",
        "show-big-image-size": "$1 × $2 піхеляў",
        "file-info-gif-looped": "закальцаваныя",
        "newimages-legend": "Фільтр",
        "newimages-label": "Назва файла (або яе частка):",
        "newimages-showbots": "Паказваць укладанні ботамі",
+       "newimages-hidepatrolled": "Без паказу ўхваленых ўкладанняў",
        "noimages": "Тут нічога няма.",
        "ilsubmit": "Знайсці",
        "bydate": "п. датаў",
        "exif-compression-4": "CCITT Group 4, факсавае кадзіраванне",
        "exif-copyrighted-true": "Ахоўваецца аўтарскім правам",
        "exif-copyrighted-false": "Статус аўтарства не ўстаноўлены",
+       "exif-photometricinterpretation-1": "Чорны і белы (чорны — 0)",
        "exif-unknowndate": "Невядомая дата",
        "exif-orientation-1": "Звычайна",
        "exif-orientation-2": "Адлюстравана злева ўправа",
        "scarytranscludefailed-httpstatus": "[Не ўдалося атрымаць шаблон для $1: HTTP $2]",
        "scarytranscludetoolong": "[Занадта доўгі URL]",
        "deletedwhileediting": "'''Увага''': гэтая старонка была сцёрта пасля таго, як вы пачалі з ёй працаваць!",
-       "confirmrecreate": "Удзельнік [[User:$1|$1]] ([[User talk:$1|размова]]) сцёр гэты артыкул пасля таго, як вы пачалі працу з ім, падаўшы прычыну:\n: ''$2''\nПацвердзіце свой намер аднавіць гэты артыкул.",
-       "confirmrecreate-noreason": "Удзельнік [[User:$1|$1]] ([[User talk:$1|размовы]]) выдаліў гэтую старонку пасля таго, як вы пачалі яе рэдагаваць. Калі ласка, пацвердзіце, што вы сапраўды жадаеце аднавіць гэтую старонку.",
+       "confirmrecreate": "{{GENDER:$1|Удзельнік|Удзельніца}} [[User:$1|$1]] ([[User talk:$1|размова]]) {{GENDER:$1|сцёр|сцерла}} гэты артыкул пасля таго, як вы пачалі працу з ім, падаўшы прычыну:\n: <em>$2</em>\nПацвердзіце свой намер аднавіць гэты артыкул.",
+       "confirmrecreate-noreason": "{{GENDER:$1|Удзельнік|Удзельніца}} [[User:$1|$1]] ([[User talk:$1|размовы]]) {{GENDER:$1|сцёр|сцёрла}} гэту старонку пасля таго, як вы пачалі яе рэдагаваць.\nКалі ласка, пацвердзіце, што вы сапраўды жадаеце аднавіць гэтую старонку.",
        "recreate": "Аднавіць",
        "unit-pixel": "крпк",
        "confirm_purge_button": "ОК",
        "watchlisttools-edit": "Паказаць спіс назірання",
        "watchlisttools-raw": "Паказаць нефарматаваны спіс назірання",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|размовы]])",
+       "timezone-local": "Мясцовы",
        "duplicate-defaultsort": "Увага: прадвызначаная клавіша ўпарадкавання \"$2\" замяніла ранейшую такую клавішу \"$1\".",
        "duplicate-displaytitle": "<strong>Папярэджанне:</strong> Паказаная назва \"$2\" перасягае ранейшую назву \"$1\".",
+       "invalid-indicator-name": "<strong>Памылка:</strong> Атрыбут <code>name</code> індыкатараў статусу старонкі не можа быць пустым.",
        "version": "Версія",
        "version-extensions": "Устаноўленыя прыстаўкі",
        "version-skins": "Устаноўленыя вокладкі",
        "version-entrypoints": "Уваходныя адрасы",
        "version-entrypoints-header-entrypoint": "Кропка ўваходу",
        "version-entrypoints-header-url": "URL",
+       "version-libraries": "Устаноўленыя бібліятэкі",
+       "version-libraries-library": "Бібліятэка",
        "version-libraries-version": "Версія",
        "version-libraries-license": "Ліцэнзія",
        "version-libraries-description": "Апісанне",
        "version-libraries-authors": "Аўтары",
        "redirect": "Перасылка да файла, ID удзельніка, старонкі, версіі ці журнала",
-       "redirect-legend": "Перасылка да файла ці старонкі",
        "redirect-summary": "Гэта адмысловая старонка перасылае да файла (з назвы файла), на старонку (з ідэнтыфікатара версіі ці старонкі), ці на старонку ўдзельніка (калі дадзены лічбавы ID удзельніка). Ужыванне: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], ці [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Перайсці",
        "redirect-lookup": "Шукаць:",
        "redirect-page": "Ідэнтыфікатар старонкі",
        "redirect-revision": "Версія старонкі",
        "redirect-file": "Назва файла",
+       "redirect-logid": "ID журнала",
        "redirect-not-exists": "Значэнне не знойдзена",
        "fileduplicatesearch": "Пошук дублікатных файлаў",
        "fileduplicatesearch-summary": "Пошук дублікатных файлах на падставе іх хэшаў.",
        "specialpages-group-wiki": "Вікізвесткі і прылады",
        "specialpages-group-redirects": "Адмысловыя старонкі-перасылкі",
        "specialpages-group-spam": "Прылады супраць спама",
+       "specialpages-group-developer": "Інструменты распрацоўшчыка",
        "blankpage": "Пустая старонка",
        "intentionallyblankpage": "Старонка наўмысна пакінута пустой, і ўжываецца для вымярэння хуткасці і падобнага.",
        "external_image_whitelist": " #Гэты радок пакіньце ў такім самым выглядзе<pre>\n#Упішыце часткі рэгулярных выразаў (тое, што пішуць паміж знакамі //) ніжэй\n#Гэта будзе параўноўвацца з адрасамі URL вонкавых выяваў, на якія ёсць спасылкі\n#Тыя з іх, дзе атрымаецца адпаведнасць, будуць паказаныя як выявы, а іначай толькі як спасылкі\n#Радкі, якія пачынаюцца з знака #, лічацца каментарамі\n#Малыя і вялікія літары не адрозніваюцца\n\n#Усе часткі рэгулярных выразаў павінны быць над гэтым радком. Сам радок пакіньце ў такім самым выглядзе</pre>",
        "tags-actions-header": "Дзеянні",
        "tags-active-yes": "Да",
        "tags-active-no": "Не",
+       "tags-source-extension": "Вызначаецца канчаткам назвы",
+       "tags-source-manual": "Ставіцца ўручную ўдзельнікамі і робатамі",
+       "tags-source-none": "Больш не выкарыстоўваецца",
        "tags-edit": "правіць",
+       "tags-delete": "сцерці",
+       "tags-activate": "актываваць",
+       "tags-deactivate": "адключыць",
        "tags-hitcount": "$1 {{PLURAL:$1|змена|змены|змен}}",
+       "tags-create-heading": "Стварыць новую бірку",
+       "tags-create-explanation": "Калі не ўказана іншае, новыя біркі будуць даступны для выкарыстання ўдзельнікам і робатам.",
+       "tags-create-tag-name": "Назва біркі:",
+       "tags-create-reason": "Прычына:",
+       "tags-create-submit": "Стварыць",
+       "tags-create-no-name": "Вы мусіце ўказаць назву біркі.",
+       "tags-create-invalid-chars": "Назвы бірак не павінны ўтрымліваць коскі (<code>,</code>) або касыя рысы (<code>/</code>).",
+       "tags-create-invalid-title-chars": "Назвы бірак не павінны ўтрымліваць сімвалы, якія нельга выкарыстоўваць у назвах старонак.",
+       "tags-create-already-exists": "Бірка \"$1\" ужо ёсць.",
+       "tags-create-warnings-below": "Вы хочаце прадоўжыць стварэнне біркі?",
+       "tags-delete-title": "Сцерці бірку",
+       "tags-delete-explanation-initial": "Вы збіраецеся выдаліць бірку \"$1\" з базы звестак.",
+       "tags-delete-explanation-warning": "Гэта дзеянне <strong>незваротнае</strong> і <strong>не можа быць адкочана</strong> нават адміністратарамі базы звестак. Упэўніцеся, што гэта тая бірка, што вы хочаце выдаліць.",
+       "tags-delete-reason": "Прычына:",
+       "tags-delete-submit": "Незваротна сцерці гэту бірку",
+       "tags-delete-not-allowed": "Біркі, вызначаныя пашырэннем, нельга прыбраць, акрамя выпадкаў, калі гэта дазволена яўна.",
+       "tags-delete-not-found": "Бірка \"$1\" не існуе.",
+       "tags-delete-too-many-uses": "Бірка \"$1\" прыменена ў больш чым $2 {{PLURAL:$2|версіі|версіях}}, а значыць, яна не можа быць сцёрта.",
+       "tags-delete-warnings-after-delete": "Бірка \"$1\" была сцёрта, але {{PLURAL:$2|1=атрымана наступнае папярэджанне|атрыманы наступныя папярэджанні}}:",
+       "tags-activate-title": "Актываваць бірку",
+       "tags-activate-question": "Вы збіраецеся актываваць бірку \"$1\".",
+       "tags-activate-reason": "Прычына:",
+       "tags-activate-not-allowed": "Немагчыма актываваць бірку \"$1\".",
+       "tags-activate-not-found": "Бірка \"$1\" не існуе.",
+       "tags-activate-submit": "Актываваць",
+       "tags-deactivate-title": "Дэактываваць бірку",
+       "tags-deactivate-question": "Вы збіраецеся дэактываваць бірку \"$1\".",
+       "tags-deactivate-reason": "Прычына:",
+       "tags-deactivate-not-allowed": "Немагчыма дэактываваць бірку \"$1\".",
+       "tags-deactivate-submit": "Дэактываваць",
+       "tags-update-add-not-allowed-one": "Бірку \"$1\" нельга дадаваць уручную.",
+       "tags-edit-title": "Правіць біркі",
+       "tags-edit-manage-link": "Кіраванне біркамі",
+       "tags-edit-revision-selected": "{{PLURAL:$1|Выбраная версія|Выбраныя версіі}} [[:$2]]:",
+       "tags-edit-logentry-selected": "{{PLURAL:$1|Выбраны запіс|Выбраныя запісы}} журнала:",
+       "tags-edit-revision-legend": "Дадаць ці прыбраць біркі з {{PLURAL:$1|1=гэтай версіі|усіх $1 версій}}",
+       "tags-edit-logentry-legend": "Дадаць ці прыбраць біркі з {{PLURAL:$1|1=гэтага запісу|усіх $1 запісаў}} журнала",
+       "tags-edit-existing-tags": "Наяўныя біркі:",
+       "tags-edit-existing-tags-none": "<em>Няма</em>",
+       "tags-edit-new-tags": "Новыя біркі:",
+       "tags-edit-add": "Дадаць гэтыя біркі:",
+       "tags-edit-remove": "Сцерці гэтыя біркі:",
+       "tags-edit-remove-all-tags": "(сцерці ўсе біркі)",
+       "tags-edit-chosen-placeholder": "Выберыце біркі",
+       "tags-edit-chosen-no-results": "Не знойдзена бірак, якія б адпавядалі запыту",
+       "tags-edit-reason": "Прычына:",
+       "tags-edit-nooldid-title": "Недапушчальная мэтавая версія",
        "comparepages": "Параўнанне старонак",
        "compare-page1": "Старонка 1",
        "compare-page2": "Старонка 2",
        "htmlform-cloner-create": "Дадаць яшчэ",
        "htmlform-cloner-delete": "Сцерці",
        "htmlform-cloner-required": "Неабходна хаця б адно значэнне.",
+       "htmlform-title-not-exists": "$1 не існуе.",
+       "htmlform-user-not-exists": "<strong>$1</strong> не існуе.",
        "sqlite-has-fts": "$1 з падтрымкай поўна-тэкставага пошуку",
        "sqlite-no-fts": "$1 без падтрымкі поўна-тэкставага пошуку",
        "logentry-delete-delete": "$1 {{GENDER:$2|сцёр|сцёрла}} старонку $3",
        "logentry-upload-upload": "$1 {{GENDER:$2|уклаў|уклала}} $3",
        "logentry-upload-overwrite": "$1 {{GENDER:$2|уклаў|уклала}} новую версію $3",
        "logentry-upload-revert": "$1 {{GENDER:$2|уклаў|уклала}} $3",
+       "log-name-managetags": "Журнал кіравання біркамі",
+       "log-name-tag": "Журнал бірак",
        "rightsnone": "(няма)",
        "revdelete-summary": "тлумачэнне праўкі",
        "feedback-adding": "Даданне водгуку на старонку…",
+       "feedback-back": "Назад",
        "feedback-bugcheck": "Выдатна! Толькі праверце, што ў спісе [$1 вядомых памылак] яе няма падобнага запісу.",
        "feedback-bugnew": "Я праверыў. Паведаміць пра новую памылку",
        "feedback-bugornote": "Калі вы гатовыя падрабязна апісаць тэхнічную праблему, калі ласка, [$1 паведаміце пра памылку].\nУ адваротным выпадку вы можаце выкарыстоўваць гэтую простую форму. Ваш каментар будзе дададзены на старонку «[$3 $2]» разам з вашым імем удзельніка і выкарыстоўваемым браўзерам.",
        "feedback-cancel": "Адмена",
        "feedback-close": "Зроблена.",
+       "feedback-error-title": "Памылка",
        "feedback-error1": "Памылка. Невядомы вынік з API",
        "feedback-error2": "Памылка. Збой праўкі",
        "feedback-error3": "Памылка. Няма адказу ад API",
        "feedback-message": "Паведамленне",
        "feedback-subject": "Тэма:",
-       "feedback-submit": "Даслаць водгук",
+       "feedback-submit": "Даслаць",
        "feedback-thanks": "Дзякуй! Ваш водгук размешчаны на старонцы «[$2 $1]».",
        "searchsuggest-search": "Знайсці",
        "searchsuggest-containing": "змяшчае...",
        "expand_templates_generate_xml": "Паказаць дрэва сінтаксічнага аналізу XML",
        "expand_templates_generate_rawhtml": "Паказаць зыходны код HTML",
        "expand_templates_preview": "Перадпаказ",
-       "pagelanguage": "Ð\92Ñ\8bбаÑ\80 Ð¼Ð¾Ð²Ñ\8b старонкі",
+       "pagelanguage": "Ð\97мÑ\8fнÑ\96Ñ\86Ñ\8c Ð¼Ð¾Ð²Ñ\83 старонкі",
        "pagelang-name": "Старонка",
        "pagelang-language": "Мова",
        "pagelang-use-default": "Прадвызначаная мова",
        "pagelang-select-lang": "Выберыце мову",
+       "pagelang-submit": "Адправіць",
        "right-pagelang": "Змяняць мову старонкі",
        "action-pagelang": "змяняць мову старонкі",
        "log-name-pagelang": "Журнал змянення мовы",
        "log-description-pagelang": "Гэта журнал змяненняў у мовах старонкі.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|змяніў|змяніла}} мову старонкі $3 з $4 на $5.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|змяніў|змяніла}} мову $3 з $4 на $5.",
        "default-skin-not-found": "Упс! Прадвызначаная вокладка для вашай вікі (<code>$wgDefaultSkin</code>), <code>$1</code>, недаступна.\n\nВыглядае на тое, што ваша інсталяцыя ўключае наступныя вокладкі. Гл. [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя: Устаноўка вокладак] дзеля інфармацыі па ўключэнні і выбару прадвызначанай вокладкі.\n\n$2\n\n; Калі вы толькі што ўстанавілі MediaWiki:\n: Магчыма, вы ўстанавілі з git, ці наўпрост з зыходнага коду, выкарыстаўшы іншы метад. Гэта нармальна. Паспрабуйце ўстанавіць некалькі вокладак з [https://www.mediawiki.org/wiki/Category:All_skins каталога вокладак mediawiki.org], такім чынам:\n:* Узяўшы [https://www.mediawiki.org/wiki/Download tarball-інсталятар], які ўтрымлівае некалькі вокладак і прыставак. Вы можаце скапіяваць і ўставіць каталог <code>skins/</code> з яго.\n:* Зрабіўшы клон  аднаго з сховішчаў <code>mediawiki/skins/*</code> праз git у каталог <code>skins/</code> вашай інсталяцыі MediaWiki.\n: Калі вы распрацоўшчык MediaWiki, гэта не павінна ўплываць на ваша git-сховішча.\n\n; Калі вы толькі што абнавілі MediaWiki:\n: MediaWiki 1.24 і навейшыя больш не падключаюць вокладкі аўтаматычна (гл. [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Інструкцыя: Аўтавызначэнне вокладак]). Вы можаце ўставіць наступныя радкі ў <code>LocalSettings.php</code>, каб падключыць усе ўстаноўленыя вокладкі:\n\n<pre>$3</pre>\n\n; Калі вы толькі што змянілі <code>LocalSettings.php</code>:\n: Пераправерце назвы вокладак на прадмет памылак.",
        "default-skin-not-found-no-skins": "Упс! Прадвызначаная вокладка для вашай вікі (<code>$wgDefaultSkin</code>), <code>$1</code>, недаступна.\n\nВы не ўстанавілі вокладкі.\n\n; Калі вы толькі што ўстанавілі ці абнавілі MediaWiki:\n: Магчыма, вы ўстанавілі з git, ці наўпрост з зыходнага коду, выкарыстаўшы іншы метад. Гэта нармальна. MediaWiki 1.24 і навейшыя не ўключаюць вокладкі ў асноўнае сховішча. Паспрабуйце ўстанавіць некалькі вокладак з [https://www.mediawiki.org/wiki/Category:All_skins каталога вокладак mediawiki.org], такім чынам:\n:* Узяўшы [https://www.mediawiki.org/wiki/Download tarball-інсталятар], які ўтрымлівае некалькі вокладак і прыставак. Вы можаце скапіяваць і ўставіць каталог <code>skins/</code> адтуль.\n:* Зрабіўшы клон аднаго з сховішчаў <code>mediawiki/skins/*</code> праз git у каталог <code>skins/</code> вашай інсталяцыі MediaWiki.\n: Калі вы распрацоўшчык MediaWiki, гэта не павінна адбіцца на вашым git-сховішчы. Гл. [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя: Настройка вокладак] дзеля інфармацыі па ўключэнні вокладак і выбары прадвызначэння.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (уключана)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>выключана</strong>)",
+       "mediastatistics-header-unknown": "Невядомыя",
+       "mediastatistics-header-bitmap": "Растравыя выявы",
+       "mediastatistics-header-drawing": "Рысункі (вектарныя выявы)",
+       "mediastatistics-header-total": "Усе файлы",
+       "json-error-state-mismatch": "Недапушчальны або некарэктны JSON",
+       "json-error-syntax": "Памылка сінтаксісу",
        "special-characters-group-latin": "Лацінскія",
        "special-characters-group-latinextended": "Лацінскія дадатковыя",
        "special-characters-group-ipa": "IPA",
index 7d8303e..bb8bf06 100644 (file)
        "watchlistanontext": "За преглеждане и редактиране на списъка за наблюдение се изисква влизане в системата.",
        "watchnologin": "Не сте влезли",
        "addwatch": "Добавяне към списъка за наблюдение",
-       "addedwatchtext": "Страницата „'''[[:$1]]'''“ и беседата й бяха добавени към [[Special:Watchlist|списъка ви за наблюдение]].",
+       "addedwatchtext": "Страницата „'''[[:$1]]'''“ и беседата ѝ бяха добавени към [[Special:Watchlist|списъка ви за наблюдение]].",
        "addedwatchtext-short": "Страницата „$1“ беше добавена към списъка Ви за наблюдение.",
        "removewatch": "Премахване от списъка за наблюдение",
-       "removedwatchtext": "Страницата „[[:$1]]“ и беседата й бяха премахнати от [[Special:Watchlist|списъка ви за наблюдение]].",
+       "removedwatchtext": "Страницата „[[:$1]]“ и беседата ѝ бяха премахнати от [[Special:Watchlist|списъка ви за наблюдение]].",
        "removedwatchtext-short": "Страницата „$1“ беше премахната от списъка Ви за наблюдение.",
        "watch": "Наблюдение",
        "watchthispage": "Наблюдаване на страницата",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|версия беше внесена|версии бяха внесени}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|една версия беше внесена|$1 версии бяха внесени}} от $2",
        "javascripttest": "Тестване на JavaScript",
-       "javascripttest-pagetext-noframework": "Тази страница е запазена за изпълнение на Джаваскрипт тестове.",
        "javascripttest-pagetext-unknownaction": "Неизвестно действие \"$1\".",
-       "javascripttest-pagetext-frameworks": "Моля, изберете една от предложените тестови структури: $1",
-       "javascripttest-pagetext-skins": "Избор на облик за тестванията:",
        "javascripttest-qunit-intro": "Вижте [$1 тестовата документация] на mediawiki.org.",
        "tooltip-pt-userpage": "Вашата потребителска страница",
        "tooltip-pt-anonuserpage": "Потребителската страница за адреса, от който редактирате",
index c4b6b67..924dc8e 100644 (file)
@@ -6,7 +6,8 @@
                        "Rachitrali",
                        "Mjbmr",
                        "Macofe",
-                       "Hosseinblue"
+                       "Hosseinblue",
+                       "Dalba"
                ]
        },
        "tog-underline": "لینکانی جهلگا خط کشیتین",
@@ -88,7 +89,7 @@
        "february-gen": "فیبروری",
        "march-gen": "مارچ",
        "april-gen": "اپریل",
-       "may-gen": "می",
+       "may-gen": "مای",
        "june-gen": "جون",
        "july-gen": "جولای",
        "august-gen": "اگوست",
        "feb": "فیبروری",
        "mar": "مارچ",
        "apr": "اپریل",
-       "may": "می",
+       "may": "مای",
        "jun": "جون",
        "jul": "جولای",
        "aug": "اگوست",
        "mypage": "تاکدیم",
        "mytalk": "گپ",
        "anontalk": "ای آی پی نشانی ئی باره ئا گپ",
-       "navigation": "ناوبری",
+       "navigation": "جهت یابي",
        "and": "&#32;و",
        "qbfind": "ودی کورتین",
        "qbbrowse": "مرور",
        "variants": "لهجه ئان",
        "navigation-heading": "ناوبری مینو",
        "errorpagetitle": "خطا",
-       "returnto": "بیئرگشت بئ $1.",
+       "returnto": "بیئرگشت به $1.",
        "tagline": "شه {{SITENAME}}",
        "help": "کومک",
        "search": "گشتین",
        "searchbutton": "گشتین",
        "go": "برا",
-       "searcharticle": "برا",
+       "searcharticle": "بررÙ\87",
        "history": "تاکدیمی تاریخچه",
        "history_short": "تاریخچه",
        "updatedmarker": "نئ آخرین آپڈیٹا نشان داتین",
        "viewhelppage": "کومکی تاکدیما نشان داتین",
        "categorypage": "دیستین تهری تاکدیمی",
        "viewtalkpage": "گپ تاکدیمی نشان داتین",
-       "otherlanguages": "بی دیگه زبانانی تا",
+       "otherlanguages": "به دیگه زبانانی‌تا",
        "redirectedfrom": "(گردینته بوته شه $1 ئا)",
        "redirectpagesub": "تاکدیمی تغییرمسیر داتین",
        "redirectto": "گردینتین په:",
-       "lastmodifiedat": "ای تاکدیم آخرین‌ وارا بی $1 سائت $2 تا تغییر بوته.",
+       "lastmodifiedat": "ای تاکدیم آخرین‌ وارا بِه $1‌ تاریخئا و $2 ساعت‌‌ئا گردینته بوته.",
        "viewcount": "شه ای تاکدیما کسی {{PLURAL:$1|یکوار|$1ور}} دیدن کورته.",
        "protectedpage": "قُلپ بوتگین تاکدیم",
-       "jumpto": "جوپ کورتین بی:",
-       "jumptonavigation": "ناوبری",
+       "jumpto": "جوپ کورتین بِه:",
+       "jumptonavigation": "جهت یابي",
        "jumptosearch": "گشتین",
        "view-pool-error": "متاسفانه موچین سرویس بی انونین وختا باز مشغول انت.\nبازین شه کار گیروکان لوٹنت که ای تاکدیما بگیندنت. \nمهربانی بکنیت دیم شه ایشی که پدا په ای تاکدیمی دیستینا کوشش بکنیت یک کمی صبر بکنیت.\n\n$1",
        "generic-pool-error": "متاسفانه موچین سرویس بی انونین وختا باز مشغول انت.\nبازین شه کار گیروکان لوتنت که ای تاکدیما بگیندنت. \nمهربانی بکنیت دیم شه ایشی که پدا په ای تاکدیمی دیستینا کوشش بکنیت یک کمی صبر بکنیت.",
        "pool-servererror": "پول سنتر سرویس بی دسترس ئا نه اینت ( $1 ).",
        "poolcounter-usage-error": "خطا استفاده شه: $1",
        "aboutsite": "بی بارها {{SITENAME}}",
-       "aboutpage": "Project:بی بارها",
+       "aboutpage": "Project:بِه باره‌ئا",
        "copyright": "محتوایات بی  $1 اجازه نامه ئا هستنت مگه ای که آی خلاف ئا ذکر بوته بیئنت .",
        "copyrightpage": "{{ns:project}}:کاپی رایت یا باز کورتینی حق",
-       "currentevents": "اÙ\86Ù\88Ù\86Û\8cÙ\86 Ù\88اÙ\82ئات",
-       "currentevents-url": "Project:اÙ\86Ù\88Ù\86Û\8cÙ\86 Ù\88اÙ\82ئاتان",
+       "currentevents": "اÙ\86Ù\88Ù\86Û\8cÙ\86 Ù\88اÙ\82عات",
+       "currentevents-url": "Project:اÙ\86Ù\88Ù\86Û\8cÙ\86 Ù\88اÙ\82عاتان",
        "disclaimers": "تکذیب‌ نامه‌هان",
-       "disclaimerpage": "Project:ئÙ\85Ù\88Ù\85Û\8c Ø¦Û\8cÙ\86 ØªÚ©Ø°Û\8cبâ\80\8c نامه",
+       "disclaimerpage": "Project:عÙ\85Ù\88Ù\85Û\8câ\80\8cئÛ\8cÙ\86 ØªÚ©Ø°Û\8cبâ\80\8câ\80\8cنامه",
        "edithelp": "کومک په ایدیت ئی خاتیرا",
        "helppage-top-gethelp": "کومک",
        "mainpage": "بُنیادی تاکدیم",
        "policy-url": "Project:سیاست‌ئان",
        "portal": "کار زوروکانئ داخل بوتین",
        "portal-url": "Project:کار زوروکانئ داخل بوتین",
-       "privacy": "سیاست محرمانگی",
-       "privacypage": "Project:سیاست محرمانگی",
+       "privacy": "محرمانگین سیاست",
+       "privacypage": "Project:محرمانگین سیاست",
        "badaccess": "دسترسی ئی خطا",
        "badaccess-group0": "شما اجازه په ای ئملی اجرائا که درخواست کورته ئیت نداریت.",
        "badaccess-groups": "ای ئملی که شما درخواست کورته ئیت مخصوص بی  {{PLURAL:$2|ای گروپ|ای گروپ ئان}} شه کار زوروکان اینت: $1.",
        "viewsourceold": "نشان داتین مبدائی",
        "editlink": "ایڈیٹ",
        "viewsourcelink": "نشان داتین مبدائی",
-       "editsectionhint": "ایدیت کورتین : $1 بخشی",
-       "toc": "Ù\85حتÙ\88Û\8cات",
+       "editsectionhint": "$1‌ئی: بخشێ ایڈیت کورتین",
+       "toc": "Ù\84Ú\91",
        "showtoc": "نشان داتین",
        "hidetoc": "چیهر داتین",
        "collapsible-collapse": "بستین",
        "feed-invalid": "هبر وانی وراک ئی قیسم جواز نداریت.",
        "feed-unavailable": "هبر وانی وراک ئان بی دسترس نه انت",
        "site-rss-feed": "آراس‌اس وراک په $1",
-       "site-atom-feed": "اتومئ وراک په $1",
+       "site-atom-feed": "اتومین وررگ په $1",
        "page-rss-feed": "آراس‌اس وراک په \"$1\"",
-       "page-atom-feed": "اتومي وراک په «$1»",
+       "page-atom-feed": "اتومين وررگ په «$1»",
        "red-link-title": "$1 ( دیم موجود نه اینت)",
        "sort-descending": "نزولین ترتیب کورتین",
        "sort-ascending": "صعودی ترتیب کورتین",
        "perfcached": "همراهی کنوکین دیتا شه نهانی ئین حافظهٔ ئا فراخوانی بوته و ممکن اینت کاملاً اپڈیٹ نه بوته. حداکثر {{PLURAL:$1|یک نتیجه| $1 نتیجه}} بي نهانی ئین حافظهٔ تا دسترس ئی وڈ اینت.",
        "perfcachedts": "همرای کنوکین دیتا شه نهانی ئین حافظه ئا فرخوانی بوته و آخرین وار  بئ  $1 ئی تا اپڈیٹ بوته. حداکثر {{PLURAL:$4|یک نتیجه|$4 نتیجه}} بئ نهانی ئین حافظه تا دسترس ئی وڈ اینت.",
        "querypage-no-updates": "ای تاکدیمی اپڈیٹ کورتین انون غیر فئال بوته.\nای تاکدیمی مئلومات ممکن اینت که نوک نه بوته انت.",
-       "viewsource": "Ù\86شاÙ\86 Ø¯Ø§ØªÛ\8cÙ\86 Ù\85بدائÛ\8c",
+       "viewsource": "Ù\85بدائÛ\8cÙ\86 Ù\86Ù\85اÛ\8cØ´",
        "viewsource-title": "مبدا ئی نشان داتین په $1",
        "actionthrottled": "شمی ئملی دیم گیپته بوت",
        "actionthrottledtext": "په دیمگیری شه اسپم شینک بوتینی خاتیرا، په شما اجازه نه اینت که ایرنگین ئملی ئا چینکه وار بی یک کمین وختی تا انجام دهیت.\nمهربانی بکنیت پد شه چینکه دقیقه ئا کوشش بکنیت.",
        "filereadonlyerror": "«$1» ئی فایلئ تغیر داتین ممکن نه اینت چون ه «$2» ئی فایلي مخزن فقط بی وانتینی ئین  حالت ئی تا قرار داریت.\n\nمدیری که آیرا قُلپ کورته ایرنگ توضیح داته:  «$3».",
        "invalidtitle-knownnamespace": "نا موتبرین ئنوان گو نامئ فضای  «$2» و متن ئی  «$3»",
        "invalidtitle-unknownnamespace": "ناموتبرین ئنوان گو نا زاتین نامئ فضای شماره  $1 و متن ئی «$2»",
-       "exception-nologin": "لاگین نه بوته ئیت",
+       "exception-nologin": "لاگین نه بوتهئیت",
        "exception-nologin-text": "مهربانی بئ [[Special:Userlogin|تا داخل بیئت]] تا بتوانیت بئ ای تاکدیما دسترسی داشته بئیت.",
        "exception-nologin-text-manual": "مهربانئ بکنیت  $1  تا بتوانیت بئ ای تاکدیم یا عمل ئا دسترسی داشته بئیت .",
        "virus-badscanner": "بدین پیکربندی: نازانتین ویروس ئی سکن کورتین: ''$1''",
        "userloginnocreate": "داخل بوتین",
        "logout": "در بوتین",
        "userlogout": "در بوتین",
-       "notloggedin": "لاگین نه بوته ئیت",
+       "notloggedin": "لاگین نه بوتهئیت",
        "userlogin-noaccount": "شما کار زوروکین حسابئ نداریت؟",
        "userlogin-joinproject": "بی  {{SITENAME}} تا نام‌نویسی کنیت!",
        "nologin": "شما کار زوروکین حسابئ نداریت ؟ $1.",
        "userlogin-createanother": "دیگرین کار زوروکین حسابئ جوڑ کورتین",
        "createacct-emailrequired": "ایمیل ادرس",
        "createacct-emailoptional": "ایمیل ادرس (اختیاری)",
-       "createacct-email-ph": "وتئ ایمیل ادرسا داخل بکنیت",
+       "createacct-email-ph": "وتي ایمیل ادرسا داخل بکنیت",
        "createacct-another-email-ph": "ایمیل ادرسی داخل کورتین",
        "createaccountmail": "استفاده شه تصادفین پاسوردا و آیی دیم داتین بی مشخصین ایمیل ادرسیا",
        "createacct-realname": "واقئین نام (اختیاری)",
        "createaccountreason": "دلیل:",
        "createacct-reason": "دلیل",
        "createacct-reason-ph": "پچی شما لوٹیت که دیگرین کار زوروکین حساب جوڑ کنیت؟",
-       "createacct-submit": "وتئ کار زوروکین حسابا جوڑ کنیت",
+       "createacct-submit": "وتي کار زوروکین حسابا جوڑ کنیت",
        "createacct-another-submit": "دیگرین کار زوروکین حسابئ جوڑ کورتین",
        "createacct-benefit-heading": "ای {{SITENAME}} چو شمیا همیرنگین مردمانی واسطه ئا جوڑ بوته",
        "createacct-benefit-body1": "{{PLURAL:$1|ایڈیٹ}}",
        "subject": "موضو/ئنوان:",
        "minoredit": "ای یک گونڈین ایڈیٹئ است",
        "watchthis": "دیستین ای تاکدیمی",
-       "savearticle": "اÛ\8c ØªØ§Ú©Ø¯Û\8cÙ\85 Ø°Ø®Û\8cرÙ\87 Ø¨Û\8cئت",
+       "savearticle": "تاکدÛ\8cÙ\85ئ Ø³Ø§ØªÛ\90تÛ\8cÙ\86",
        "preview": "دیم دیست",
        "showpreview": "دیم دیست",
        "showdiff": "تغیراتانئ نشان داتین",
        "previousrevision": "→ قدیمین نخسه",
        "nextrevision": "نوکین نخسه ←",
        "currentrevisionlink": "انونین نخسه یی نشان داتین",
-       "cur": "فعلی",
+       "cur": "انونین",
        "next": "بعدی",
        "last": "دیمتیرین",
        "page_first": "اولین",
        "difference-title": "$1: نخسه ئانی مانجینا فرق",
        "difference-title-multipage": "$1 و $2:تاکدیمانئ مانجینی فرق",
        "difference-multipage": "(تاکدیمانی مانجینا فرق)",
-       "lineno": "سطر $1:",
+       "lineno": "$1‌ئین سطر:",
        "compareselectedversions": "انتخاب بوته ئین نخسه ئانی مقایسه",
        "showhideselectedversions": "انتخاب بوته ئین نخسه ئانی پدیداری تغیر",
        "editundo": "خنثی‌ کورتین",
        "search-result-size": "$1 ({{PLURAL:$2|یک کلیمه|$2 کلیمه}})",
        "search-result-category-size": "{{PLURAL:$1|یک عضو|$1 عضو}} ({{PLURAL:$2|یک گۆنڈ تهر|$2 گۆنڈ تهر}}، {{PLURAL:$3|یک فایل|$3 فایل}})",
        "search-redirect": "($1 یي گردینتین)",
-       "search-section": "(بخش $1)",
+       "search-section": "($1 بخش)",
        "search-category": "(تهر  $1)",
        "search-file-match": "(فایلی محتوایی یکرنگی)",
        "search-suggest": "آیا شمی منظور ایش ات: $1",
        "showingresults": "نشان داتین حداکثر {{PLURAL:$1|'''۱''' نتیجه|'''$1''' نتیجه}} بی جهلگا، شرو شه شماره ئی  '''$2'''.",
        "showingresultsinrange": "نمایش بی جهلگا {{PLURAL:$1|<strong>1</strong> نتیجه|<strong>$1</strong> نتیجه}} بی محدودهٔ ئی #<strong>$2</strong> تا #<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|نتیجه ئان <strong>$1</strong> شه <strong>$3</strong>|نتیجه ئان <strong>$1 - $2</strong> شه <strong>$3</strong>}}",
-       "search-nonefound": "نتیجه په چیزی که شما لوٹیته تیت بی دست نه یات.",
+       "search-nonefound": "نتیجه په چیزی که شما لوٹیته‌تیت به‌دست نه یات.",
        "powersearch-legend": "پیشرفته ئین گشتین",
        "powersearch-ns": "گشتین بی نامئ فضائان:",
        "powersearch-togglelabel": "چیک کورتین:",
        "recentchanges-noresult": "هیچ تغیری بئ تعین بوته ئین دوره ئی تا گۆ ای معیاران هموانی نداشت.",
        "recentchanges-feed-description": "به ائ ویکیێ تا نۆکین و آخیرئین تغیرانه به ای فیڈئ تا بگیندێت.",
        "recentchanges-label-newpage": "ای ایڈیٹ نوکین تاکدیمی ئا جوڑ کورت",
-       "recentchanges-label-minor": "ای یک گونڈین ایڈیٹئ است",
-       "recentchanges-label-bot": "ای ایڈیٹا یک ربات ئی کورته",
+       "recentchanges-label-minor": "ای یک گونڈین ایڈیٹئ اینت",
+       "recentchanges-label-bot": "ای ایڈیٹا یک رباتئی کورته",
        "recentchanges-label-unpatrolled": "ای ایڈیٹ تا انون گشت وارته نه بوته",
-       "recentchanges-label-plusminus": "تاکدیمئ حجم بئ ای اندازگ بایٹ ئا تغیر کورته",
+       "recentchanges-label-plusminus": "تاکدیمئ حجم بِه ای اندازگ بایٹ‌ئا تغیر کورته",
        "recentchanges-legend-heading": "<strong>اختصارئان:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (همیرنگ بی [[Special:NewPages|نوکین تاکدیمانئ لڑ لیست]] ئا سیل بکنیت)",
        "rcnotefrom": "بِه جهلگا تغیرات شه <strong>$3, $4</strong> (تا <strong>$1</strong> {{PLURAL:$5|نشان داته بوته|نشان داته انت}}).",
        "rcshowhidecategorization-show": "نشان داتین",
        "rcshowhidecategorization-hide": "چیهر داتین",
        "rclinks": "نشان داتین $1 آخیر ئین تغییر بئ $2 اخیرین روچا<br />$3",
-       "diff": "تفاوت",
+       "diff": "فرق",
        "hist": "تاریخچه",
        "hide": "چیهر داتین",
        "show": "نشان داتین",
        "recentchangeslinked-toolbox": "مربوتین تغیراتان",
        "recentchangeslinked-title": "مربوتین تغیراتان گو $1",
        "recentchangeslinked-summary": "بئ جهلگا یک لڑلیست ئی شه آخیرئین ٹگلان گیندیت که بئ تاکدیما لینک بوته انت (یا چَمّی چیهری شریکین تهر) ئانه گیندیت .\nآ تاکدیمان که [[Special:Watchlist|شمی پدگیری لیست]] ئی تا به ینت '''پررنگ''' نشان داته ئه به ینت.",
-       "recentchangeslinked-page": "تاکدیم نام:",
+       "recentchangeslinked-page": "تاکدیمئ نام:",
        "recentchangeslinked-to": "نشان داتین تاکدیماني تغیرات که گۆ ای تاکدیما لینک دارنت",
        "recentchanges-page-added-to-category": "[[:$1]] به تهرئ تا اڈ بوت",
        "recentchanges-page-added-to-category-bundled": "[[:$1]] و {{PLURAL:$2|یک دیم|$2 pages}} به تهرئ تا اڈ بوتنت",
        "filehist-dimensions": "ابعاد",
        "filehist-filesize": "فایلی اندازه",
        "filehist-comment": "کومنیت",
-       "imagelinks": "بی کار گیپتین فایلئ",
+       "imagelinks": "کار گیپتین شه فایلا",
        "linkstoimage": "{{PLURAL:$1|تاکدیم|تاکدیمان}} جهلگین بی اکسا لینک {{PLURAL:$1|داریت|دارنت}}:",
        "linkstoimage-more": "گیشتیر شه $1 تاکدیم گۆ ای فایلا لینک {{PLURAL:$1|داریت|دارنت}}.\nجهلگی لڑ تانا {{PLURAL:$1|اولین لینک|اولین $1 لینک}} گۆ ای دیما نشان ئا دنت.\n[[Special:WhatLinksHere/$2|کامیلین لیست]] هم موجود اینت.",
        "nolinkstoimage": "شه ای فایلا بِه هیچ تاکدیمئ تا کار گیپته نه بوته.",
        "listduplicatedfiles-entry": "[[:File:$1|$1]][[$3|{{PLURAL:$2|یک تکرار|$2 تکرار}}]] داریت.",
        "unusedtemplates": "استفاده نه بوته ئین تراشوانان",
        "unusedtemplateswlh": "دیگه لینک ئان",
-       "randompage": "تصادفی مقاله",
+       "randompage": "تصادفین مقاله",
        "randomincategory": "تصادفین تاکدیم بئ تهر ئی تا",
        "randomincategory-invalidcategory": "«$1» یک موتبرین نامئ په تهر ئان نه اینت.",
        "randomincategory-nopages": "هیچ تاکدیمی بئ  [[:Category:$1|$1]] ئی تهری تا موجود نه اینت.",
        "allpagesto": "تاکدیمانئ نشان داتین الاسئ گو:",
        "allarticles": "موچین تاکدیمان",
        "allinnamespace": "موچین تاکدیمان ($1 نامی فضا)",
-       "allpagessubmit": "برا",
+       "allpagessubmit": "بررÙ\87",
        "allpagesprefix": "تاکدیمانی نمایش گۆ دیمۆندا:",
        "allpagesbadtitle": "شمی درخواستین ئنوان ناموتبر،خالی،یا میان زبانین یا میان ویکی ئین ئنوان و یا شه خرابین لینکی است.\nممکن اینت که یک یا چینکه نویسگ داشته بیئت که نتوانن آوانا بئ تاکدیمانی ئنوانانی تا استیپاده کنن.",
        "allpages-bad-ns": "{{SITENAME}} ، «$1» ئی نامی فضا ئا نداریت.",
        "deleteprotected": "شما نه توانیت که ای تاکدیما پاک کنیت چون که شه آیی محافظت بوته.",
        "deleting-backlinks-warning": "''' هشدار:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|دیگرین تاکدیم]] هستنت که گۆ ای تاکدیما که شما ئه لوٹیت آیرا پاک بکنیت لینک بوته انت.",
        "rollback": "ایڈیٹئ بیئرگردینتین",
-       "rollbacklink": "بÛ\8cجا Ø¢Ù\88رتین",
+       "rollbacklink": "بÛ\8cرگردÛ\8cÙ\86â\80\8cتین",
        "rollbacklinkcount": "بیئرگردینتین $1 {{PLURAL:$1|ایڈیٹ|ایڈیٹ هانئ}}",
        "rollbacklinkcount-morethan": "بیئرگردینتین گیشتیر شه $1 ایڈیٹا",
        "rollbackfailed": "بیئرگردینته نه بوت",
        "blocklink": "بلاک یا بستین",
        "unblocklink": "پاچ یا انبلاک بێت",
        "change-blocklink": "بلاک ئی تغیرداتین",
-       "contribslink": "مشارکت ئان",
+       "contribslink": "شراکت‌ئان",
        "emaillink": "ایمیلی دیم داتین",
        "blocklogpage": "کورمئ بستین",
        "blocklogentry": "«[[$1]]» ئا تا $2 بست $3",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} وارد بوته",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} داخل بوته شه $2",
        "javascripttest": "جاوا اسکریپتی آزمایش",
-       "javascripttest-pagetext-noframework": "ای تاکدیم په جاوا اسکریپتی آزمایشی خاتیرا ایشته بوته.",
        "javascripttest-pagetext-unknownaction": "نازانتین اکشن \"$1\".",
-       "javascripttest-pagetext-skins": "پوسته‌ای ئا په آزمایشانی اجرا ئا انتخاب کنیت:",
        "javascripttest-qunit-intro": "[$1 آزمایشی مشتندانا] بئ mediawiki.org تا بگیندیت.",
        "tooltip-pt-userpage": "{{GENDER:|شمئ کار زُورۆکین}} تاکدیم",
        "tooltip-pt-mytalk": "{{GENDER:|شمئ}} حبر و گپئ تاکدیم",
        "tooltip-pt-preferences": "{{GENDER:|شمئ}} تنظیماتان",
        "tooltip-pt-watchlist": "آ دیمانی لیست که شما آوانی تغیرانا پدگیری ئا کنیت",
        "tooltip-pt-mycontris": "{{GENDER:|شمئ}} شراکتاني لڑ",
-       "tooltip-pt-login": "توصیه ئه کنن که بئ سایٹ ئی تا داخل بئیت. اگرچه که ای کار په جبر و زور نه اینت",
+       "tooltip-pt-login": "توصیه ئه کنن که بِه سایٹ‌ئی تا داخل به‌ئێت. اگرچه ای کار په جبر و زور نه اینت",
        "tooltip-pt-logout": "در بوتین",
-       "tooltip-pt-createaccount": "شه شما ئه لوٹن که په وت یک کار زوروکئ حساب ئی جۆڑ بکنیت و بئ سایٹ ئی تا داخل بئیت؛هرچینکه که ای کار جبری نه اینت",
+       "tooltip-pt-createaccount": "شه شما ئه لوٹن که په وت یک کار زوروکین حساب‌ئی جۆڑ بکنیت و بِه سایٹ‌ئی تا داخل به‌ئێت؛هرچینکه که ای کار جبری نه اینت",
        "tooltip-ca-talk": "ای دیمی محتوا ئانی باره ئا حبر و گپ",
        "tooltip-ca-edit": "شما ئا توانیت که ای دیما ایڈیٹ بکنیت. مهربانی بکنیت دیم شه ایشی که ای دیما ذخیره بکنیت، شه دیم دیست ئا استفاده بکنیت.",
        "tooltip-ca-addsection": "نوکین بخشی جۆڑ بکنیت",
        "tooltip-ca-move": "ای تاکدیمی انتقال",
        "tooltip-ca-watch": "اضافه کورتین ای تاکدیمی بی نی واچلیستی تا",
        "tooltip-ca-unwatch": "ڈیلیٹ کورتین ای تاکدیمی شه نی واچلیستی لڑ لیستا",
-       "tooltip-search": "گشتین بی {{SITENAME}}",
-       "tooltip-search-go": "اگÙ\87 Ø§Ù\85کاÙ\86 Ø¯Ø§Ø´ØªÙ\87 Ø¨Û\8cئت ØªØ§Ú©Ø¯Û\8cÙ\85Û\8c ØªØ§ Ú¯Ù\88 Ø§Û\8c Ù\86اÙ\85ا Ø¨Ø±Ø§",
-       "tooltip-search-fulltext": "گشتین په ای کلمه ئی خاتیرا بی تاکدیمانی تا",
+       "tooltip-search": "گشتین بِه {{SITENAME}}‌ئی تا",
+       "tooltip-search-go": "اگÙ\87 Ø§Ù\85کاÙ\86 Ø¯Ø§Ø´ØªÙ\87 Ø¨Û\90ت Ø¨Ù\87 Ø§Û\8c Ù\86اÙ\85 Ù\88Ù\84ائÛ\8cÙ\86 ØªØ§Ú©Ø¯Û\8cÙ\85Û\8c ØªØ§ Ø¨Ø±Ø±Ù\87",
+       "tooltip-search-fulltext": "به تاکدیمانی تا گشتین په ای کلمه‌ئی خاتیرا",
        "tooltip-p-logo": "بُنیاد ئین تاکدیمی دیستین",
        "tooltip-n-mainpage": "بُنیاد ئین تاکدیمی دیستین",
        "tooltip-n-mainpage-description": "بُنیاد ئین تاکدیمی دیستین",
-       "tooltip-n-portal": "بی پروژه ئی موریدا٬ آنچه که توانیت انجام دهیت و ای که چی چیزی ئا شه گوجا ودی بکنیت",
+       "tooltip-n-portal": "بِه پروژه‌ئی موریدا٬ آنچه که توانێت انجام دهیت و ای که چی چیزی‌ئا شه گوجا ودی بکنێت",
        "tooltip-n-currentevents": "پدزمینه ئین مئلوماتئ بدست آورتین شه انونین رویداد ئان",
        "tooltip-n-recentchanges": "ائ ویکیێ نۆکین و آخیرئین تغیراني لڑ",
-       "tooltip-n-randompage": "یک تصادفی ئین دیمی آورتین",
-       "tooltip-n-help": "جای په ودی کورتین ئا",
+       "tooltip-n-randompage": "یک تصادفیئین دیمی آورتین",
+       "tooltip-n-help": "جاگه په ودي کورتین‌ئا",
        "tooltip-t-whatlinkshere": "موچین تاکدیمانی لڑ لیست که گۆ ای دیما لینک وارته انت",
        "tooltip-t-recentchangeslinked": "تاکدیمانئ آخیرین تغیران که ای دیم گۆ آوان لینک داریت",
        "tooltip-feed-rss": "آراس‌اس ئی خبرنامه په ای تاکدیما",
        "tooltip-ca-nstab-help": "دیستین کومکی تاکدیمئ",
        "tooltip-ca-nstab-category": "دیستین تهری تاکدیمی",
        "tooltip-minoredit": "ای ایڈیٹ ئا گۆنڈ ایڈیٹ نشانگ کن",
-       "tooltip-save": "وتئ تغیرانا ذخیره بکنیت",
-       "tooltip-preview": "شمی تغیرانی دیم دیست، مهربانی بکنیت دیما شه تاکدیمی ذخیره کورتینا شه ای کیلی ئا استفاده بکنیت.",
-       "tooltip-diff": "شمی تغیرانی نمایش که شما بئ متن ئی تا داته ایت.",
+       "tooltip-save": "وتي تغیرانا ذخیره بکنیت",
+       "tooltip-preview": "شمئ تغیرانی دیم دیست، مهربانی بکنیت دیما شه تاکدیمی ذخیره کورتینا شه ای کیلی ئا استفاده بکنیت.",
+       "tooltip-diff": "شمی تغیرانی نمایش که شما بِه متن‌ئی تا داته ایت.",
        "tooltip-compareselectedversions": "ای تاکدمئ دو انتخاب بوته ئین نخسه ئاني فرقاني دیستین",
        "tooltip-watch": "ای دیما به وتي واچلیست یا پدگیری لیستئ تا اڈڈ بکنیت",
        "tooltip-watchlistedit-normal-submit": "ئنوانانی پاک کورتین",
        "pageinfo-hidden-categories": "چیهرین {{PLURAL:$1| تهر|تهر هان}} ( $1 )",
        "pageinfo-templates": "{{PLURAL:$1|تراشوان|تراشوان}} استفاده‌ بوته ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|تاکدیم|تاکدیمان}} ترانسکلوڈ بوتگ بئ ($1) تا",
-       "pageinfo-toolboxlink": "تاکدÛ\8cÙ\85ئ Ù\85ئلومات",
+       "pageinfo-toolboxlink": "تاکدÛ\8cÙ\85ئ Ù\85الومات",
        "pageinfo-redirectsto": "تغییر مسیر بی",
        "pageinfo-redirectsto-info": "مئلومات",
        "pageinfo-contentpage": "هیساب بوته بئ ئنوان مهتوائین دیمی",
        "exif-copyright": "کاپی رایٹ ئی واوُند",
        "exif-exifversion": "exif ئی نخسه",
        "exif-flashpixversion": "Flashpix ئی پُشتیوانی بوته ئین نخسه",
-       "exif-colorspace": "رنگانئ فضا",
+       "exif-colorspace": "رنگاني فضا",
        "exif-componentsconfiguration": "هریک شه مووله په ئانی مانا",
        "exif-compressedbitsperpixel": "اکس ئی پشرده ئی هالت",
        "exif-pixelydimension": "اکسئ گۆر",
        "watchlisttools-view": "مربوتین تغیرانی دیستین",
        "watchlisttools-edit": "دیدارلیست ئی دیستین و ایڈیٹ کورتین",
        "watchlisttools-raw": "واچلیستئ آمگین لیستانی ایڈیٹ",
+       "iranian-calendar-m1": "مولمان",
+       "iranian-calendar-m2": "کرا",
+       "iranian-calendar-m3": "سوچکان",
+       "iranian-calendar-m4": "جلکان",
+       "iranian-calendar-m5": "جلکشان",
+       "iranian-calendar-m6": "سچان",
+       "iranian-calendar-m7": "تۆمشان",
+       "iranian-calendar-m8": "سرتان",
+       "iranian-calendar-m9": "گوبشان",
+       "iranian-calendar-m10": "تاکشان",
+       "iranian-calendar-m11": "بهاران",
+       "iranian-calendar-m12": "اوسته‌مان",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|گپ و حبر]])",
        "version": "نخسه",
        "version-extensions": "لچیته گین اپزونه ئان",
        "version-libraries-license": "اجازه نامه",
        "version-libraries-description": "توضیحان",
        "version-libraries-authors": "نویسوکان",
-       "redirect-legend": "گردینتین په یک پایل یا تاکدیمئ",
        "redirect-submit": "برا",
        "redirect-lookup": "گشتین:",
        "redirect-value": "اندازه گ:",
index c7a5faf..000e61b 100644 (file)
        "category-media-header": "\"$1\" বিষয়শ্রেণীতে অন্তর্ভুক্ত মিডিয়া ফাইলগুলি",
        "category-empty": "''এই বিষয়শ্রণীতে বর্তমানে কোন পাতা বা মিডিয়া ফাইল নেই।''",
        "hidden-categories": "{{PLURAL:$1|লুকায়িত বিষয়শ্রেণী|লুকায়িত বিষয়শ্রেণীসমূহ}}",
-       "hidden-category-category": "লুকায়িত বিষয়শ্রেণীসমূহ",
+       "hidden-category-category": "লà§\81à¦\95à§\8dà¦\95ায়িত à¦¬à¦¿à¦·à¦¯à¦¼à¦¶à§\8dরà§\87ণà§\80সমà§\82হ",
        "category-subcat-count": "{{PLURAL:$2|এই বিষয়শ্রেণীতে কেবলমাত্র নিচের উপবিষয়শ্রেণীটি আছে।|এই বিষয়শ্রেণীতে অন্তর্ভুক্ত মোট $2টি উপবিষয়শ্রেণীর মধ্যে {{PLURAL:$1|টি উপবিষয়শ্রেণী|$1টি উপবিষয়শ্রেণী}} নিচে দেখানো হয়েছে।}}",
        "category-subcat-count-limited": "এই বিষয়শ্রেণীতে নিচের {{PLURAL:$1|টি উপবিষয়শ্রেণী|$1টি উপবিষয়শ্রেণী আছে}}।",
        "category-article-count": "{{PLURAL:$2|এই বিষয়শ্রেণীতে কেবল নিচের পাতাটি আছে।|এই বিষয়শ্রেণীতে অন্তর্ভুক্ত মোট $2টি পাতার মধ্যে {{PLURAL:$1|টি পাতা|$1টি পাতা}} নিচে দেখানো হল।}}",
        "nocookieslogin": "ব্যবহারকারীদের প্রবেশ সম্পন্ন করতে {{SITENAME}} কুকি ব্যবহার করে। আপনার ব্রাউজারে কুকি নিষ্ক্রিয় করা আছে। কুকি চালু করে আবার চেষ্টা করুন।",
        "nocookiesfornew": "ব্যবহারকারীর অ্যাকাউন্ট তৈরি হয়নি, কারণ এর উৎস সম্পর্কে আমরা নিশ্চিত নই।\nনিশ্চিত করুন আপনার কুকি সক্রিয় রয়েছে, পাতাটি পুনরায় লোড করে আবার চেষ্টা করুন।",
        "noname": "আপনি সঠিক ব্যবহারকারী নাম নির্দিষ্ট করেননি।",
-       "loginsuccesstitle": "পà§\8dরবà§\87শ à¦¸à¦«à¦²",
-       "loginsuccess": "'''আপনি এইমাত্র \"$1\" নামে {{SITENAME}}-তে প্রবেশ করেছেন।'''",
+       "loginsuccesstitle": "পà§\8dরবà§\87শ à¦\95রà§\87à¦\9bà§\87ন",
+       "loginsuccess": "<strong>আপনি এইমাত্র \"$1\" নামে {{SITENAME}}-তে প্রবেশ করেছেন।</strong>",
        "nosuchuser": "\"$1\" নামে কোন ব্যবহারকারী নেই।\nব্যবহারকারী নামের আকার সংবেদনশীল।\nআপনার বানান পরীক্ষা করে দেখুন, অথবা [[Special:UserLogin/signup|নতুন একটি অ্যাকাউন্ট খুলুন]]।",
        "nosuchusershort": "\"$1\" নামের কোন ব্যবহারকারী নেই। নামের বানান পরীক্ষা করুন।",
        "nouserspecified": "আপনাকে অবশ্যই ব্যবহারকারী নাম নির্দিষ্ট করতে হবে।",
        "noemail": "\"$1\" ব্যবহারকারীর জন্য কোন ই-মেইল ঠিকানা সংরক্ষিত নেই।",
        "noemailcreate": "আপনাকে অবশ্যই একটি সঠিক ইমেইল ঠিকানা দিতে হবে",
        "passwordsent": "একটি নতুন পাসওয়ার্ড \"$1\" ব্যবহারকারীর ই-মেইল ঠিকানায় পাঠানো হয়েছে। দয়াকরে তা পাওয়ার পর আবার লগ-ইন করুন।",
-       "blocked-mailpassword": "আপনার আইপি ঠিকানাটি থেকে সম্পাদনা করতে বাধা আছে, তাই এই ঠিকানার অপব্যবহার করে পাসওয়ার্ড ফেরত আনতে দেয়া যাবে না।",
+       "blocked-mailpassword": "আপনার আইপি ঠিকানাটি থেকে সম্পাদনা করতে বাধা আছে। অপব্যবহার রোধ করার জন্য, এই আইপি ঠিকানা থেকে পাসওয়ার্ড পুনরুদ্ধার করার অনুমতি দেয়া হয়নি।",
        "eauthentsent": "মনোনীত ই-মেইল ঠিকানায় একটি নিশ্চিতকরণ ই-মেইল পাঠানো হয়েছে।\nঐ অ্যাকাউন্টটে অন্য কোন ই-মেইল পাঠানোর আগে আপনাকে ই-মেইলের নির্দেশগুলি অনুসরণ করতে হবে, যাতে অ্যাকাউন্টটি যে আসলেই আপনার, তা নিশ্চিত হয়।",
        "throttled-mailpassword": "বিগত {{PLURAL:$1|ঘণ্টার|$1 ঘণ্টার}} মধ্যে ইতিমধ্যেই একবার পাসওয়ার্ড বদলের তথ্য পাঠানো হয়েছে। অপব্যবহার রোধে প্রতি {{PLURAL:$1|ঘণ্টায়|$1 ঘণ্টায়}} কেবল একবার পাসওয়ার্ড বদলের তথ্য পাঠানো যাবে।",
        "mailerror": "ইমেইল পাঠাতে সমস্যা: $1",
        "createaccount-title": "{{SITENAME}}-এর জন্য অ্যাকাউন্ট সৃষ্টি",
        "createaccount-text": "কেউ $2-এর জন্য {{SITENAME}}-এ একটি অ্যাকাউন্ট সৃষ্টি করেছেন ($4)। \"$2\"-এর জন্য পাসওয়ার্ড হল \"$3\"। আপনার এখন অ্যাকাউন্টে প্রবেশ করে পাসওয়ার্ড পরিবর্তন করা উচিত।\n\nযদি ভুল করে অ্যাকাউন্টটি সৃষ্টি হয়ে থাকে, তাহলে এই বার্তাটি উপেক্ষা করুন।",
        "login-throttled": "আপনি সাম্প্রতিক সময়ে পরপর বেশ কয়েকবার প্রবেশের চেষ্টা করেছেন।\nপুনরায় চেষ্টা করার পূর্বে অনুগ্রহ করে $1 অপেক্ষা করুন।",
-       "login-abort-generic": "à¦\86পনার à¦²à¦\97à¦\87ন à¦¸à¦«à¦² à¦\9bিলà§\8b à¦¨à¦¾ - বাতিল করা হয়েছে",
+       "login-abort-generic": "à¦\86পনার à¦ªà§\8dরবà§\87শ à¦¬à§\8dযরà§\8dথ à¦¹à¦¯à¦¼à§\87à¦\9bà§\87 - বাতিল করা হয়েছে",
        "login-migrated-generic": "আপনার অ্যাকাউন্ট স্থানান্তরিত করা হয়েছে, এবং আপনার ব্যবহারকারী নাম আর এই উইকিতে বিদ্যমান নয়।",
        "loginlanguagelabel": "ভাষা: $1",
        "suspicious-userlogout": "আপনার প্রস্থানের অনুরোধ বাতিল হয়েছে কারণ অনুমিত যে আপনার ব্রাউজার অসম্পূর্ণ অথবা পূবর্বতী তথ্য প্রেরণ করেছে।",
        "newpassword": "নতুন পাসওয়ার্ড:",
        "retypenew": "নতুন পাসওয়ার্ড আবার লিখুন:",
        "resetpass_submit": "পাসওয়ার্ড দাও এবং লগ-ইন করো",
-       "changepassword-success": "à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦¸à¦¾à¦«à¦²à¦­à¦¾à¦¬à§\87 à¦ªà¦°à¦¿à¦¬à¦°à§\8dতà§\80ত à¦¹à¦¯à¦¼à§\87à¦\9bà§\87।",
+       "changepassword-success": "à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87!",
        "changepassword-throttled": "আপনি সম্প্রতি পরপর বেশ কয়েকবার প্রবেশের চেষ্টা করেছেন। পুনরায় চেষ্টা করার পূর্বে অনুগ্রহ করে $1 অপেক্ষা করুন।",
        "botpasswords": "বট পাসওয়ার্ড",
        "botpasswords-disabled": "বট পাসওয়ার্ড নিষ্ক্রিয় করা।",
        "botpasswords-insert-failed": "\"$1\" নামের বট যুক্ত করা যায়নি। আগে থেকেই তালিকায় রয়েছে?",
        "botpasswords-update-failed": "\"$1\" নামের বট যুক্ত করা যায়নি। আগে অপসারণ করা হয়েছিল?",
        "botpasswords-created-title": "বট পাসওয়ার্ড তৈরী করা হয়েছে",
-       "botpasswords-created-body": "\"$1\", বট পাসওয়ার্ড তৈরী করা হয়েছে।",
+       "botpasswords-created-body": "ব্যবহারকারী \"$2\"-এর \"$1\" নামের বটের জন্য বট পাসওয়ার্ড তৈরী করা হয়েছে।",
        "botpasswords-updated-title": "বট পাসওয়ার্ড আপডেট করা হয়েছে",
-       "botpasswords-updated-body": "\"$1\" বট পাসওয়ার্ডটি সফলভাবে হালনাগাদ করা হয়েছে।",
+       "botpasswords-updated-body": "ব্যবহারকারী \"$2\"-এর \"$1\" নামের বটের জন্য বট পাসওয়ার্ড হালনাগাদ করা হয়েছে।",
        "botpasswords-deleted-title": "বট পাসওয়ার্ড অপসারণ করা হয়েছে",
-       "botpasswords-deleted-body": "\"$1\" বটের পাসওয়ার্ড মুছে ফেলা হয়েছিল",
+       "botpasswords-deleted-body": "ব্যবহারকারী \"$2\"-এর \"$1\" নামের বটের জন্য বট পাসওয়ার্ড মুছে ফেলা হয়েছিল।",
        "botpasswords-no-provider": "BotPasswordsSessionProvider উপলব্ধ নয়।",
        "resetpass_forbidden": "পাসওয়ার্ড পরিবর্তন করা সম্ভব নয়",
        "resetpass-no-info": "এই পাতাটিতে সরাসরি প্রবেশাধিকার পেতে আপনাকে অবশ্যই লগইন করতে হবে।",
        "resetpass-submit-loggedin": "পাসওয়ার্ড পরিবর্তন",
        "resetpass-submit-cancel": "বাতিল",
-       "resetpass-wrong-oldpass": "ভà§\81ল à¦\85সà§\8dথায়à§\80 à¦\85থবা à¦¬à¦°à§\8dতমান à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড।\nসমà§\8dভবতà¦\83 à¦\86পনি à¦\87তà§\8bমধà§\8dযà§\87à¦\87 à¦¸à¦«à¦²à¦­à¦¾à¦¬à§\87 à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dডà¦\9fি à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রà§\87à¦\9bà§\87ন à¦\85থবা à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦\85সà§\8dথায়à§\80 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dডà§\87র à¦\9cনà§\8dয à¦\85নà§\81রà§\8bধ à¦\95রà§\87à¦\9bà§\87ন।",
+       "resetpass-wrong-oldpass": "ভুল অস্থায়ী অথবা বর্তমান পাসওয়ার্ড।\nসম্ভবতঃ আপনি ইতোমধ্যেই আপনার পাসওয়ার্ডটি পরিবর্তন করেছেন অথবা একটি নতুন অস্থায়ী পাসওয়ার্ডের জন্য অনুরোধ করেছেন।",
        "resetpass-recycled": "অনুগ্রহ করে বর্তমানে ব্যবহার করছেন এমন পাসওয়ার্ডের পরিবর্তে নতুন একটি পাসওয়ার্ড নির্ধারণ করুন।",
        "resetpass-temp-emailed": "সাময়িকভাবে ব্যবহার করার কোড দিয়ে আপনি লগইন করেছেন।\nলগইন করার জন্য আপনাকে অবশ্যই একটি নতুন পাসওয়ার্ড নির্ধারন করতে হবে:",
        "resetpass-temp-password": "অস্থায়ী পাসওয়ার্ড:",
        "previewnote": "'''খেয়াল করুন, এটি একটি প্রাকদর্শন মাত্র।'''\nআপনার পরিবর্তন এখনও সংরক্ষণ করা হয়নি!",
        "continue-editing": "সম্পাদনা করুন",
        "previewconflict": "এই প্রাকদর্শনটি সম্পাদনা ক্ষেত্রের উপরের অংশটির টেক্সট সংরক্ষণ করলে যেরকম দেখাবে, তা দেখাচ্ছে।",
-       "session_fail_preview": "'''দুঃখিত! সেশন ডাটা হারিয়ে যাওয়ার কারণে আপনার সম্পাদনাটি সংরক্ষণ করা সম্ভব হয়নি। দয়া করে লেখাটি আবার জমা দেয়ার চেষ্টা করুন। যদি এতেও কাজ না হয়, তবে অ্যাকাউন্ট থেকে বেরিয়ে গিয়ে আবার অ্যাকাউন্টে প্রবেশ করে চেষ্টা করুন।'''",
+       "session_fail_preview": "দুঃখিত! সেশন ডাটা হারিয়ে যাওয়ার কারণে আপনার সম্পাদনাটি সংরক্ষণ করা সম্ভব হয়নি।\n\nআপনি সম্ভবত সংযোগ হারিয়েছন। <strong>দয়া করে যাচাই করুন যে আপনি এখনও প্রবেশরত রয়েছেন এবং আবার চেষ্টা করুন</strong>। যদি এটি এখনও কাজ না করে, তাহলে দয়া করে [[Special:UserLogout|অ্যাকাউন্ট থেকে প্রস্থান করুন]] এবং আবার অ্যাকাউন্টে প্রবেশ করে চেষ্টা করুন এবং এবং পরীক্ষা করুন যে আপনার ব্রাউজার এই সাইটে কুকি ব্যবহারের অনুমতি দেয়।",
        "session_fail_preview_html": "'''দুঃখিত! সেশন উপাত্ত হারিয়ে যাওয়ার কারণে আমরা আপনার সম্পাদনাটি প্রক্রিয়া করতে পারিনি।'''\n\n''{{SITENAME}}-এ raw HTML সক্রিয় আছে বলে জাভাস্ক্রিপ্টভিত্তিক আক্রমণ থেকে প্রতিরক্ষার জন্য প্রাকদর্শনটি দেখানো হচ্ছে না।''\n\n'''যদি এটি সম্পাদনার একটি বৈধ প্রচেষ্টা হয়, তবে অনুগ্রহ করে আবার চেষ্টা করুন। যদি তারপরেও কাজ না হয়, তবে অ্যাকাউন্ট থেকে বেরিয়ে গিয়ে আবার প্রবেশ করে চেষ্টা করুন।'''",
        "token_suffix_mismatch": "'''আপনার সম্পাদনাটি প্রত্যাখ্যান করা হয়েছে, কারণ আপনার ক্লায়েন্ট প্রোগ্রামটি সম্পাদনা টেক্সটের বিরামচিহ্নগুলি গুলিয়ে ফেলেছে। পাতাটির টেক্সটে যাতে ক্ষতি না হয় সেজন্য সম্পাদনাটি প্রত্যাখ্যান করা হয়েছে। আপনি কোন ত্রুটিপূর্ণ ওয়েব-ভিত্তিক বেনামী প্রক্সি সেবা ব্যবহার করলে এরকম হতে পারে।'''",
        "edit_form_incomplete": "'''আপনার সম্পাদনার কিছু অংশ সার্ভারে পৌছায় নি; আপনার সম্পাদনা সম্পূর্ণরুপে আছে কিনা নিশ্চিত হয়ে আবার চেষ্টা করুন'''",
        "allowemail": "অন্য ব্যবহারকারীদেরকে আপনাকে ই-মেইল পাঠানোর অনুমতি দিন।",
        "prefs-searchoptions": "অনুসন্ধান",
        "prefs-namespaces": "নামস্থানসমূহ",
-       "default": "à¦\86দি à¦\85বসà§\8dথা",
+       "default": "পà§\82রà§\8dবনিরà§\8dধারিত",
        "prefs-files": "ফাইল",
        "prefs-custom-css": "স্বনির্ধারিত CSS",
        "prefs-custom-js": "স্বনির্ধারিত JS",
        "userrights-changeable-col": "দল যা আপনি পরিবর্তন করতে পারেন",
        "userrights-unchangeable-col": "দল যা আপনি পরিবর্তন করতে পারবেন না",
        "userrights-conflict": "ব্যবহারকারী অধিকার দ্বন্দ্ব! অনুগ্রহ করে নিশ্চিত হোন এবং পুনরায় চেষ্টা করুন।",
-       "userrights-removed-self": "à¦\86পনি à¦¸à¦«à¦²à¦­à¦¾à¦¬à§\87 à¦\86পনার à¦¨à¦¿à¦\9cà§\87র à¦\85ধিà¦\95ার à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রà§\87à¦\9bà§\87ন। à¦\8fর à¦«à¦²à§\87 à¦\8fà¦\96ন à¦¥à§\87à¦\95à§\87 à¦\86পনি à¦\86র à¦\8fà¦\87 à¦ªà¦¾à¦¤à¦¾à¦¯à¦¼ à¦ªà§\8dরবà§\87শ à¦\95রতà§\87 à¦ªà¦¾à¦°à¦¬à§\87ন à¦¨à¦¾à¥¤",
+       "userrights-removed-self": "আপনি আপনার নিজের অধিকার পরিবর্তন করেছেন। এর ফলে এখন থেকে আপনি আর এই পাতায় প্রবেশ করতে পারবেন না।",
        "group": "দল:",
        "group-user": "ব্যবহারকারীগণ",
        "group-autoconfirmed": "স্বয়ংক্রিয়ভাবে নিশ্চিতকৃত ব্যবহারকারীরা",
        "recentchangeslinked-page": "পাতার নাম:",
        "recentchangeslinked-to": "প্রদত্ত পাতায় সংযুক্ত আছে এমন পাতাগুলোর পরিবর্তন দেখাও",
        "recentchanges-page-added-to-category": "বিষয়শ্রেণীতে [[:$1]] যোগ করা হয়েছে",
-       "recentchanges-page-added-to-category-bundled": "বিষয়শà§\8dরà§\87ণà§\80তà§\87 [[:$1]] à¦\8fবà¦\82 {{PLURAL:$2|à¦\8fà¦\95à¦\9fি à¦ªà¦¾à¦¤à¦¾|$2à¦\9fি à¦ªà¦¾à¦¤à¦¾}} যোগ করা হয়েছে",
+       "recentchanges-page-added-to-category-bundled": "বিষয়শà§\8dরà§\87ণà§\80তà§\87 [[:$1]] à¦\93 [[Special:WhatLinksHere/$1|{{PLURAL:$2|à¦\8fà¦\95à¦\9fি à¦ªà¦¾à¦¤à¦¾|$2à¦\9fি à¦ªà¦¾à¦¤à¦¾}}]] যোগ করা হয়েছে",
        "recentchanges-page-removed-from-category": "বিষয়শ্রেণী থেকে [[:$1]] সরানো হয়েছে",
-       "recentchanges-page-removed-from-category-bundled": "বিষয়শà§\8dরà§\87ণà§\80 à¦¥à§\87à¦\95à§\87 [[:$1]] à¦\8fবà¦\82 {{PLURAL:$2|à¦\8fà¦\95à¦\9fি à¦ªà¦¾à¦¤à¦¾|$2à¦\9fি à¦ªà¦¾à¦¤à¦¾}} সরানো হয়েছে",
+       "recentchanges-page-removed-from-category-bundled": "বিষয়শà§\8dরà§\87ণà§\80 à¦¥à§\87à¦\95à§\87 [[:$1]] à¦\93 [[Special:WhatLinksHere/$1|{{PLURAL:$2|à¦\8fà¦\95à¦\9fি à¦ªà¦¾à¦¤à¦¾|$2à¦\9fি à¦ªà¦¾à¦¤à¦¾}}]] সরানো হয়েছে",
        "autochange-username": "মিডিয়াউইকি স্বয়ংক্রিয় পরিবর্তন",
        "upload": "আপলোড",
        "uploadbtn": "ফাইল আপলোড করুন",
        "uploadstash-badtoken": "আপনার অনুরোধকৃত কাজটি সম্পন্ন হয়নি, হয়তো আপনার সম্পাদনার অনুমতি মেয়াদ উত্তীর্ণ হয়েছে। পুনরায় চেষ্টা করুন।",
        "uploadstash-errclear": "ফাইলগুলো পরিষ্কারকরণ ব্যর্থ হয়েছে।",
        "uploadstash-refresh": "ফাইলের তালিকা রিফ্রেশ করুন",
+       "uploadstash-thumbnail": "থাম্বনেইল দেখুন",
        "invalid-chunk-offset": "ত্রুটিপূর্ণ চাংক অফসেট",
        "img-auth-accessdenied": "প্রবেশাধিকার নাই",
        "img-auth-nopathinfo": "PATH_INFO পাওয়া যাচ্ছে না।\nআপনার সার্ভার থেকে এই তথ্য পাঠানোর জন্য কনফিগার করা হয়নি।\nএটি হয়তো CGI ভিত্তিক এবং img_auth সমর্থন করে না।\nবিস্তারিত দেখুন https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization।",
        "apisandbox-dynamic-parameters-add-label": "প্যারামিটার যোগ করুন:",
        "apisandbox-dynamic-parameters-add-placeholder": "প্যারামিটারের নাম",
        "apisandbox-results": "ফলাফল",
+       "apisandbox-sending-request": "API অনুরোধ পাঠানো হচ্ছে...",
+       "apisandbox-loading-results": "API ফলাফল গ্রহণ করা হচ্ছে...",
        "apisandbox-request-url-label": "অনুরোধের URL:",
        "apisandbox-request-time": "অনুরোধের সময়: {{PLURAL:$1|$1 মি.সে.}}",
        "booksources": "বইয়ের উৎস",
        "speciallogtitlelabel": "লক্ষ্য (শিরোনাম বা {{ns:user}}:ব্যবহারকারীর জন্য ব্যবহারকারী নাম):",
        "log": "লগগুলি",
        "logeventslist-submit": "দেখাও",
-       "all-logs-page": "সব à¦ªà¦¾à¦¬à¦²à¦¿à¦\95 লগ",
+       "all-logs-page": "সব à¦ªà§\8dরà¦\95াশà§\8dয লগ",
        "alllogstext": "{{SITENAME}}-এর সবগুলো লগের সম্মিলিত প্রদর্শন।\nআপনি লগের ধরন, ব্যবহারকারীর নাম, বা পাতার নাম নির্বাচন করে প্রদর্শনটির আকার কমিয়ে আনতে পারেন।",
        "logempty": "মিলে যায় এমন কিছু লগে পাওয়া যায়নি।",
        "log-title-wildcard": "এই টেক্সট দিয়ে শুরু হওয়া শিরোনামগুলি অনুসন্ধান করা হোক",
        "changecontentmodel-title-label": "পাতার শিরোনাম",
        "changecontentmodel-model-label": "পাতার বিষয়বস্তুর প্রতিরূপ",
        "changecontentmodel-reason-label": "কারণ:",
+       "changecontentmodel-submit": "পরিবর্তন করুন",
        "changecontentmodel-success-title": "বিষয়বস্তুর প্রতিরূপ পরিবর্তিত হয়েছিলো",
        "changecontentmodel-success-text": "[[:$1]]-এর বিষয়বস্তুর ধরণ পরিবর্তন হয়েছে।",
        "log-name-contentmodel": "বিষয়বস্তুর মডেল পরিবর্তন লগ",
        "ipb-unblock": "ব্যবহারকারী বা আইপি ঠিকানার উপর থেকে বাধা তুলে নেওয়া হোক",
        "ipb-blocklist": "বিদ্যমান বাধাগুলি দেখুন",
        "ipb-blocklist-contribs": "{{GENDER:$1|$1}}-এর অবদানসমূহ",
+       "ipb-blocklist-duration-left": "$1 বাকি",
        "unblockip": "ব্যবহারকারীর উপর থেকে বাধা তুলে নেওয়া হোক",
        "unblockiptext": "নিচের ফর্মটি ব্যবহার করে পূর্বে বাধা দেওয়া কোন আইপি ঠিকানা বা ব্যবহারকারীর সাইটে লেখার অধিকার পুনঃপ্রতিষ্ঠা করুন।",
        "ipusubmit": "বাধা তুলে নেওয়া হোক",
        "import-logentry-upload-detail": "$1টি {{PLURAL:$1|সংশোধন}} আমদানি করা হয়েছে",
        "import-logentry-interwiki-detail": "$2 থেকে $1টি {{PLURAL:$1|সংশোধন}} আমদানি করা হয়েছে",
        "javascripttest": "জাভাস্ক্রিপ্ট পরীক্ষা",
-       "javascripttest-pagetext-noframework": "এই পাতাটি জাভাস্ক্রিপ্ট পরীক্ষার জন্য সংরক্ষিত।",
-       "javascripttest-pagetext-unknownframework": "পরীক্ষার অজানা ফ্রেমওয়ার্ক \"$1\"।",
        "javascripttest-pagetext-unknownaction": "অজানা কার্য \"$1\"।",
-       "javascripttest-pagetext-frameworks": "অনুগ্রহ করে নিচের কোনো একটি ফ্রেমওয়ার্ক নির্ধারণ করুন: $1",
-       "javascripttest-pagetext-skins": "পরীক্ষার জন্য একটি স্কীন নির্ধারণ করুন:",
        "javascripttest-qunit-intro": "mediawiki.org থেকে [$1 পরীক্ষার ডলুমেন্টেশন] দেখুন।",
        "tooltip-pt-userpage": "{{GENDER:|আপনার ব্যবহারকারী}} পাতা",
        "tooltip-pt-anonuserpage": "যে আইপি ঠিকানা থেকে আপনি সম্পাদনা করছেন, তার ব্যবহারকারী পাতা",
        "exif-compression-2": "সিসিআইটিটি গ্রুপ ৩ ১-ডাইমেনশনাম মডিফাইড হাফম্যান রান লেংক্থ এনকোডিং",
        "exif-compression-3": "সিসিআইটিটি গ্রুপ ৩ ফ্যাক্স এনকোডিং",
        "exif-compression-4": "সিসিআইটিটি গ্রুপ ৪ ফ্যাক্স এনকোডিং",
+       "exif-compression-6": "JPEG (পুরনো)",
        "exif-copyrighted-true": "কপিরাইটকৃত",
        "exif-copyrighted-false": "কপিরাইট সংক্রান্ত তথ্য নেই",
+       "exif-photometricinterpretation-0": "কালো এবং সাদা (সাদা হল 0)",
        "exif-photometricinterpretation-1": "কালো এবং সাদা (কালো হল 0)",
        "exif-unknowndate": "অজানা তারিখ",
        "exif-orientation-1": "সাধারণ",
        "version-entrypoints-header-entrypoint": "শুরু",
        "version-entrypoints-header-url": "ইউআরএল",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath নিবন্ধের পথ]",
+       "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath স্ক্রিপ্টের পথ]",
        "version-libraries": "ইনস্টল লাইব্রেরি",
        "version-libraries-library": "লাইব্রেরী",
        "version-libraries-version": "সংস্করণ",
        "version-libraries-description": "বিবরণ",
        "version-libraries-authors": "লেখক",
        "redirect": "পাতা, ফাইল, ব্যবহারকরী, সংশোধন বা লগ আইডি দ্বারা পুনঃনির্দেশ করা হয়েছে",
-       "redirect-legend": "একটি ফাইল অথবা পাতায় পুনঃনির্দেশ করা হয়েছে",
        "redirect-summary": "এই বিশেষ পাতাটি একটি ফাইলে (প্রদত্ত ফাইলের নাম), একটি পাতায় (প্রদত্ত সংস্করণ আইডি বা পাতা আইডি), একটি ব্যবহারকরী পাতায় (প্রদত্ত সংখ্যায় লেখা ব্যবহারকারী আইডি) বা একটি লগ ভুক্তিতে (প্রদত্ত লগ ভুক্তি) পুনঃনির্দেশিত হয়েছে। ব্যবহার:  [[{{#Special:Redirect}}/file/উদাহরণ.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], বা [[{{#Special:Redirect}}/logid/186]]।",
        "redirect-submit": "যাও",
        "redirect-lookup": "দেখুন:",
        "tags-edit-chosen-no-results": "কোন ট্যাগ মিল পাওয়া যায়নি",
        "tags-edit-reason": "কারণ:",
        "tags-edit-revision-submit": "Apply changes to {{PLURAL:$1|এই সংশোধনে|$1 সংশোধনসমূহে}} পরিবর্তন প্রয়োগ করুন",
-       "tags-edit-success": "পরিবরà§\8dতন à¦¸à¦«à¦²à¦­à¦¾à¦¬à§\87 à¦ªà§\8dরয়à§\8bà¦\97 à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87।",
+       "tags-edit-success": "পরিবর্তন প্রয়োগ করা হয়েছে।",
        "tags-edit-failure": "পরিবর্তন প্রয়োগ করা যায়নি: $1",
        "tags-edit-nooldid-title": "লক্ষ্য সংশোধন অবৈধ",
        "tags-edit-none-selected": "যোগ করতে অথবা অপসারণ করতে অন্ততপক্ষে একটি ট্যাগ দয়া করে নির্বাচন করুন।",
        "logentry-protect-modify-cascade": "$1 $3-এর জন্য সুরক্ষা স্তর {{GENDER:$2|পরিবর্তন করেছেন}} $4 [প্রপাতাকার]",
        "logentry-rights-rights": "$1 ব্যবহারকারী, $3 এর দলগত সদস্যপদ $4 থেকে $5 এ {{GENDER:$2|পরিবর্তন}} করেছেন",
        "logentry-rights-rights-legacy": "$1 দলের সদস্যপদ পরিবর্তন করেছেন {{GENDER:$2|changed}} এর জন্য $3",
-       "logentry-rights-autopromote": "$1 à¦¸à¦¯à¦¼à¦\82à¦\95à§\8dরিয়ভাবà§\87 $4 à¦¥à§\87à¦\95à§\87 $5 à¦\8f {{GENDER:$2|à¦\89নà§\8dনà§\80ত}} à¦¹à¦¯à¦¼à§\87à¦\9bà§\87",
+       "logentry-rights-autopromote": "$1 à¦¸à§\8dবয়à¦\82à¦\95à§\8dরিয়ভাবà§\87 $4 à¦¥à§\87à¦\95à§\87 $5-à¦\8f {{GENDER:$2|à¦\89নà§\8dনà§\80ত}} à¦¹à¦¯à¦¼à§\87à¦\9bà§\87ন",
        "logentry-upload-upload": "$1 $3 {{GENDER:$2|আপলোড করেছেন}}",
        "logentry-upload-overwrite": "$1 $3-এর একটি নতুন সংস্করণ {{GENDER:$2|আপলোড করেছেন}}",
        "logentry-upload-revert": "$1 $3 {{GENDER:$2|আপলোড করেছেন}}",
        "log-name-managetags": "ট্যাগ ব্যবস্থাপনা লগ",
        "logentry-managetags-create": "$1 \"$4\" ট্যাগ {{GENDER:$2|তৈরি করেছে}}",
+       "logentry-managetags-delete": "$1 \"$4\" ট্যাগটি {{GENDER:$2|অপসারণ করেছেন}} ($5টি {{PLURAL:$5|সংস্করণ বা লগ ভুক্তি|সংস্করণ ও/বা লগ ভুক্তি}} সরানো হয়েছে)",
        "log-name-tag": "ট্যাগ লগ",
        "rightsnone": "(কিছু নাই)",
        "revdelete-summary": "সম্পাদনা সারাংশ",
        "special-characters-group-ipa": "আইপিএ",
        "special-characters-group-symbols": "চিহ্নসমূহ",
        "special-characters-group-greek": "গ্রিক",
+       "special-characters-group-greekextended": "সম্প্রসারিত গ্রিক",
        "special-characters-group-cyrillic": "সিরিলিক",
        "special-characters-group-arabic": "আরবি",
        "special-characters-group-arabicextended": "সম্প্রসারিত আরবি",
        "sessionprovider-generic": "$1টি সেশন",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "কুকি-ভিত্তিক সেশন",
        "sessionprovider-nocookies": "কুকি নিষ্ক্রিয় করা। নিশ্চিত করুন যে আপনার কুকি সক্রিয় আছে এবং আবার শুরু করুন।",
-       "randomrootpage": "অজানা মূল পাতা"
+       "randomrootpage": "অজানা মূল পাতা",
+       "log-action-filter-block": "বাধাদানের ধরন:",
+       "log-action-filter-delete": "অপসারণের ধরন:",
+       "log-action-filter-patrol": "টহলের ধরন:",
+       "log-action-filter-protect": "সুরক্ষার ধরন:",
+       "log-action-filter-upload": "আপলোডের ধরন:",
+       "log-action-filter-all": "সব",
+       "log-action-filter-block-block": "বাধাদান",
+       "log-action-filter-block-reblock": "বাধাদান পরিবর্তন",
+       "log-action-filter-block-unblock": "বাধা অপসারণ",
+       "log-action-filter-delete-delete": "পাতা অপসারণ",
+       "log-action-filter-delete-restore": "পাতা পুনঃরুদ্ধার",
+       "log-action-filter-delete-event": "লগ অপসারণ",
+       "log-action-filter-delete-revision": "সংশোধন অপসারণ",
+       "log-action-filter-patrol-patrol": "ম্যানুয়াল টহল",
+       "log-action-filter-patrol-autopatrol": "স্বয়ংক্রিয় টহল",
+       "log-action-filter-protect-protect": "সুরক্ষা",
+       "log-action-filter-protect-modify": "সুরক্ষা পরিমার্জন",
+       "log-action-filter-protect-unprotect": "অসুরক্ষা",
+       "log-action-filter-upload-upload": "নতুন আপলোড",
+       "log-action-filter-upload-overwrite": "পুনঃআপলোড"
 }
index e531009..83d271e 100644 (file)
@@ -58,6 +58,7 @@
        "tog-watchlisthidebots": "Sakrij izmjene botova sa spiska praćenih članaka",
        "tog-watchlisthideminor": "Sakrij manje izmjene sa spiska praćenih članaka",
        "tog-watchlisthideliu": "Sakrij izmjene prijavljenih korisnika sa spiska praćenih članaka",
+       "tog-watchlistreloadautomatically": "Automatski osvježi spisak praćenja kad god se izmijeni filter (potreban JavaScript)",
        "tog-watchlisthideanons": "Sakrij izmjene anonimnih korisnika sa spiska praćenih članaka",
        "tog-watchlisthidepatrolled": "Sakrij patrolirane izmjene sa spiska praćenja",
        "tog-watchlisthidecategorization": "Sakrij kategorizaciju stranica",
        "mypreferencesprotected": "Nemate dozvolu da uređujete svoje postavke.",
        "ns-specialprotected": "Specijalne stranice se ne mogu uređivati.",
        "titleprotected": "Ovaj naslov stranice je od pravljenja [[User:$1|{{GENDER:$1|zaštitio $1|zaštitila $1}}]].\nRazlog: <em>$2</em>.",
-       "filereadonlyerror": "Ne mogu promijeniti datoteku \"$1\" jer je skladište datoteka \"$2\" zaključano samo za čitanje.\n\nAdministrator koji ga je zaključao naveo je ovo objašnjenje: \"$3\".",
+       "filereadonlyerror": "Ne mogu promijeniti datoteku \"$1\" jer je skladište datoteka \"$2\" zaključano samo za čitanje.\n\nSistemski administrator koji ga je zaključao naveo je ovo objašnjenje: \"$3\".",
        "invalidtitle-knownnamespace": "Neispravan naslov s imenskim prostorom \"$2\" i tekstom \"$3\"",
        "invalidtitle-unknownnamespace": "Neispravan naslov s imenskim prostorom br. $1 i tekstom \"$2\"",
        "exception-nologin": "Niste prijavljeni",
        "nocookieslogin": "{{SITENAME}} koristi kolačiće (''cookies'') da bi se korisnici prijavili.  Vi ste onemogućili kolačiće na Vašem kompjuteru.  Molimo Vas da ih omogućite i da pokušate ponovo sa prijavom.",
        "nocookiesfornew": "Korisnički račun nije napravljen, jer nismo mogli da potvrdimo njegov izvor.\nProvjerite da li su cookies omogućeni, ponovo učitajte ovu stranicu i pokušajte ponovo.",
        "noname": "Niste izabrali ispravno korisničko ime.",
-       "loginsuccesstitle": "Prijavljivanje uspješno",
+       "loginsuccesstitle": "Prijavljen",
        "loginsuccess": "'''Sad ste prijavljeni na {{SITENAME}} kao \"$1\".'''",
        "nosuchuser": "Ne postoji korisnik s imenom \"$1\".\nKorisnička imena razlikuju velika i mala slova.\nProvjerite Vaš unos ili [[Special:UserLogin/signup|napravite novi korisnički račun]].",
        "nosuchusershort": "Ne postoji korisnik s imenom \"$1\".\nProvjerite jeste li dobro ukucali.",
        "wrongpasswordempty": "Lozinka koju ste unijeli je bila prazna.\nMolimo Vas da pokušate ponovno.",
        "passwordtooshort": "Lozinka mora imati najmanje {{PLURAL:$1|1 znak|$1 znaka|$1 znakova}}.",
        "passwordtoolong": "Lozinke ne mogu biti duže od {{PLURAL:$1|jednog znaka|$1 znaka|$1 znakova}}.",
-       "password-name-match": "Vaša šifra mora biti različita od Vašeg korisničkog imena.",
+       "password-name-match": "Vaša lozinka mora biti različita od Vašeg korisničkog imena.",
        "password-login-forbidden": "Korištenje ovih korisničkih imena i šifara je zabranjeo.",
        "mailmypassword": "Poništi lozinku",
-       "passwordremindertitle": "{{SITENAME}} - privremena šifra",
-       "passwordremindertext": "Neko (vjerovatno Vi, sa IP adrese $1) je zahtjevao da vam pošaljemo novu šifru za {{SITENAME}}  ($4). Privremena šifra za korisnika \"$2\" je napravljena i glasi \"$3\". Ako ste to željeli, sad treba da se prijavite i promjenite šifru.\nVaša privremena šifra će isteči za {{PLURAL:$5|$5 dan|$5 dana}}.\n\nAko je neko drugi napravio ovaj zahtjev ili ako ste se sjetili vaše šifre i ne želite više da je promjenite, možete da ignorišete ovu poruku i da nastavite koristeći vašu staru šifru.",
+       "passwordremindertitle": "Privremena lozinka za {{GRAMMAR:akuzativ|{{SITENAME}}}}",
+       "passwordremindertext": "Neko (vjerovatno Vi, s IP adrese $1) zathijevao je da Vam pošaljemo novu lozinku za {{GRAMMAR:akuzativ|{{SITENAME}}}} ($4). Privremena lozinka za korisnika \"$2\" napravljena je i glasi \"$3\". Ako ste to željeli, sad se trebate prijaviti i promijeniti lozinku.\nVaša privremena lozinku isteći će za {{PLURAL:$5|$5 dan|$5 dana}}.\n\nAko je neko drugi napravio ovaj zahtjev ili ako ste se u međuvremenu sjetili Vaše lozinke i više je ne želite promijeniti, možete ignorirati ovu poruku i nastaviti da koristite Vašu staru lozinku.",
        "noemail": "Ne postoji adresa e-pošte za korisnika \"$1\".",
        "noemailcreate": "Morate da navedete validnu e-mail adresu",
-       "passwordsent": "Nova šifra je poslata na adresu e-pošte korisnika \"$1\".\nMolimo Vas da se prijavite nakon š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.",
+       "passwordsent": "Nova lozinka poslana je na adresu e-pošte korisnika \"$1\".\nMolimo Vas da se prijavite nakon š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 lozinke.",
        "eauthentsent": "Na navedenu adresu e-pošte poslana je poruka s potvrdom.\nPrije nego što pošaljemo daljnje poruke, pratite uputstva s e-pošte da biste potvrdili da je račun zaista Vaš.",
-       "throttled-mailpassword": "Već Vam je poslan e-mail za promjenu šifre u {{PLURAL:$1|posljednjih sat vremena|posljednja $1 sata|posljednjih $1 sati}}.\nDa 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}}.",
+       "throttled-mailpassword": "Već Vam je poslana e-poruka za promjenu lozinke u {{PLURAL:$1|posljednjih sat vremena|posljednja $1 sata|posljednjih $1 sati}}.\nDa bi se spriječila zloupotreba, može se poslati samo jedna e-poruka za promjenu lozinke {{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.\nKao rezultat, posjetioci koji koriste ovu IP adresu ne mogu trenutno praviti više računa.",
        "emailauthenticated": "Vaša adresa e-pošte potvrđena je $2 u $3.",
        "accountcreated": "Korisnički račun je napravljen",
        "accountcreatedtext": "Korisnički račun za [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|razgovor]]) je napravljen.",
        "createaccount-title": "Pravljenje korisničkog računa za {{SITENAME}}",
-       "createaccount-text": "Neko je napravio korisnički račun za vašu e-mail adresu na {{SITENAME}} ($4) sa imenom \"$2\", i sa šifrom \"$3\".\nTrebali biste se prijaviti i promijeniti šifru.\n\nMožete ignorisati ovu poruku, ako je korisnički račun napravljen greškom.",
+       "createaccount-text": "Neko je napravio korisnički račun za Vašu adresu e-pošte na {{GRAMMAR:dativ|{{SITENAME}}}} ($4) s imenom \"$2\", i s lozinkom \"$3\".\nTrebali biste se prijaviti i promijeniti lozinku.\n\nMožete ignorirati ovu poruku, ako je korisnički račun napravljen greškom.",
        "login-throttled": "Previše puta ste se pokušali prijaviti.\nMolimo Vas da sačekate $1 prije nego što pokušate ponovo.",
-       "login-abort-generic": "Vaša prijava nije bila uspješna – Prekinuto",
+       "login-abort-generic": "Neuspješna prijava – Prekinuto",
        "login-migrated-generic": "Vaš račun je premješten, a vaše korisničko ime više ne postoji na ovoj wiki.",
        "loginlanguagelabel": "Jezik: $1",
        "suspicious-userlogout": "Vaš zahtjev za odjavu je odbijen jer je poslan preko pokvarenog preglednika ili keširanog proksija.",
        "php-mail-error-unknown": "Nepoznata greška u PHP funkciji mail()",
        "user-mail-no-addy": "Pokušaj slanja e-maila bez navedene e-mail adrese.",
        "user-mail-no-body": "Pokušano slanje e-poruke s praznim ili nerazumno kratkim sadržajem.",
-       "changepassword": "Promijeni šifru",
-       "resetpass_announce": "Da biste završili prijavu, morate postaviti novu šifru.",
+       "changepassword": "Promijeni lozinku",
+       "resetpass_announce": "Da biste završili prijavu, morate podesiti novu lozinku.",
        "resetpass_text": "<!-- Unesi tekst ovdje -->",
-       "resetpass_header": "Obnovi šifru za račun",
-       "oldpassword": "Stara šifra:",
-       "newpassword": "Nova šifra:",
-       "retypenew": "Ponovo upišite novu šifru:",
-       "resetpass_submit": "Odredi šifru i prijavi se",
-       "changepassword-success": "Vaša šifra/lozinka je uspiješno promjenjena!",
+       "resetpass_header": "Promjena lozinke računa",
+       "oldpassword": "Stara lozinka:",
+       "newpassword": "Nova lozinka:",
+       "retypenew": "Ponovo upišite novu lozinku:",
+       "resetpass_submit": "Postavi lozinku i prijavi se",
+       "changepassword-success": "Vaša lozinka je promijenjena.",
        "changepassword-throttled": "Previše puta ste se pokušali prijaviti.\nMolimo Vas da sačekate $1 prije nego što pokušate ponovo.",
-       "resetpass_forbidden": "Šifre ne mogu biti promjenjene",
+       "resetpass_forbidden": "Lozinke ne mogu biti promijenjene",
        "resetpass-no-info": "Morate biti prijavljeni da biste pristupili ovoj stranici direktno.",
-       "resetpass-submit-loggedin": "Promijeni šifru",
+       "resetpass-submit-loggedin": "Promijeni lozinku",
        "resetpass-submit-cancel": "Odustani",
-       "resetpass-wrong-oldpass": "Privremena ili trenutna šifra nije validna.\nMožda ste već uspješno promijenili Vašu šifru ili ste tražili novu privremenu šifru.",
+       "resetpass-wrong-oldpass": "Privremena ili trenutna lozinka nije validna.\nMožda ste već promijenili Vašu lozinku ili ste tražili novu privremenu lozinku.",
        "resetpass-recycled": "Molimo resetirajte vašu lozinku u nešto drugo od vaše trenutne lozinke.",
        "resetpass-temp-emailed": "Prijavili ste se sa privremenim kodom iz e-pošte.\nDa biste završili prijavljivanje morate postaviti novu lozinku ovdje:",
-       "resetpass-temp-password": "Privremena šifra:",
-       "resetpass-abort-generic": "Promjenu šifre/lozinke je prekinula ekstenzija.",
+       "resetpass-temp-password": "Privremena lozinka:",
+       "resetpass-abort-generic": "Promjenu lozinke prekinulo je proširenje.",
        "resetpass-expired": "Vaša lozinka je istekla. Postavite novu lozinku da biste se prijavili.",
-       "resetpass-expired-soft": "Vaša šifra je istekla i mora se resetirati. Molimo odaberite sada novu šifru ili kliknite  \"{{int:resetpass-submit-cancel}}\" da je resetirate kasnije.",
-       "resetpass-validity-soft": "Vaša šifra nije valjana: $1\n\nMolimo odaberite novu šifru ili kliknite \"{{int:resetpass-submit-cancel}}\" da je resetirate kasnije.",
-       "passwordreset": "Poništavanje šifre",
-       "passwordreset-text-one": "Ispunite ovaj obrazac da biste resetovali Vašu šifru/lozinku.",
+       "resetpass-expired-soft": "Vaša lozinka je istekla i mora se resetirati. Molimo odaberite sada novu lozinka ili kliknite  \"{{int:resetpass-submit-cancel}}\" da je resetirate kasnije.",
+       "resetpass-validity-soft": "Vaša lozinka nije valjana: $1\n\nMolimo odaberite novu lozinku ili kliknite \"{{int:resetpass-submit-cancel}}\" da je resetirate kasnije.",
+       "passwordreset": "Ponovo postavljanje lozinke",
+       "passwordreset-text-one": "Ispunite ovaj obrazac da biste dobili privremenu lozinku na Vašu adresu e-pošte.",
        "passwordreset-text-many": "{{PLURAL:$1|Ispunite jedno od polja kako biste dobili privremenu lozinku putem e-pošte.}}",
-       "passwordreset-disabled": "Poništavanje šifre  je onemogućeno na ovoj wiki.",
+       "passwordreset-disabled": "Ponovo postavljanje lozinke je onemogućeno na ovom wikiju.",
        "passwordreset-emaildisabled": "E-pošta je onemogućena na ovom wikiju.",
        "passwordreset-username": "Korisničko ime:",
        "passwordreset-domain": "Domen:",
        "newarticle": "(Novi)",
        "newarticletext": "Došli ste na stranicu koja još nema sadržaja.\n*Ako želite unijeti sadržaj, počnite tipkati u prozor ispod ovog teksta.\n*Ako Vam treba pomoć, idite na [$1 stranicu za pomoć].\n*Ako ste ovamo dospjeli slučajno, kliknite na dugme \"Nazad\" (''Back'') u Vašem internetskom pregledniku.",
        "anontalkpagetext": "----''Ovo je stranica za razgovor za anonimnog korisnika koji još nije napravio nalog ili ga ne koristi.\nZbog toga moramo da koristimo brojčanu IP adresu kako bismo identifikovali njega ili nju.\nTakvu adresu može dijeliti više korisnika.\nAko ste anonimni korisnik i mislite da su vam upućene nebitne primjedbe, molimo Vas da [[Special:UserLogin/signup|napravite nalog]] ili se [[Special:UserLogin|prijavite]] da biste izbjegli buduću zabunu sa ostalim anonimnim korisnicima.''",
-       "noarticletext": "Na ovoj stranici trenutno nema teksta.\nMožete [[Special:Search/{{PAGENAME}}|tražiti naslov ove stranice]] na drugim stranicama.\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tražiti u povezanim zapisnicima] ili [{{fullurl:{{FULLPAGENAME}}|action=edit}} urediti ovu stranicu]</span>.",
+       "noarticletext": "Na ovoj stranici trenutno nema teksta.\nMožete [[Special:Search/{{PAGENAME}}|tražiti naslov ove stranice]] na drugim stranicama,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tražiti u povezanim zapisnicima] ili [{{fullurl:{{FULLPAGENAME}}|action=edit}} napraviti ovu stranicu]</span>.",
        "noarticletext-nopermission": "Trenutno nema teksta na ovoj stranici.\nMožete [[Special:Search/{{PAGENAME}}|tražiti ovaj naslov stranice]] na drugim stranicama ili <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pretražiti povezane zapisnike]</span>, ali nemate dozvolu da napravite ovu stranicu.",
        "missing-revision": "Uređivanje broj $1 na stranici \"{{FULLPAGENAME}}\" ne postoji.\n\nOvo se obično dešava kad pratite zastarjelu vezu na stranicu koja je obrisana.\nViše informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} protokolu brisanja].",
        "userpage-userdoesnotexist": "Korisnički račun \"<nowiki>$1</nowiki>\" nije registrovan.\nMolimo provjerite da li želite napraviti/izmijeniti ovu stranicu.",
        "userrights": "Postavke korisničkih prava",
        "userrights-lookup-user": "Menadžment korisničkih grupa",
        "userrights-user-editname": "Upišite korisničko ime:",
-       "editusergroup": "Uredi korisničke grupe",
+       "editusergroup": "Uredi {{GENDER:$1|korisničke}} grupe",
        "editinguser": "Mijenjate korisnička prava korisnika <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Uredi korisničke grupe",
        "saveusergroups": "Sačuvaj korisničke grupe",
        "userrights-changeable-col": "Grupe koje možete mijenjati",
        "userrights-unchangeable-col": "Grupe koje ne možete mijenjati",
        "userrights-conflict": "Sukob u izmjeni korisničkih prava! Molimo da razmotrite i potvrdite Vaše promjene.",
-       "userrights-removed-self": "Uspješno ste uklonili vlastite prava. Zbog toga više niste u stanju pristupiti ovoj stranici.",
+       "userrights-removed-self": "Uklonili ste vlastita prava. Zbog toga više ne možete pristupiti ovoj stranici.",
        "group": "Grupa:",
        "group-user": "Korisnici",
        "group-autoconfirmed": "Potvrđeni korisnici",
        "right-managechangetags": "Napravi i briši [[Special:Tags|oznake]] iz baze podataka",
        "right-applychangetags": "Primijeni [[Special:Tags|oznake]] na nečije izmjene",
        "right-changetags": "Dodavanje ili uklanjanje raznih [[Special:Tags|oznaka]] na pojedinačnim verzijama i unosima zapisnika",
+       "grant-group-page-interaction": "Upravljanje stranicama",
+       "grant-group-watchlist-interaction": "Upravljanje Vašim spiskom praćenja",
+       "grant-group-high-volume": "Izvršavanje velikog broja radnji",
+       "grant-group-customization": "Prilagodbe i postavke",
+       "grant-group-other": "Raznovrsno djelovanje",
        "grant-createeditmovepage": "Pravljenje, uređivanje i premještanje stranica",
+       "grant-editmycssjs": "Uređivanje Vašeg korisničkog CSS-a ili JavaScripta",
+       "grant-editmyoptions": "Uređivanje Vaših postavki",
        "grant-editmywatchlist": "Uređivanje Vašeg spiska praćenja",
        "grant-editpage": "Uređivanje postojećih stranica",
        "grant-editprotected": "Uređivanje zaštićenih stranica",
-       "grant-highvolume": "Uređivanja velikog opsega",
+       "grant-highvolume": "Veliki broj izmjena",
+       "grant-patrol": "Patroliranje izmjena stranica",
        "grant-uploadeditmovefile": "Postavljanje, zamjena i premještanje datoteka",
        "grant-uploadfile": "Postavljanje novih datoteka",
+       "grant-basic": "Osnovna prava",
        "grant-viewmywatchlist": "Pregled Vašeg spiska praćenja",
        "newuserlogpage": "Zapisnik novih korisnika",
        "newuserlogpagetext": "Ovo je zapisnik o registraciji novih korisnika.",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|spisak novih stranica]])",
        "recentchanges-submit": "Prikaži",
        "rcnotefrom": "Ispod {{PLURAL:$5|je izmjena|su izmjene}} od <strong>$3, $4</strong> (do <strong>$1</strong> prikazano).",
-       "rclistfrom": "Prikaži nove izmjene počev od $3 $2",
+       "rclistfrom": "Prikaži nove izmjene počev od $3 $2",
        "rcshowhideminor": "$1 manje izmjene",
        "rcshowhideminor-show": "Prikaži",
        "rcshowhideminor-hide": "Sakrij",
        "recentchangeslinked-page": "Naslov stranice:",
        "recentchangeslinked-to": "Pokaži promjene stranica koji su povezane sa datom stranicom",
        "recentchanges-page-added-to-category": "[[:$1]] dodana je u kategoriju",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] i još {{PLURAL:$2|jedna stranica|$2 stranice|$2 stranica}} su dodane u kategoriju",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] i još [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedna stranica|$2 stranice|$2 stranica}}]] su dodane u kategoriju",
        "recentchanges-page-removed-from-category": "[[:$1]] je uklonjena iz kategorije",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] i još {{PLURAL:$2|jedna stranica|$2 stranice|$2 stranica}} su uklonjene iz kategorije",
        "autochange-username": "Automatska promjena MediaWikija",
        "foreign-structured-upload-form-label-own-work": "Ovo je moje djelo",
        "foreign-structured-upload-form-label-infoform-categories": "Kategorije",
        "foreign-structured-upload-form-label-infoform-date": "Datum",
-       "foreign-structured-upload-form-label-own-work-message-local": "Potvrđujem da postavljam ovu datoteku u skladu s uvjetima korištenja i pravilima o licenciranju na {{GRAMMAR:dativ|{{SITENAME}}}}.",
+       "foreign-structured-upload-form-label-own-work-message-local": "Potvrđujem da postavljam ovu datoteku u skladu s uslovima korištenja i pravilima o licenciranju na {{GRAMMAR:dativ|{{SITENAME}}}}.",
        "foreign-structured-upload-form-label-not-own-work-message-local": "Ako niste u stanju postaviti ovu datoteku pod pravilima {{GRAMMAR:genitiv|{{SITENAME}}}}, molimo zatvorite ovaj prozor i pokušajte drugom metodom.",
        "foreign-structured-upload-form-label-not-own-work-local-local": "Također možete pokušati [[Special:Upload|na standardnoj stranici za postavljanje]].",
-       "foreign-structured-upload-form-label-own-work-message-default": "Shvatam da postavljam ovu datoteku na zajedničko spremište. Potvrđujem da to činim u skladu s uvjetima korištenja i ovdašnjim pravilima licenciranja.",
+       "foreign-structured-upload-form-label-own-work-message-default": "Shvatam da postavljam ovu datoteku na zajedničko spremište. Potvrđujem da to činim u skladu s uslovima korištenja i ovdašnjim pravilima licenciranja.",
        "foreign-structured-upload-form-label-not-own-work-message-default": "Ako niste u stanju postaviti ovu datoteku pod pravilima zajedničkog skladišta, molimo zatvorite ovaj prozor i pokušajte drugom metodom.",
        "foreign-structured-upload-form-label-not-own-work-local-default": "Možete također pokušati koristeći  [[Special:Upload|stranicu za postavljanje na  {{GRAMMAR:dativ|{{SITENAME}}}}]], ako se ova datoteka može postaviti pod tamošnjim pravilima.",
-       "foreign-structured-upload-form-label-own-work-message-shared": "Potvrđujem da posjedujem autorska prava za ovu datoteku i slažem se da ću je neopozivo postaviti na Wikimedia Commons pod licencom [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0], te se slažem s [https://wikimediafoundation.org/wiki/Terms_of_Use Uvjetima korištenja].",
+       "foreign-structured-upload-form-label-own-work-message-shared": "Potvrđujem da posjedujem autorska prava za ovu datoteku i slažem se da ću je neopozivo postaviti na Wikimedia Commons pod licencom [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0], te se slažem s [https://wikimediafoundation.org/wiki/Terms_of_Use uslovima korištenja].",
        "foreign-structured-upload-form-label-not-own-work-message-shared": "Ako ne posjedujete autorska prava za ovu datoteku ili je želite postaviti pod drugom licencom, imajte na umu da možete koristiti [https://commons.wikimedia.org/wiki/Special:UploadWizard čarobnjak za postavljanje datoteka na Commonsu].",
-       "foreign-structured-upload-form-label-not-own-work-local-shared": "Također možete koristiti [[Special:Upload|stranicu za postavljanje datoteka na projektu {{SITENAME}}]] ako politika stranice dozvoljava postavljanje ove datoteke.",
+       "foreign-structured-upload-form-label-not-own-work-local-shared": "Također možete koristiti [[Special:Upload|stranicu za postavljanje datoteka na {{GRAMMAR:dativ|{{SITENAME}}}}]] ako pravila te stranice dozvoljavaju postavljanje ove datoteke.",
        "backend-fail-stream": "Ne mogu emitirati datoteku $1.",
        "backend-fail-backup": "Ne može sigurnosno kopirati datoteku $1.",
        "backend-fail-notexists": "Datoteka $1 ne postoji.",
        "wlshowlast": "Prikaži posljednjih $1 sati $2 dana",
        "watchlist-hide": "Sakrij",
        "watchlist-submit": "Prikaži",
-       "wlshowtime": "Prikaži posljednjih:",
+       "wlshowtime": "Vremensko razdoblje za prikaz:",
        "wlshowhideminor": "manje izmjene",
        "wlshowhidebots": "botove",
        "wlshowhideliu": "registrovane korisnike",
        "javascripttest-pagetext-frameworks": "Molimo Vas izaberite jednu od sljedećih testnih okvira: $1",
        "javascripttest-pagetext-skins": "Izaberite s kojom temom želite da pokrenete probu:",
        "javascripttest-qunit-intro": "Pogledajte [$1 dokumentaciju za testiranje] na mediawiki.org.",
-       "tooltip-pt-userpage": "Vaša korisnička stranica",
+       "tooltip-pt-userpage": "{{GENDER:|Vaša}} korisnička stranica",
        "tooltip-pt-anonuserpage": "Korisnička stranica za ip koju Vi uređujete kao",
-       "tooltip-pt-mytalk": "Vaša stranica za razgovor",
+       "tooltip-pt-mytalk": "{{GENDER:|Vaša}} stranica za razgovor",
        "tooltip-pt-anontalk": "Razgovor o doprinosu sa ove IP adrese",
-       "tooltip-pt-preferences": "Vaše postavke",
+       "tooltip-pt-preferences": "{{GENDER:|Vaše}} postavke",
        "tooltip-pt-watchlist": "Spisak stranica koje pratite",
-       "tooltip-pt-mycontris": "Spisak vaših doprinosa",
+       "tooltip-pt-mycontris": "Spisak {{GENDER:|Vaših}} doprinosa",
        "tooltip-pt-login": "Predlažemo da se prijavite, ali nije obvezno.",
        "tooltip-pt-logout": "Odjavi me",
        "tooltip-pt-createaccount": "Ohrabrujemo vas da otvorite nalog i prijavite se, međutim to nije obavezno",
        "tooltip-t-recentchangeslinked": "Nedavne izmjene na stranicama koje su povezane sa ovom",
        "tooltip-feed-rss": "RSS za ovu stranicu",
        "tooltip-feed-atom": "Atom za ovu stranicu",
-       "tooltip-t-contributions": "Pogledajte spisak doprinosa ovog korisnika",
-       "tooltip-t-emailuser": "Pošaljite pismo ovom korisniku",
+       "tooltip-t-contributions": "Pogledajte spisak doprinosa {{GENDER:$1|ovog korisnika|ove korisnice|ove osobe}}",
+       "tooltip-t-emailuser": "Pošaljite e-poruku {{GENDER:$1|ovom korisniku}}",
        "tooltip-t-info": "Više informacija o ovoj stranici",
        "tooltip-t-upload": "Postavi slike i druge medije",
        "tooltip-t-specialpages": "Spisak svih posebnih stranica",
        "version-poweredby-others": "ostali",
        "version-poweredby-translators": "translatewiki.net prevodioci",
        "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(li) mijenjati pod uvjetima opće javne GNU licence kao što je objavljeno od strane \"Free Software Foundationa\", bilo u verziji 2 licence ili (po Vašoj volji) nekoj od kasnijih verzija.\n\nMediawiki se distribuira u nadi da će biti korisna, ali BEZ IKAKVIH GARANCIJA, čak i bez ikakvih posrednih garancija o KOMERCIJALNOSTI ili DOSTUPNOSTI ZA ODREĐENU SVRHU. Pogledajte opću javnu GNU licencu za više detalja.\n\nTrebali biste dobiti [{{SERVER}}{{SCRIPTPATH}}/KOPIJU opće javne GNU licence] zajedno s ovim programom. Ako niste, pišite \"Free Software Foundationu\" na adresu: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ili je pročitajte [//www.gnu.org/licenses/old-licenses/gpl-2.0.html ovdje].",
+       "version-license-info": "Mediawiki je slobodni softver; možete ga redistribuirati i(li) mijenjati pod uslovima opće javne GNU licence kao što je objavljeno od strane \"Free Software Foundationa\", bilo u verziji 2 licence ili (po Vašoj volji) nekoj od kasnijih verzija.\n\nMediawiki se distribuira u nadi da će biti korisna, ali BEZ IKAKVIH GARANCIJA, čak i bez ikakvih posrednih garancija o KOMERCIJALNOSTI ili DOSTUPNOSTI ZA ODREĐENU SVRHU. Pogledajte opću javnu GNU licencu za više detalja.\n\nTrebali biste dobiti [{{SERVER}}{{SCRIPTPATH}}/KOPIJU opće javne GNU licence] zajedno s ovim programom. Ako niste, pišite \"Free Software Foundationu\" na adresu: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ili je pročitajte [//www.gnu.org/licenses/old-licenses/gpl-2.0.html ovdje].",
        "version-software": "Instalirani softver",
        "version-software-product": "Proizvod",
        "version-software-version": "Verzija",
        "tags-edit-revision-legend": "Dodaj ili ukloni oznake sa {{PLURAL:$1|ove verzije|svih $1 verzija}}",
        "tags-edit-logentry-legend": "Dodaj ili ukloni oznake sa {{PLURAL:$1|ove zapisničke stavke|svih $1 zapisničkih stavki}}",
        "tags-edit-existing-tags": "Postojeće oznake:",
-       "tags-edit-existing-tags-none": "\"Nema\"",
+       "tags-edit-existing-tags-none": "<em>Nema</em>",
        "tags-edit-new-tags": "Nove oznake:",
        "tags-edit-add": "Dodaj ove oznake:",
        "tags-edit-remove": "Ukloni ove oznake:",
        "tags-edit-reason": "Razlog:",
        "tags-edit-revision-submit": "Primijeni izmjene {{PLURAL:$1|ovoj verziji|svim $1 verzijama}}",
        "tags-edit-logentry-submit": "Primijeni izmjene {{PLURAL:$1|ovom zapisničkom unosu|svim $1 zapisničkim unosima}}",
-       "tags-edit-success": "Izmjene su uspješno primijenjene.",
+       "tags-edit-success": "Izmjene su primijenjene.",
        "tags-edit-failure": "Nije bilo moguće primijeniti izmjene:\n$1",
        "tags-edit-nooldid-title": "Neispravna odredišna verzija",
        "tags-edit-nooldid-text": "Niste izabrali odredišnu verziju na koju treba primijeniti ovu funkciju, ili odredišna verzija na postoji.",
index eb9d6c9..33b619a 100644 (file)
        "nocookiesfornew": "No s'ha creat el compte d'usuari, ja que no es podia confirmar el seu origen.\nVerifiqueu que teniu habilitades les galetes al vostre navegador, torneu a carregar aquesta pàgina i intenteu-lo de nou.",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "No heu especificat un nom vàlid d'usuari.",
-       "loginsuccesstitle": "S'ha iniciat la sessió amb èxit",
+       "loginsuccesstitle": "Sessió iniciada",
        "loginsuccess": "Heu iniciat la sessió a {{SITENAME}} com a «$1».",
        "nosuchuser": "No hi ha cap usuari anomenat «$1».\nReviseu-ne l'ortografia (recordeu que es distingeixen les majúscules i minúscules), o [[Special:UserLogin/signup|creeu un compte d'usuari nou]].",
        "nosuchusershort": "No hi ha cap usuari anomenat «$1». Comproveu que ho hàgiu escrit correctament.",
        "createaccount-title": "Creació d'un compte a {{SITENAME}}",
        "createaccount-text": "Algú ha creat un compte d'usuari anomenat $2 en el projecte {{SITENAME}}\n($4) amb la vostra adreça de correu electrònic. La contrasenya per a l'usuari «$2» és «$3». Hauríeu d'accedir al compte i canviar-vos aquesta contrasenya com més aviat millor.\n\nSi no hi teniu cap relació i aquest compte s'ha creat per error, simplement ignoreu el missatge.",
        "login-throttled": "Heu realitzat massa intents d'accés a la sessió.\nEspereu $1 abans de tornar-ho a provar.",
-       "login-abort-generic": "L'entrada al compte d'usuari no ha reeixit - S'ha interromput.",
+       "login-abort-generic": "L'inici de sessió ha fallat - Operació anul·lada.",
        "login-migrated-generic": "S'ha migrat el vostre compte, i el vostre nom d'usuari ja no existeix en aquest wiki.",
        "loginlanguagelabel": "Llengua: $1",
        "suspicious-userlogout": "S'ha denegat la vostra petició per a tancar la sessió, ja que sembla que va ser enviada per un navegador defectuós o un servidor intermediari.",
        "newpassword": "Contrasenya nova",
        "retypenew": "Torneu a escriure la nova contrasenya:",
        "resetpass_submit": "Definiu una contrasenya i inicieu una sessió",
-       "changepassword-success": "S'ha canviat la vostra contrasenya amb èxit!",
+       "changepassword-success": "S'ha canviat la vostra contrasenya!",
        "changepassword-throttled": "Heu realitzat massa intents d'inici de sessió.\nEspereu $1 abans de tornar-ho a provar.",
        "botpasswords": "Contrasenyes de bot",
        "botpasswords-disabled": "S'han inhabilitat les contrasenyes dels bots",
        "botpasswords-no-central-id": "Per a utilitzar contrasenyes de bots heu d'haver iniciat una sessió en un compte centralitzat.",
+       "botpasswords-existing": "Contrasenyes de bot existents",
+       "botpasswords-createnew": "Crea una contrasenya de bot nova",
+       "botpasswords-editexisting": "Edita una contrasenya de bot existent",
        "botpasswords-label-appid": "Nom del bot:",
        "botpasswords-label-create": "Crea",
        "botpasswords-label-update": "Actualitza",
        "botpasswords-label-cancel": "Cancel·la",
        "botpasswords-label-delete": "Suprimeix",
        "botpasswords-label-resetpassword": "Reinicia la contrasenya",
+       "botpasswords-label-grants": "Permisos aplicables:",
+       "botpasswords-label-restrictions": "Restriccions d'ús:",
+       "botpasswords-label-grants-column": "Concedit",
+       "botpasswords-bad-appid": "El nom del bot «$1» no és vàlid.",
+       "botpasswords-insert-failed": "No s'ha pogut afegir el nom del bot «$1». Ja hi estava afegit?",
+       "botpasswords-update-failed": "No s'ha pogut actualitzar el nom del bot «$1». Hi estava suprimit?",
+       "botpasswords-created-title": "S'ha creat la contrasenya del bot",
        "resetpass_forbidden": "No poden canviar-se les contrasenyes",
        "resetpass-no-info": "Heu d'estar registrats en un compte per a poder accedir directament a aquesta pàgina.",
        "resetpass-submit-loggedin": "Canvia la contrasenya",
        "passwordreset-emailtext-ip": "Algú (vós mateix segurament, des de l'adreça IP $1) ha demanat una reinicialització de la vostra contrasenya al projecte {{SITENAME}} ($4). {{PLURAL:$3|El següent compte d'usuari està associat|Els següents comptes d'usuari estan associats}} amb aquesta adreça de correu electrònic:\n\n$2\n\n{{PLURAL:$3|Aquesta contrasenya temporal caducarà|Aquestes contrasenyes temporals caducaran}} en {{PLURAL:$5|un dia|$5 dies}}.\nHauríeu d'entrar al compte per a fixar-hi una nova contrasenya al més aviat possible. Si algú que no sou vós és qui ha fet aquesta petició o si heu recordat la contrasenya original i ja no la voleu canviar, podeu ignorar aquest missatge i seguir utilitzant la vostra antiga contrasenya.",
        "passwordreset-emailtext-user": "L'usuari $1 de {{SITENAME}} ha demanat una reinicialització de la vostra contrasenya per al projecte {{SITENAME}} ($4). {{PLURAL:$3|El següent compte d'usuari està associat|Els següents comptes d'usuari estan associats}} amb aquesta adreça de correu electrònic:\n\n$2\n\n{{PLURAL:$3|Aquesta contrasenya temporal caducarà|Aquestes contrasenyes temporals caducaran}} en {{PLURAL:$5|un dia|$5 dies}}.\nHauríeu d'entrar ara per fixar una nova contrasenya. Si algú que no sou vós és qui ha fet aquesta petició o si heu recordat la contrasenya original i ja no la voleu canviar, podeu ignorar aquest missatge i seguir utilitzant la vostra antiga contrasenya.",
        "passwordreset-emailelement": "Nom d'usuari: \n$1\n\nContrasenya temporal: \n$2",
-       "passwordreset-emailsentemail": "Si aquesta és una adreça electrònica registrada amb el vostre compte, s’hi enviarà un missatge de restabliment de contrasenya.",
+       "passwordreset-emailsentemail": "Si aquesta adreça electrònica està associada al vostre compte, s’enviarà un missatge de restabliment de contrasenya.",
        "passwordreset-emailsent-capture": "S'ha enviat un correu electrònic de reinicialització de contrasenya, tal com es mostra a continuació.",
        "passwordreset-emailerror-capture": "S'ha generat un correu electrònic de renovació de contrasenya, que es mostra a continuació, però ha fallat l'enviament a {{GENDER:$2:l'usuari|la usuària}}: $1",
        "changeemail": "Canvia o elimina l’adreça electrònica",
        "copyrightwarning2": "Si us plau, tingueu en compte que totes les contribucions al projecte {{SITENAME}} poden ser corregides, alterades o esborrades per altres usuaris. Si no desitgeu la modificació i distribució lliure dels vostres escrits sense el vostre consentiment, no els poseu ací.<br />\nA més a més, en enviar el vostre text, doneu fe que és vostra l'autoria, o bé de fonts en el domini públic o altres recursos lliures similars (consulteu $1 per a més detalls).\n'''No feu servir textos amb drets d'autor sense permís!'''",
        "editpage-cannot-use-custom-model": "El model de contingut d'aquesta pàgina no pot ser canviat.",
        "longpageerror": "'''Error: El text que heu introduït és {{PLURAL:$1|d'un kilobyte|de $1 kilobytes}} i sobrepassa el màxim permès de {{PLURAL:$2|one kilobyte|$2 kilobytes}}.'''\nNo es pot desar.",
-       "readonlywarning": "'''Avís: La base de dades està tancada per manteniment, de manera que no podreu desar els canvis ara mateix.'''\nÉs possible que vulgueu copiar i enganxar el text en un arxiu de text i desar-ho més tard.\n\nL'administrador que l'ha bloquejada ha donat la següent explicació: $1",
+       "readonlywarning": "<strong>Avís: La base de dades està tancada per manteniment, de manera que no podreu desar els canvis ara mateix.</strong>\nÉs possible que vulgueu copiar i enganxar el text en un arxiu de text i desar-ho més tard.\n\nL'administrador de sistema que l'ha bloquejada ha donat la següent explicació: $1",
        "protectedpagewarning": "'''ATENCIÓ: Aquesta pàgina està bloquejada i només els usuaris amb drets d'administrador la poden modificar.\nA continuació es mostra la darrera entrada del registre com a referència:",
        "semiprotectedpagewarning": "'''Avís:''' Aquesta pàgina està bloquejada i només pot ser modificada per usuaris registrats.\nA continuació es mostra la darrera entrada del registre com a referència:",
        "cascadeprotectedwarning": "'''Atenció:''' Aquesta pàgina està protegida de forma que només la poden modificar els administradors, ja que està inclosa a {{PLURAL:$1|la següent pàgina|les següents pàgines}} amb l'opció de «protecció en cascada» activada:",
        "permissionserrors": "Error de permisos",
        "permissionserrorstext": "No teniu permisos per a fer-ho, {{PLURAL:$1|pel següent motiu|pels següents motius}}:",
        "permissionserrorstext-withaction": "No teniu permís per a $2, {{PLURAL:$1|pel motiu següent|pels motius següents}}:",
-       "contentmodelediterror": "No podeu modificar aquesta revisió perquè el seu model de contingut és <code>$1</code>, i el model de contingut actual de la pàgina és <code>$2</code>.",
+       "contentmodelediterror": "No podeu modificar aquesta revisió perquè el seu model de contingut és <code>$1</code>, que difereix del model de contingut actual de la pàgina <code>$2</code>.",
        "recreate-moveddeleted-warn": "'''Avís: esteu creant una pàgina que s'ha suprimit prèviament.'''\n\nHauríeu de considerar si és realment necessari continuar editant aquesta pàgina.\nA continuació s'ofereix el registre de supressions i de reanomenaments de la pàgina:",
        "moveddeleted-notice": "S'ha suprimit aquesta pàgina.\nA continuació us mostrem com a referència el registre d'esborraments i reanomenaments de la pàgina.",
        "moveddeleted-notice-recent": "S’ha suprimit aquesta pàgina recentment (en les últimes 24 hores).\nA continuació us mostrem com a referència el registre de supressions i reanomenaments de la pàgina.",
        "revdelete-unsuppress": "Suprimir les restriccions de les revisions restaurades",
        "revdelete-log": "Motiu:",
        "revdelete-submit": "Aplica a {{PLURAL:$1|la revisió seleccionada|les revisions seleccionades}}",
-       "revdelete-success": "'''La visibilitat d'aquesta revisió s'ha actualitzat correctament.'''",
+       "revdelete-success": "La visibilitat d'aquesta revisió s'ha actualitzat.",
        "revdelete-failure": "'''La visibilitat de la revisió no ha pogut actualitzar-se:'''\n$1",
        "logdelete-success": "'''S'ha establert correctament la visibilitat d'aquest element.'''",
        "logdelete-failure": "'''No s'ha pogut establir la visibilitat del registre:'''\n$1",
        "mergehistory-empty": "No pot fusionar-se cap revisió.",
        "mergehistory-done": "{{PLURAL:$3|S’ha|S’han}} fusionat correctament $3 {{PLURAL:$3|revisió|revisions}} de $1 a [[:$2]].",
        "mergehistory-fail": "No s'ha pogut realitzar la fusió de l'historial, comproveu la pàgina i els paràmetres horaris.",
+       "mergehistory-fail-bad-timestamp": "La marca horària no és vàlida.",
+       "mergehistory-fail-invalid-source": "La pàgina font no és vàlida.",
+       "mergehistory-fail-invalid-dest": "La pàgina de destinació no és vàlida.",
+       "mergehistory-fail-self-merge": "Les pàgines d'origen i de destinació no poden ser la mateixa",
        "mergehistory-fail-toobig": "No s'ha pogut fer la fusió de l'historial perquè es mourien més del límit de $1 {{PLURAL:$1|revisió|revisions}}.",
        "mergehistory-no-source": "La pàgina d'origen $1 no existeix.",
        "mergehistory-no-destination": "La pàgina de destinació $1 no existeix.",
        "userrights": "Gestió dels permisos d’usuari",
        "userrights-lookup-user": "Gestiona els grups d'usuari",
        "userrights-user-editname": "Introduïu un nom d'usuari:",
-       "editusergroup": "Edita els grups d'usuaris",
+       "editusergroup": "Edita els grups d'{{GENDER:$1|usuari}}",
        "editinguser": "Modificació dels permisos de {{GENDER:$1|l'usuari|la usuària}} <strong>[[User:$1|$1]]</strong>$2",
        "userrights-editusergroup": "Edita els grups d'usuaris",
-       "saveusergroups": "Desa els grups d'usuari",
+       "saveusergroups": "Desa els grups d'{{GENDER:$1|usuari}}",
        "userrights-groupsmember": "Membre de:",
        "userrights-groupsmember-auto": "Membre implícit de:",
        "userrights-groupsmember-type": "$1",
        "userrights-unchangeable-col": "Grups que no podeu canviar",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "Conflicte de canvis dels permisos d'usuari. Reviseu i confirmeu els canvis.",
-       "userrights-removed-self": "Heu suprimit els vostres propis permisos correctament. Per tant, ja no podeu tornar a accedir a aquesta pàgina.",
+       "userrights-removed-self": "Heu suprimit els vostres propis permisos. Per tant, ja no podeu tornar a accedir a aquesta pàgina.",
        "group": "Grup:",
        "group-user": "Usuaris",
        "group-autoconfirmed": "Usuaris autoconfirmats",
        "grant-group-file-interaction": "Interacció amb fitxes multimèdia",
        "grant-group-watchlist-interaction": "Interacció amb la vostra llista de seguiment",
        "grant-group-email": "Enviament de correu",
+       "grant-group-customization": "Personalització i preferències",
+       "grant-group-administration": "Realitza accions administratives",
+       "grant-group-other": "Activitat miscel·lània",
+       "grant-blockusers": "Bloca i desbloca usuaris",
        "grant-createaccount": "Crea comptes",
        "grant-createeditmovepage": "Crea, modifica i reanomena pàgines",
        "grant-delete": "Suprimeix pàgines, revisions i entrades de registre",
+       "grant-editinterface": "Modifica l'espai de noms MediaWiki i els CSS/JavaScript d'usuari",
+       "grant-editmywatchlist": "Modifica la llista de seguiment",
+       "grant-editpage": "Modifica les pàgines existents",
+       "grant-editprotected": "Modifica pàgines protegides",
+       "grant-highvolume": "Edició d'alt volum",
+       "grant-oversight": "Amaga usuaris i suprimeix revisions",
+       "grant-uploadfile": "Carrega fitxers nous",
+       "grant-basic": "Permisos bàsics",
+       "grant-viewdeleted": "Mostra fitxers eliminats i pàgines",
+       "grant-viewmywatchlist": "Modifica la llista de seguiment",
        "newuserlogpage": "Registre de creació d'usuaris",
        "newuserlogpagetext": "Aquest és un registre de creació de nous usuaris.",
        "rightslog": "Registre dels permisos d'usuari",
        "action-createpage": "crear pàgines",
        "action-createtalk": "crear pàgines de discussió",
        "action-createaccount": "crear aquest compte d'usuari",
+       "action-autocreateaccount": "crea automàtica aquest compte d'usuari extern",
        "action-history": "mostra l'historial de la pàgina",
        "action-minoredit": "marcar aquesta modificació com a menor",
        "action-move": "moure aquesta pàgina",
        "rcshowhidemine": "$1 edicions pròpies",
        "rcshowhidemine-show": "Mostra",
        "rcshowhidemine-hide": "Amaga",
-       "rcshowhidecategorization": "$1 la categorització de la pàgina",
+       "rcshowhidecategorization": "$1 categoritzacions de pàgina",
        "rcshowhidecategorization-show": "Mostra",
        "rcshowhidecategorization-hide": "Amaga",
        "rclinks": "Mostra els darrers $1 canvis en els darrers $2 dies<br />$3",
        "recentchangeslinked-page": "Nom de la pàgina:",
        "recentchangeslinked-to": "Mostra els canvis de les pàgines enllaçades amb la pàgina donada",
        "recentchanges-page-added-to-category": "[[:$1]] afegida a la categoria",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] i {{PLURAL:$2|una pàgina|$2 pàgines}} més afegides a la categoria",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] i [[Special:WhatLinksHere/$1|{{PLURAL:$2|una pàgina|$2 pàgines}}]] més afegides a la categoria",
        "recentchanges-page-removed-from-category": "[[:$1]] treta de la categoria",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] i {{PLURAL:$2|una pàgina|$2 pàgines}} més tretes de la categoria",
        "autochange-username": "Canvi automàtic del MediaWiki",
        "apisandbox": "Pàgina de proves de l'API",
        "apisandbox-api-disabled": "L'API està desactivada en aquest lloc.",
        "apisandbox-intro": "Utilitzeu aquesta pàgina per experimentar amb l'<nowiki />'''API de web service de MediaWiki'''.\nVisiteu [//www.mediawiki.org/wiki/API:Main_page la documentació de l'API] per a més informació sobre l'ús de l'API. Exemple: [//www.mediawiki.org/wiki/API#A_simple_example recuperar el contingut d'una Pàgina Principal]. Seleccioneu una acció per veure més exemples.\n\nTingueu en compte que, encara que això és una pàgina de proves, les accions que feu en aquesta pàgina poden modificar la wiki.",
+       "apisandbox-unfullscreen": "Mostra la pàgina",
        "apisandbox-submit": "Fes sol·licitud",
        "apisandbox-reset": "Neteja",
-       "apisandbox-examples": "Exemple",
-       "apisandbox-results": "Resultat",
+       "apisandbox-retry": "Torna a provar",
+       "apisandbox-loading": "S'està carregant la informació del mòdul d'API «$1»...",
+       "apisandbox-helpurls": "Enllaços d'ajuda",
+       "apisandbox-examples": "Exemples",
+       "apisandbox-dynamic-parameters": "Paràmetres adicionals",
+       "apisandbox-dynamic-parameters-add-label": "Afegeix un paràmetre:",
+       "apisandbox-dynamic-parameters-add-placeholder": "Nom del paràmetre",
+       "apisandbox-deprecated-parameters": "Paràmetres obsolets",
+       "apisandbox-submit-invalid-fields-title": "Alguns camps no són vàlids",
+       "apisandbox-results": "Resultats",
        "apisandbox-request-url-label": "Sol·licita URL:",
        "apisandbox-request-time": "Temps de sol·licitud: $1",
        "booksources": "Obres de referència",
        "listgrouprights-namespaceprotection-namespace": "Espai de noms",
        "listgrouprights-namespaceprotection-restrictedto": "Permisos que permeten modificar a l'usuari",
        "listgrants": "Autoritzacions",
-       "listgrants-grant": "Autoritza",
+       "listgrants-grant": "Concedeix",
        "listgrants-rights": "Permisos",
        "trackingcategories": "Categories de seguiment",
        "trackingcategories-summary": "Aquesta pàgina llista les categories de seguiment que s'omplen automàticament pel programari MediaWiki. Es poden canviar els seus noms modificant els missatges del sistema corresponents en l'espai de noms {{ns:8}}.",
        "wlshowlast": "Mostra les darreres $1 hores, els darrers $2 dies",
        "watchlist-hide": "Amaga",
        "watchlist-submit": "Mostra",
+       "wlshowtime": "Període de temps per mostrar:",
        "wlshowhideminor": "edicions menors",
        "wlshowhidebots": "bots",
        "wlshowhideliu": "usuaris registrats",
        "wlshowhideanons": "usuaris anònims",
        "wlshowhidepatr": "edicions supervisades",
        "wlshowhidemine": "les meves edicions",
+       "wlshowhidecategorization": "categorització de pàgines",
        "watchlist-options": "Opcions de la llista de seguiment",
        "watching": "S'està vigilant...",
        "unwatching": "S'està desatenent...",
        "changecontentmodel-title-label": "Títol de la pàgina",
        "changecontentmodel-model-label": "Nou model de contingut",
        "changecontentmodel-reason-label": "Motiu:",
+       "changecontentmodel-submit": "Canvia",
        "changecontentmodel-success-title": "S'ha canviat el model de contingut",
        "changecontentmodel-success-text": "S'ha canviat el tipus de contingut de [[:$1]].",
        "changecontentmodel-cannot-convert": "El contingut a [[:$1]] no es pot convertir a un tipus de $2.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisió|revisions}} importades",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisió|revisions}} importades de $2",
        "javascripttest": "Proves de JavaScript",
-       "javascripttest-pagetext-noframework": "Es reserva la pàgina per a l'execució de tests amb JavaScript.",
-       "javascripttest-pagetext-unknownframework": "L'entorn de proves «$1» és desconegut.",
        "javascripttest-pagetext-unknownaction": "Acció desconeguda «$1».",
-       "javascripttest-pagetext-frameworks": "Trieu un dels següents entorns de prova: $1",
-       "javascripttest-pagetext-skins": "Trieu un tema per a executar-hi els tests:",
        "javascripttest-qunit-intro": "Consulteu la [documentació de tests de $1] a mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|La vostra}} pàgina d'usuari",
        "tooltip-pt-anonuserpage": "La pàgina d'usuari per la ip que utilitzeu",
        "newimages-legend": "Nom del fitxer",
        "newimages-label": "Nom de fitxer (o part d'ell):",
        "newimages-showbots": "Mostra les càrregues dels bots",
+       "newimages-hidepatrolled": "Amaga les càrregues patrullades",
        "noimages": "Res per veure.",
        "ilsubmit": "Cerca",
        "bydate": "per data",
        "watchlisttools-edit": "Visualitza i edita la llista de seguiment",
        "watchlisttools-raw": "Edita la llista de seguiment sense format",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussió]])",
+       "timezone-local": "Local",
        "duplicate-defaultsort": "Atenció: La clau d'ordenació per defecte \"$2\" invalida l'anterior clau \"$1\".",
        "duplicate-displaytitle": "<strong>Avís:</strong> El títol a mostrar «$2» sobreescriu l'anterior títol a mostrar «$1».",
        "invalid-indicator-name": "<strong>Error:</strong> No pot estar buit l'atribut <code>name</code> dels indicadors d'estat de la pàgina.",
        "version-libraries-description": "Descripció",
        "version-libraries-authors": "Autors",
        "redirect": "Redirigeix per fitxer, usuari, pàgina 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 (donats un ID de la revisió o un ID de pàgina), o a una pàgina d'usuari (donat un ID numèric d'usuari). Ús: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Vés-hi",
        "redirect-lookup": "Consulta:",
        "tags-edit-revision-selected": "{{PLURAL:$1|Revisió seleccionada|Revisions seleccionades}} de [[:$2]]:",
        "tags-edit-logentry-legend": "Afegeix o suprimeix etiquetes {{PLURAL:$1|d'aquesta entrada del registre|de totes les entrades del registre}}",
        "tags-edit-existing-tags": "Etiquetes existents:",
-       "tags-edit-existing-tags-none": "''Cap''",
+       "tags-edit-existing-tags-none": "<em>Cap</em>",
        "tags-edit-new-tags": "Etiquetes noves:",
        "tags-edit-add": "Afegeix aquestes etiquetes:",
        "tags-edit-remove": "Treu aquestes etiquetes:",
        "tags-edit-reason": "Motiu:",
        "tags-edit-revision-submit": "Aplica els canvis a {{PLURAL:$1|a aquesta revisió|$1 revisions}}",
        "tags-edit-logentry-submit": "Aplica els canvis a {{PLURAL:$1|aquesta entrada de registre|$1 entrades de registre}}",
-       "tags-edit-success": "S’han aplicat els canvis correctament.",
+       "tags-edit-success": "S’han aplicat els canvis.",
        "tags-edit-failure": "No s’han pogut aplicar els canvis:\n$1",
        "tags-edit-nooldid-title": "Revisió de l'objectiu no vàlida",
        "tags-edit-none-selected": "Seleccioneu com a mínim una etiqueta per afegir o suprimir.",
        "expand_templates_preview": "Previsualitza",
        "expand_templates_preview_fail_html": "<em>Atès que {{SITENAME}} té HTML cru i hi ha hagut una pèrdua de dades de la sessió, s'ha amagat la vista prèvia com a mesura de precaució contra atacs en JavaScript.</em>\n\n<strong>Si això és un intent de previsualització legítim, torneu-ho a provar.</strong>\nSi encara no funciona, intenteu [[Special:UserLogout|finalitzar la sessió]] i iniciar-la de nou.",
        "expand_templates_preview_fail_html_anon": "<em>Atès que {{SITENAME}} té l'HTML cru habilitat i no heu iniciat una sessió, s'ha amagat la previsualització com a prevenció d'atacs en JavaScript.</em>\n\n<strong>Si això és un intent de previsualització legítim, [[Special:UserLogin|inicieu una sessió]] i torneu-ho a provar.</strong>",
-       "pagelanguage": "Selector de l'idioma de les pàgines",
+       "expand_templates_input_missing": "Cal que proporcioneu al menys algun text d'entrada.",
+       "pagelanguage": "Canvia l'idioma de la pàgina",
        "pagelang-name": "Pàgina",
        "pagelang-language": "Idioma",
        "pagelang-use-default": "Utilitza l'idioma per defecte",
        "pagelang-select-lang": "Selecciona un idioma",
+       "pagelang-submit": "Envia",
        "right-pagelang": "Canvia l'idioma de la pàgina",
        "action-pagelang": "canvia l'idioma de la pàgina",
-       "log-name-pagelang": "Canvia el registre de llengua",
+       "log-name-pagelang": "Registre de canvi de llengua",
        "log-description-pagelang": "Aquest és un registre dels canvis en les llengües de les pàgines.",
        "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ha canviat}} la llengua de la pàgina per a $3 de $4 a $5.",
        "default-skin-not-found": "Òndia! L'aparença per defecte per al wiki, definit en <code dir=\"ltr\">$wgDefaultSkin</code> com <code>$1</code>, no està disponible.\n\nLa vostra instal·lació sembla que inclou les següents aparences. Consulteu [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Configuració d'aparences] per a la informació de com habilitar-les i triar-ne el valor per defecte.\n\n$2\n\n; Si heu acabat d'instal·lar MediaWiki:\n: Probablement l'instal·làveu des de git, o directament des del codi font utilitzant algun altre mètode. Això és l'esperat. Intenteu instal·lar algunes aparences des del [https://www.mediawiki.org/wiki/Category:All_skins directori d'aparences de mediawiki.org], per:\n: * Descarregar l'[https://www.mediawiki.org/wiki/Download instal·lador tarball], que ve amb diverses aparences i ampliacions. Podeu copiar i enganxar el directori <code>skins/</code> des d'aquí.\n: * Clonar un dels repositoris <code>mediawiki/skins/*</code> a través de git en el directori <code dir=\"ltr\">skins/</code> de la vostra instal·lació de MediaWiki.\n: Fent això no s'hauria d'interferir amb el vostre dipòsit git si sou un desenvolupador de MediaWiki.\n\n; Si només heu actualitzat MediaWiki:\n: Per MediaWiki 1.24 i posteriors ja no permet aparences instal·lades automàticament (consulteu [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: Aparences autodiscovery]). Podeu enganxar les línies següents en <code>LocalSettings.php</code> per permetre totes les aparences instal·lades actualment:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Si només heu modificat <code>LocalSettings.php</code>:\n: Reviseu els noms de l'aparença per errors tipogràfics.",
        "special-characters-group-ipa": "AFI",
        "special-characters-group-symbols": "Símbols",
        "special-characters-group-greek": "Grec",
+       "special-characters-group-greekextended": "Grec estès",
        "special-characters-group-cyrillic": "Ciríl·lic",
        "special-characters-group-arabic": "Aràbic",
        "special-characters-group-arabicextended": "Aràbic estès",
        "mw-widgets-titleinput-description-new-page": "la pàgina no existeix encara",
        "mw-widgets-titleinput-description-redirect": "redirigeix a $1",
        "api-error-blacklisted": "Trieu un títol diferent, més descriptiu.",
+       "sessionmanager-tie": "No es poden combinar diferents tipus de sol·licituds d'autenticació: $1.",
        "sessionprovider-generic": "$1 sessions",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessions basades en galetes",
-       "sessionprovider-nocookies": "Pot ser que les galetes estiguin inhabilitades. Assegureu-vos que teniu les galetes habilitades i inicieu de nou."
+       "sessionprovider-nocookies": "Pot ser que les galetes estiguin inhabilitades. Assegureu-vos que teniu les galetes habilitades i inicieu de nou.",
+       "randomrootpage": "Pàgina arrel aleatòria",
+       "log-action-filter-block": "Tipus de blocatge:",
+       "log-action-filter-delete": "Tipus de supressió:",
+       "log-action-filter-patrol": "Tipus de patrullatge:",
+       "log-action-filter-protect": "Tipus de protecció:",
+       "log-action-filter-upload": "Tipus de càrrega:",
+       "log-action-filter-protect-protect": "Protecció",
+       "log-action-filter-protect-modify": "Modificació de la protecció",
+       "log-action-filter-protect-unprotect": "Desprotecció",
+       "log-action-filter-upload-upload": "Nova càrrega",
+       "log-action-filter-upload-overwrite": "Torna a carregar"
 }
index 8c4cf3e..cf650ea 100644 (file)
        "tagline": "來源:{{SITENAME}}",
        "help": "幫助",
        "search": "尋討",
-       "searchbutton": "討",
+       "searchbutton": "討",
        "go": "去",
        "searcharticle": "去",
        "history": "頁面歷史",
        "toc": "目錄",
        "showtoc": "顯示",
        "hidetoc": "囥起",
-       "collapsible-collapse": "",
+       "collapsible-collapse": "",
        "collapsible-expand": "現",
        "confirmable-confirm": "汝會確定𣍐?",
        "confirmable-yes": "是",
        "site-atom-feed": "$1原子訂閱",
        "page-rss-feed": "「$1」RSS訂閱",
        "page-atom-feed": "「$1」原子訂閱",
-       "red-link-title": "$1(頁面無敆𡅏)",
+       "red-link-title": "$1(無許頁)",
        "sort-descending": "降序排序",
        "sort-ascending": "升序排序",
        "nstab-main": "頁面",
        "searchrelated": "相關其",
        "searchall": "全部",
        "showingresults": "顯示趁#<b>$2</b>開始其{{PLURAL:$1|'''$1'''萆結果}}。",
+       "search-nonefound": "討毋着",
        "preferences": "設定",
        "mypreferences": "我其設定",
        "prefs-edits": "修改數量:",
        "watchlisttools-view": "看相關改變",
        "watchlisttools-edit": "看共修改監視單",
        "watchlisttools-raw": "修改原始監視單",
-       "specialpages": "特殊頁"
+       "specialpages": "特殊頁",
+       "searchsuggest-search": "討"
 }
index 2dc4b68..4a69007 100644 (file)
@@ -10,7 +10,8 @@
                        "아라",
                        "Kaganer",
                        "Исмаил Садуев",
-                       "Macofe"
+                       "Macofe",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "КӀел сиз хьакха хьажорган:",
        "grant-createaccount": "Декъашхочун дӀаяздарш кхоллар",
        "grant-createeditmovepage": "АгӀонашна хийцам бар",
        "grant-delete": "АгӀонаш а, нисдарш а, декъашхойн дӀаяздар а дӀадахар",
-       "grant-editinterface": "MediaWiki Ñ\86Ó\80еÑ\80ийн Ð°Ð½Ð° Ð°, Ð´Ð¾Ð»Ð°Ñ\80а CSS/JavaScript нисъяр",
+       "grant-editinterface": "MediaWiki Ñ\86Ó\80еÑ\80ийн Ð¼ÐµÑ\82Ñ\82иг Ð°, Ð´Ð¾Ð»Ð°Ñ\80а CSS/JavaScript Ð° нисъяр",
        "grant-editmycssjs": "Долара CSS/JavaScript нисъяр",
        "grant-editmyoptions": "Табе хьай гӀирс",
        "grant-editmywatchlist": "Хьан тергаме могӀам табар",
        "recentchangeslinked-page": "АгӀон цӀе:",
        "recentchangeslinked-to": "Кхечу агӀор, гайта хийцамаш агӀонашца, хӀоттийначу агӀонтӀе хьажорг йолуш",
        "recentchanges-page-added-to-category": "[[:$1]] категори чу тоьхна",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] а, {{PLURAL:$2|цхьа агӀо|$2 агӀо}} а категорин тӀетоьхна",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] а, [[Special:WhatLinksHere/$1|{{PLURAL:$2|цхьа агӀо|$2 агӀо}}]] а категорин тӀетоьхна",
        "recentchanges-page-removed-from-category": "[[:$1]] дӀаяьккхина категори чура",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] а, {{PLURAL:$2|цхьа агӀо|$2 агӀо}} а категорин чура дӀаяьккхина",
        "autochange-username": "MediaWiki авто-хийцамбар",
        "uploaddisabled": "Чуяккхар магийна дац",
        "copyuploaddisabled": "URL тӀера чуяккхар дӀадайина ду.",
        "uploaddisabledtext": "Файлаш чуяхар дӀадайина ду.",
-       "uploadscriptednamespace": "Ð¥Ó\80окÑ\85Ñ\83 SVG-Ñ\84айлан Ñ\86Ó\80еÑ\80ийн Ð°Ð½Ð° нийса яц '$1'",
+       "uploadscriptednamespace": "Ð¥Ó\80окÑ\85Ñ\83 SVG-Ñ\84айлан Ñ\86Ó\80еÑ\80ийн Ð¼ÐµÑ\82Ñ\82иг нийса яц '$1'",
        "upload-source": "ДIайолалун файл",
        "sourcefilename": "ДIайолалун файл:",
        "sourceurl": "Хьостан URL-адрес:",
        "allpagesfrom": "Гучé яха агӀонаш, йолалуш йолу оцу:",
        "allpagesto": "Араяхар сацадé тӀе:",
        "allarticles": "Массо агӀонаш",
-       "allinnamespace": "Массо агӀонаш оцу цӀерийн анахь «$1»",
+       "allinnamespace": "Массо агӀонаш «$1» цӀерийн меттигехь",
        "allpagessubmit": "Кхочушдé",
        "allpagesprefix": "Лаха агӀонаш, дӀайолалуш йолу:",
        "allpagesbadtitle": "Цамагош йолу агӀон цӀе. Коьрта могӀан юкъах ю юкъарвики меттанийн юкъе тӀечӀагӀйина йолу хьаьрк я магийна доцу оцу коьрта моӀанца символаш я кхин.",
-       "allpages-bad-ns": "{{SITENAME}} кху чохь ана цӀерш яц «$1».",
+       "allpages-bad-ns": "{{SITENAME}} кху чохь цӀерийн меттиг яц «$1».",
        "allpages-hide-redirects": "Къайлаяха дӀасахьажийнарш",
        "cachedspecial-viewing-cached-ttl": "Хьо хьоьжу агӀона верси кэш чура ю, иза карлаяьккхина хила мега $1 хьалха.",
        "cachedspecial-refresh-now": "Хьажа тӀехьарчу версега.",
        "listgrouprights-addgroup-all": "массо тобанийн юкъатоха йиш ю",
        "listgrouprights-removegroup-all": "тобан чура дӀабаха ло",
        "listgrouprights-namespaceprotection-header": "ЦӀеран анан бехкам",
-       "listgrouprights-namespaceprotection-namespace": "ЦÓ\80еÑ\80ийн Ð°Ð½Ð°",
+       "listgrouprights-namespaceprotection-namespace": "ЦÓ\80еÑ\80ийн Ð¼ÐµÑ\82Ñ\82иг",
        "listgrouprights-namespaceprotection-restrictedto": "Декъашхочун хийцамаш бан таро хуьлуьйту бакъонаш",
        "listgrants": "Бакъо",
        "listgrants-grant": "Бакъо",
        "protect-title": "Ларъяр: «$1»",
        "protect-title-notallowed": "ГӀораллин бараме хьажар «$1»",
        "prot_1movedto2": "«[[$1]]» цӀе хийцина → «[[$2]]»",
-       "protect-badnamespace-title": "Ð\93Ó\80оÑ\80аладан Ñ\86алÑ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\86Ó\80еÑ\80ийн Ð°Ð½Ð°",
+       "protect-badnamespace-title": "Ð\9bаÑ\80Ñ\8aÑ\8fн Ñ\86алÑ\83Ñ\88 Ð¹Ð¾Ð»Ñ\83 Ñ\86Ó\80еÑ\80ийн Ð¼ÐµÑ\82Ñ\82иг",
        "protect-badnamespace-text": "ХӀокху цӀерийн меттигехь йолу агӀонашна гӀараладан цало.",
        "protect-norestrictiontypes-title": "ГӀараладан цалуш йолу агӀо",
        "protect-legend": "Бакъде агӀо ларъяр",
        "namespace": "ЦӀерийн меттигаш:",
        "invert": "Хаьржинарг къайлаяккха",
        "tooltip-invert": "ХӀоттае хӀара билгало, хаьржинчу цӀерийн анан агӀонийн хийцамаш къайлабаха (кхин дихкина цӀерийн анаш, гайтина елахь)",
-       "namespace_association": "Ð\99иÑ\85кина Ð°Ð½Ð°",
-       "tooltip-namespace_association": "Ð¥Ó\80оÑ\82Ñ\82ае Ñ\85Ó\80аÑ\80а Ð±Ð¸Ð»Ð³Ð°Ð»Ð¾, Ð¸Ñ\88Ñ\82Ñ\82а Ð´Ð¸Ð¹Ñ\86аÑ\80ийн (Ñ\8f ÐºÑ\85ин) Ñ\86Ó\80еÑ\80ийн Ð°Ð½Ð° юкъахь хилийта",
+       "namespace_association": "Ð\99иÑ\85кина Ð¼ÐµÑ\82Ñ\82иг",
+       "tooltip-namespace_association": "Ð¥Ó\80оÑ\82Ñ\82ае Ñ\85Ó\80аÑ\80а Ð±Ð¸Ð»Ð³Ð°Ð»Ð¾, Ð¸Ñ\88Ñ\82Ñ\82а Ð´Ð¸Ð¹Ñ\86аÑ\80ийн (Ñ\8f ÐºÑ\85ин) Ñ\86Ó\80еÑ\80ийн Ð¼ÐµÑ\82Ñ\82иг юкъахь хилийта",
        "blanknamespace": "(Коьрта)",
        "contributions": "{{GENDER:$1|Декъашхочун}} къинхьегам",
        "contributions-title": "{{GENDER:$1|Декъашхочун}} къинхьегам $1",
        "whatlinkshere-page": "АгӀо:",
        "linkshere": "ТӀаьхьайогӀу агӀонаш оцу '''[[:$1]]''': хьажоргца ю",
        "nolinkshere": "ХӀокху '''[[:$1]]''' агӀона тӀе кхечу агӀонашкахь хьажоргаш яц.",
-       "nolinkshere-ns": "ХаÑ\8cÑ\80жинÑ\87Ñ\83 Ð°Ð½Ð°хь яц '''[[:$1]]''' цӀе йолу агӀонаш",
+       "nolinkshere-ns": "ХаÑ\8cÑ\80жинÑ\87Ñ\83 Ð¼ÐµÑ\82Ñ\82игехь яц '''[[:$1]]''' цӀе йолу агӀонаш",
        "isredirect": "агӀо-дӀасахьажорг",
        "istemplate": "юкъаялийнарш",
        "isimage": "Файлан хьажорг",
        "seconds-abbrev": "$1 оцу",
        "minutes-abbrev": "$1 мин",
        "hours-abbrev": "$1 сахь.",
+       "days-abbrev": "$1 д",
        "seconds": "{{PLURAL:$1|$1 секунд|$1 секунд}}",
        "minutes": "{{PLURAL:$1|$1 минот|$1 минот}}",
        "hours": "{{PLURAL:$1|$1 сахьт}}",
        "tags-hitcount-header": "Билгалдина нисдарш",
        "tags-actions-header": "Дийраш",
        "tags-active-yes": "ХӀаъ",
-       "tags-active-no": "ХӀахӀа",
+       "tags-active-no": "ХӀан-хӀа",
        "tags-source-extension": "Билгалйо шоралица",
        "tags-source-none": "Кхий лелош яц",
        "tags-edit": "нисъе",
index 928a791..b549436 100644 (file)
@@ -17,7 +17,8 @@
                        "Ebraminio",
                        "Macofe",
                        "Pirehelokan",
-                       "Diyariq"
+                       "Diyariq",
+                       "Sarchia"
                ]
        },
        "tog-underline": "ھێڵ ھێنان بەژێر بەستەرەکان:",
        "october-date": "$1ی تشرینی یەکەم",
        "november-date": "$1ی تشرینی دووەم",
        "december-date": "$1ی کانوونی یەکەم",
+       "period-am": "پێش نیوەڕۆ",
+       "period-pm": "پاش نیوەڕۆ",
        "pagecategories": "{{PLURAL:$1|پۆل|پۆلەکان}}",
        "category_header": "پەڕەکانی پۆلی «$1»",
        "subcategories": "ژێرپۆلەکان",
        "morenotlisted": "ئەم لیستەیە تەواو نییە",
        "mypage": "پەڕە",
        "mytalk": "لێدوان",
-       "anontalk": "لێدوان بۆ ئەم ئایپییە",
+       "anontalk": "لێدوان",
        "navigation": "ڕێدۆزی",
        "and": "&#32;و",
        "qbfind": "بدۆزەرەوە",
        "createacct-reason": "ھۆکار",
        "createacct-reason-ph": "بۆ ھەژمارێکی تر دروست دەکەی",
        "createacct-submit": "ھەژمارەکەت دروست بکە",
-       "createacct-another-submit": "ھەژمارێکی تر دروست بکە",
+       "createacct-another-submit": "ھەژمار دروست بکە",
        "createacct-benefit-heading": "{{SITENAME}} لە لایەن کەسانێک وەکوو خۆت دروست کراوە.",
        "createacct-benefit-body1": "{{PLURAL:$1|دەستکاری}}",
        "createacct-benefit-body2": "{{PLURAL:$1|پەڕە}}",
        "nocookieslogin": "{{SITENAME}} بۆ چوونەژوورەوە لە کووکی‌یەکان کەڵک وەرئەگرێت.\nڕێگەت نەداوە بە کووکی‌یەکان.\nڕێگەیان پێ بدەو و دیسان تێبکۆشە.",
        "nocookiesfornew": "ھەژماری بەکارھێنەری دروست نەکرا، چون ناتوانین سەرچاوەکەی پشتڕاست بکەینەوە.\nدڵنیا بە کوکییەکانت چالاک کردووە، پەڕەکە بار بکەوە و دیسان ھەوڵ بدە.",
        "noname": "ناوی بەکارهێنەرییەکی گۆنجاوت دیاری نەکردووه.",
-       "loginsuccesstitle": "سەرکەوتی بۆ چوونە ژوورەوە",
+       "loginsuccesstitle": "چوویە ناوەوە",
        "loginsuccess": "'''ئێستا بە ناوی «$1»ەوە لە {{SITENAME}} چوویتەتەژوورەوە.'''",
        "nosuchuser": "بەکارھێنەرێک بە ناوی «$1» نیە.\nناوی بەکارھێنەر بە گەورە و بچووک بوونی پیتەکان ھەستیارە.\nڕێنووسەکەت چاولێکەرەوە، یان [[Special:UserLogin/signup|ھەژمارێکی نوێ دروست بکە]].",
        "nosuchusershort": "بەکارھێنەرێک بە ناوی «$1»ەوە نیە.\nبە نووسراوەکەتدا بچۆرەوە.",
        "retypenew": "تێپەڕوشەی نوێ دوبارە بنووسەوە:",
        "resetpass_submit": "تێپەڕوشە رێکخە و بچۆ ژوورەوە",
        "changepassword-success": "تێپەروشەکەت بە سەرکەوتوویی گۆڕدرا!",
+       "botpasswords-label-create": "دروستکردن",
+       "botpasswords-label-update": "نوێکردنەوە",
+       "botpasswords-label-cancel": "ھەڵوەشاندنەوە",
+       "botpasswords-label-delete": "سڕینەوە",
+       "botpasswords-label-resetpassword": "ڕێکخستنەوەی تێپەڕوشە",
        "resetpass_forbidden": "تێپەڕوشەکە ناگۆڕدرێت",
        "resetpass-no-info": "بۆ گەیشتنی راستەوخۆ بەم پەڕە ئەشێ بچیتە ژوورەوە.",
        "resetpass-submit-loggedin": "تێپەڕوشە بگۆڕە",
        "rcshowhidemine": "دەستکارییەکانم $1",
        "rcshowhidemine-show": "نیشان بدە",
        "rcshowhidemine-hide": "بشارەوە",
+       "rcshowhidecategorization": "$1 پۆلێنکردنی پەڕە",
        "rcshowhidecategorization-show": "نیشانی بدە",
        "rclinks": "دوایین $1 گۆڕانکاریی $2 ڕۆژی ڕابردوو نیشان بدە<br />$3",
        "diff": "جیاوازی",
        "unwatchthispage": "ئیتر چاودێری مەکە",
        "notanarticle": "پەڕەی بێ ناوەڕۆک",
        "notvisiblerev": "پیاچوونەوە سڕاوەتەوە",
-       "watchlist-details": "{{PLURAL:$1|$1 پەڕە|$1 پەڕە}} لە لیستی چاودێریەکەتدایە، بێجگە پەڕەکانی لێدوان.",
+       "watchlist-details": "بێجگە لە پەڕەکانی لێدوان، {{PLURAL:$1|$1 پەڕە}} لە پێرستی {{PLURAL:$1|چاودێرییەکەتدایە|چاودێرییەکەتدان}}.",
        "wlheader-enotif": "ئاگاداری بە ئیمەیل چالاکە.",
        "wlheader-showupdated": "‏ئەو پەڕانە کە لە پاش دوایین سەردانت دەستکاری کراون بە <strong>ئەستوور</strong> نیشان دراون.",
        "wlnote": "خوارەوە {{PLURAL:$1|دوایین گۆڕانکارییە|دوایین <strong>$1</strong> گۆڕانکارییە}} لە دوایین {{PLURAL:$2|کاتژمێر|<strong>$2</strong> کاتژمێر}}دا ھەتا $4ی $3.",
        "pageinfo-contentpage-yes": "بەڵێ",
        "pageinfo-protect-cascading-yes": "بەڵێ",
        "pageinfo-category-info": "زانیاریی پۆل",
+       "pageinfo-category-total": "ژمارەی سەرجەمی ئەندامان",
        "pageinfo-category-pages": "ژمارەی پەڕەکان",
        "pageinfo-category-subcats": "ژمارەی ژێرپەڕەکان",
        "pageinfo-category-files": "ژمارەی پەڕگەکان",
        "version-libraries-description": "وەسف",
        "version-libraries-authors": "نووسەر",
        "redirect": "ڕەوانەکەر بە پێی پەڕگە، بەکارھێنەر، پەڕە، پێداچوونەوە یان پێناسەی لۆگ",
-       "redirect-legend": "ڕەوانەکەر بۆ پەڕگە یان پەڕەیەک",
        "redirect-summary": "ئەم پەڕە تایبەتە ڕەوانە دەکرێ بۆ پەڕگەیەک (ناوی پەڕگەکە)، پەڕەیەک (پێناسەی پێداچوونەوەیەک یان پێناسەی پەڕە) یان پەڕەیەکی بەکارھێنەر (پێناسەیەکی  ژمارەیی بەکارھێنەر). بەکارھێنان: [[{{#Special:Redirect}}/file/Example.jpg]]، [[{{#Special:Redirect}}/page/64308]]، [[{{#Special:Redirect}}/revision/328429]] یان [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "بڕۆ",
        "redirect-lookup": "گەڕان لە:",
index 1bac2e1..089bfc3 100644 (file)
        "nov": "ноя",
        "dec": "дек",
        "pagecategories": "{{PLURAL:$1|1=Саифенинъ категориясы|Саифенинъ категориялары}}",
-       "category_header": "\"$1\" категориясындаки саифелер",
+       "category_header": "«$1» категориясындаки саифелер",
        "subcategories": "Алт категориялар",
-       "category-media-header": "\"$1\" категориясындаки медиа файллары",
+       "category-media-header": "«$1» категориясындаки медиа файллары",
        "category-empty": "''Ишбу категорияда ич бир саифе я да медиа файл ёкъ.''",
        "hidden-categories": "Гизли {{PLURAL:$1|1=категория|категориялар}}",
        "hidden-category-category": "Гизли категориялар",
        "perfcachedts": "Ашагъыдаки малюмат кэштен алынды, кэшнинъ сонъки янъартылгъан вакъты: $1. Кэште энъ чокъ {{PLURAL:$1|1=бир нетидже|$1 нетидже}} сакъланып тура.",
        "querypage-no-updates": "Бу саифени денъиштирмеге шимди изин ёкъ. Бу малюмат аман янъартылмайджакъ.",
        "viewsource": "Менба кодуны косьтер",
-       "viewsource-title": "$1 саифесининъ менба коду",
+       "viewsource-title": "«$1» саифесининъ менба коду",
        "actionthrottled": "Арекет токъталды",
        "actionthrottledtext": "Спамгъа къаршы куреш себебинден бу арекетни аз вакъыт ичинде чокъ кере текрарлап оламайсынъыз. Мумкюн олгъан къарардан зияде арекет яптынъыз. Бир къач дакъкъадан сонъ текрарлап бакъынъыз.",
        "protectedpagetext": "Бу саифеде денъиштирме я да башкъа бир арекет япылмасын деп о блок этильди.",
        "updated": "(Янъарды)",
        "note": "'''Ихтар:'''",
        "previewnote": "'''Бу тек бакъып чыкъув, метин аля даа сакъланмагъан!'''",
+       "continue-editing": "Денъиштирюв пенджересине къайт",
        "previewconflict": "Бу бакъып чыкъув юкъары тарир пенджересиндеки метиннинъ сакъланувдан сонъ оладжакъ корюнишини акс эте.",
        "session_fail_preview": "''' Сервер сиз япкъан денъиштирмелерни сессия идентификаторы джоюлгъаны себебинден сакълап оламады.\nБу вакътынджа проблемадыр. Лютфен, текрар сакълап бакъынъыз.\nБундан да сонъ олып чыкъмаса, малюмат локаль файлгъа сакъланъыз да браузеринъизни бир къапатып ачынъыз.'''",
        "session_fail_preview_html": "'''Афу этинъиз! HTML сессиянынъ малюматлары гъайып олгъаны себебинден сизинъ денъиштирмелеринъизни къабул этмеге имкян ёкътыр.'''",
        "editing": "«$1» саифесини денъиштиреятасыз",
        "creating": "«$1» саифесини яратув",
        "editingsection": "«$1» саифесинде болюк денъиштиреятасыз",
-       "editingcomment": "$1 саифесини денъиштиреятасыз (янъы болюк)",
+       "editingcomment": "«$1» саифесини денъиштиреятасыз (янъы болюк)",
        "editconflict": "Денъиштирмелер чатышмасы: $1",
        "explainconflict": "Сиз саифени денъиштиргенде башкъа бири де денъиштирме япты.\nЮкъарыдаки язы саифенинъ шимдики алыны косьтере.\nСизинъ денъиштирмелеринъиз астында косьтерильди.\nШимди япкъан денъиштирмелеринъизни ашагъы пенджереден юкъары пенджереге авуштырмакъ керексинъиз.\n\"{{int:savearticle}}\"гъа баскъанда '''тек''' юкъарыдаки язы сакъланаджакъ.",
        "yourtext": "Сизинъ метнинъиз",
        "randompage": "Тесадюфий саифе",
        "randompage-nopages": "\"$1\" {{PLURAL:$2|1=исим фезасында|исим фезаларында}} ич бир саифе ёкъ.",
        "randomredirect": "Тесадюфий ёллама саифеси",
-       "randomredirect-nopages": "\"$1\" исим фезасында ич бир ёллама саифеси ёкъ.",
+       "randomredirect-nopages": "«$1» исим фезасында ич бир ёллама саифеси ёкъ.",
        "statistics": "Статистика",
        "statistics-header-pages": "Саифе статистикасы",
        "statistics-header-edits": "Денъиштирюв статистикасы",
        "protectlogtext": "Ашагъыдаки, къорчалавгъа алув/къорчалавдан чыкъарув иле багълы денъишмелер журналыдыр.\nКъорчалангъан саифелер [[Special:ProtectedPages|там джедвелини]] де коре билесинъиз.",
        "protectedarticle": "\"[[$1]]\" къорчалав алтына алынды",
        "modifiedarticleprotection": "«[[$1]]» ичюн къорчалав севиеси денъиштирильди",
-       "unprotectedarticle": "\"[[$1]]\" саифесинден къорчалав чыкъарлыды",
+       "unprotectedarticle": "«[[$1]]» саифесинден къорчалав чыкъарлыды",
        "prot_1movedto2": "[[$1]] саифесининъ ады [[$2]] деп денъиштирильди",
        "protect-legend": "Къорчалавны тасдыкъла",
        "protectcomment": "Себеп:",
        "sp-contributions-newonly": "Тек янъы саифе яраткъан денъиштирмелерни косьтер",
        "sp-contributions-submit": "Къыдыр",
        "whatlinkshere": "Бу саифеге багълантылар",
-       "whatlinkshere-title": "$1 саифесине багъланты олгъан саифелер",
+       "whatlinkshere-title": "«$1» саифесине багъланты олгъан саифелер",
        "whatlinkshere-page": "Саифе:",
        "linkshere": "'''[[:$1]]''' саифесине багъланты берген саифелер:",
        "nolinkshere": "'''[[:$1]]''' саифесине багъланты берген саифе ёкъ.",
        "ip_range_invalid": "Рухсетсиз IP аралыгъы.",
        "lockdb": "Малюмат базасы килитли",
        "lockbtn": "Малюмат базасы килитли",
-       "move-page": "$1 саифесининъ адыны денъиштиреятасыз",
+       "move-page": "«$1» саифесининъ адыны денъиштиреятасыз",
        "move-page-legend": "Саифенинъ адыны денъиштирюв",
        "movepagetext": "Ашагъыдаки форма къулланылып саифенинъ ады денъиштирилир. Бунынънен берабер денъиштирмелер журналы да янъы адгъа авуштырылыр.\nЭски ады янъы адына ёнетме олур. Эски серлевагъа ёнетип тургъан саифелерни автоматик оларакъ янъартып оласынъыз. Бу арекетни автоматик япмагъа истемесенъиз, бутюн [[Special:DoubleRedirects|чифт]] ве [[Special:BrokenRedirects|йыртыкъ]] ёнетме саифелерини озюнъиз тешкермеге меджбур олурсынъыз. Багълантылар эндиден берли догъру чалышмасындан эмин олмалысынъыз.\n\nЯнъы адда бир саифе энди бар олса, ад денъиштирилюви <strong>япылмайджакъ</strong>, анджакъ бар олгъан саифе ёнетме я да бош олса ад денъиштирилюви мумкюн оладжакъ. Бу демек ки, саифенинъ адыны янълыштан денъиштирген олсанъыз деминки адыны кери къайтарып оласынъыз, амма бар олгъан саифени тесадюфен ёкъ этамайсынъыз.\n\n<strong>ТЕНБИ!</strong>\nАд денъиштирилюви популяр саифелер ичюн буюк ве бекленмеген денъишмелерге себеп ола билир. Лютфен, денъиштирме япмаздан эвель ола биледжеклерни козь огюне алынъыз.",
        "movepagetalktext": "Къошулгъан музакере саифесининъ де (бар олса)\nады автоматик тарзда денъиштириледжек. '''Мустесналар:'''\n\n* Айны бу адда бош олмагъан бир музакере саифеси энди бар;\n* Ашагъыдаки бошлукъкъа ишарет къоймадынъыз.\n\nБойле алларда, керек олса, саифелерни къолнен ташымагъа я да бирлештирмеге меджбур олурсынъыз.",
index 9333f95..ffdd83c 100644 (file)
        "nov": "noy",
        "dec": "dek",
        "pagecategories": "{{PLURAL:$1|Saifeniñ kategoriyası|Saifeniñ kategoriyaları}}",
-       "category_header": "\"$1\" kategoriyasındaki saifeler",
+       "category_header": "“$1” kategoriyasındaki saifeler",
        "subcategories": "Alt kategoriyalar",
-       "category-media-header": "\"$1\" kategoriyasındaki media faylları",
+       "category-media-header": "“$1” kategoriyasındaki media faylları",
        "category-empty": "''İşbu kategoriyada iç bir saife ya da media fayl yoq.''",
        "hidden-categories": "Gizli {{PLURAL:$1|kategoriya|kategoriyalar}}",
        "hidden-category-category": "Gizli kategoriyalar",
        "formerror": "Hata: formanıñ malümatını yollamaqnıñ iç çaresi yoq",
        "badarticleerror": "Siz yapmağa istegen işlev bu saifede yapılıp olamay.",
        "cannotdelete": "\"$1\" saife ya da faylı yoq etilip olamadı. Başqa bir qullanıcı tarafından yoq etilgen ola bile.",
-       "cannotdelete-title": "\"$1\" saifesini yoq etmege olmaz",
+       "cannotdelete-title": "“$1” saifesini yoq etmege olmaz",
        "delete-hook-aborted": "Yoq etüv çengel protsedurasınen toqtatıldı.\nİç bir izaat berilmedi.",
        "badtitle": "Ruhsetsiz serleva",
        "badtitletext": "İstenilgen saife adı doğru degil, o boştır, yahut tillerara bağlantı ya da vikilerara bağlantı doğru yazılmağan. Belki saife adında yasaqlanğan işaretler bar.",
        "perfcachedts": "Aşağıdaki malümat keşten alındı, keşniñ soñki yañartılğan vaqtı: $1. Keşte eñ çoq {{PLURAL:$1|bir netice|$1 netice}} saqlanıp tura.",
        "querypage-no-updates": "Bu saifeni deñiştirmege şimdi izin yoq. Bu malümat aman yañartılmaycaq.",
        "viewsource": "Menba kodunı köster",
-       "viewsource-title": "$1 saifesiniñ menba kodu",
+       "viewsource-title": "“$1” saifesiniñ menba kodu",
        "actionthrottled": "Areket toqtaldı",
        "actionthrottledtext": "Spamğa qarşı küreş sebebinden bu areketni az vaqıt içinde çoq kere tekrarlap olamaysıñız. Mümkün olğan qarardan ziyade areket yaptıñız. Bir qaç daqqadan soñ tekrarlap baqıñız.",
        "protectedpagetext": "Bu saifede deñiştirme ya da başqa bir areket yapılmasın dep o blok etildi.",
        "updated": "(Yañardı)",
        "note": "'''İhtar:'''",
        "previewnote": "'''Bu tek baqıp çıquv, metin alâ daa saqlanmağan!'''",
+       "continue-editing": "Deñiştirüv penceresine qayt",
        "previewconflict": "Bu baqıp çıquv yuqarı tarir penceresindeki metinniñ saqlanuvdan soñ olacaq körünişini aks ete.",
        "session_fail_preview": "''' Server siz yapqan deñiştirmelerni sessiya identifikatorı\ncoyulğanı sebebinden saqlap olamadı. Bu vaqtınca problemadır. Lütfen, tekrar saqlap baqıñız.\nBundan da soñ olıp çıqmasa, malümat lokal faylğa saqlañız da brauzeriñizni bir qapatıp\naçıñız.'''",
        "session_fail_preview_html": "'''Afu etiñiz! HTML sessiyanıñ malümatları ğayıp olğanı sebebinden siziñ deñiştirmeleriñizni qabul etmege imkân yoqtır.'''",
        "editing": "“$1” saifesini deñiştireyatasız",
        "creating": "“$1” saifesini yaratuv",
        "editingsection": "“$1” saifesinde bölük deñiştireyatasız",
-       "editingcomment": "$1 saifesini deñiştireyatasız (yañı bölük)",
+       "editingcomment": "“$1” saifesini deñiştireyatasız (yañı bölük)",
        "editconflict": "Deñiştirmeler çatışması: $1",
        "explainconflict": "Siz saifeni deñiştirgende başqa biri de deñiştirme yaptı.\nYuqarıdaki yazı saifeniñ şimdiki alını köstere.\nSiziñ deñiştirmeleriñiz astında kösterildi. Şimdi yapqan deñiştirmeleriñizni aşağı pencereden yuqarı pencerege avuştırmaq kereksiñiz.\n\"{{int:savearticle}}\"ğa basqanda '''tek''' yuqarıdaki yazı saqlanacaq.",
        "yourtext": "Siziñ metniñiz",
        "randompage": "Tesadüfiy saife",
        "randompage-nopages": "\"$1\" {{PLURAL:$2|isim fezasında|isim fezalarında}} iç bir saife yoq.",
        "randomredirect": "Tesadüfiy yollama saifesi",
-       "randomredirect-nopages": "\"$1\" isim fezasında iç bir yollama saifesi yoq.",
+       "randomredirect-nopages": "“$1” isim fezasında iç bir yollama saifesi yoq.",
        "statistics": "Statistika",
        "statistics-header-pages": "Saife statistikası",
        "statistics-header-edits": "Deñiştirüv statistikası",
        "protectlogpage": "Qorçalav jurnalı",
        "protectlogtext": "Aşağıdaki, saifeni qorçalavğa aluv/qorçalavdan çıqaruv ile bağlı deñişmeler jurnalıdır.\nQorçalanğan saifeler [[Special:ProtectedPages|tam cedvelini]] de köre bilesiñiz.",
        "protectedarticle": "\"[[$1]]\" qorçalav altına alındı",
-       "modifiedarticleprotection": "\"[[$1]]\" içün qorçalav seviyesi deñiştirildi",
-       "unprotectedarticle": "\"[[$1]]\" saifesinden qorçalav çıqarlıdı",
+       "modifiedarticleprotection": "“[[$1]]” içün qorçalav seviyesi deñiştirildi",
+       "unprotectedarticle": "“[[$1]]” saifesinden qorçalav çıqarlıdı",
        "prot_1movedto2": "[[$1]] saifesiniñ adı [[$2]] dep deñiştirildi",
        "protect-legend": "Qorçalavnı tasdıqla",
        "protectcomment": "Sebep:",
        "sp-contributions-newonly": "Tek yañı saife yaratqan deñiştirmelerni köster",
        "sp-contributions-submit": "Qıdır",
        "whatlinkshere": "Bu saifege bağlantılar",
-       "whatlinkshere-title": "$1 saifesine bağlantı bergen saifeler",
+       "whatlinkshere-title": "“$1” saifesine bağlantı bergen saifeler",
        "whatlinkshere-page": "Saife:",
        "linkshere": "'''[[:$1]]''' saifesine bağlantı bergen saifeler:",
        "nolinkshere": "'''[[:$1]]''' saifesine bağlantı bergen saife yoq.",
        "ip_range_invalid": "Ruhsetsiz IP aralığı.",
        "lockdb": "Malümat bazası kilitli",
        "lockbtn": "Malümat bazası kilitli",
-       "move-page": "$1 saifesiniñ adını deñiştireyatasız",
+       "move-page": "“$1” saifesiniñ adını deñiştireyatasız",
        "move-page-legend": "Saifeniñ adını deñiştirüv",
        "movepagetext": "Aşağıdaki forma qullanılıp saifeniñ adı deñiştirilir. Bunıñnen beraber deñiştirmeler jurnalı da yañı adğa avuştırılır.\nEski adı yañı adına yönetme olur. Eski serlevağa yönetip turğan saifelerni avtomatik olaraq yañartıp olasıñız. Bu areketni avtomatik yapmağa istemeseñiz, bütün [[Special:DoubleRedirects|çift]] ve [[Special:BrokenRedirects|yırtıq]] yönetme saifelerini özüñiz teşkermege mecbur olursıñız. Bağlantılar endiden berli doğru çalışmasından emin olmalısıñız.\n\nYañı adda bir saife endi bar olsa, ad deñiştirilüvi <strong>yapılmaycaq</strong>, ancaq bar olğan saife yönetme ya da boş olsa ad deñiştirilüvi mümkün olacaq. Bu demek ki, saifeniñ adını yañlıştan deñiştirgen olsañız deminki adını keri qaytarıp olasıñız, amma bar olğan saifeni tesadüfen yoq etamaysıñız.\n\n<strong>TENBİ!</strong>\nAd deñiştirilüvi populâr saifeler içün büyük ve beklenmegen deñişmelerge sebep ola bilir. Lütfen, deñiştirme yapmazdan evel ola bileceklerni köz ögüne alıñız.",
        "movepagetalktext": "Qoşulğan muzakere saifesiniñ de (bar olsa) adı avtomatik tarzda deñiştirilecek. '''Müstesnalar:'''\n\n*Aynı bu isimde boş olmağan bir muzakere saifesi endi bar;\n*Aşağıdaki boşluqqa işaret qoymadıñız.\n\nBöyle allarda, kerek olsa, saifelerni qolnen taşımağa ya da birleştirmege mecbur olursıñız.",
        "move-watch": "Bu saifeni közet",
        "movepagebtn": "Adını deñiştir",
        "pagemovedsub": "Saifeniñ adı deñiştirildi",
-       "movepage-moved": "'''\"$1\" saifesiniñ adı \"$2\" olaraq deñiştirildi'''",
+       "movepage-moved": "'''“$1” saifesiniñ adı “$2” olaraq deñiştirildi'''",
        "movepage-moved-redirect": "Bir yollama yaratıldı.",
        "movepage-moved-noredirect": "Yollama yaratıluvı bastırıldı.",
        "articleexists": "Bu adda bir saife endi bar ya da siz yazğan ad yasaqlı.\nLütfen, başqa bir ad saylap yazıñız.",
index 220ad5a..5ff68d3 100644 (file)
@@ -64,7 +64,7 @@
        "tog-watchlisthidebots": "Na seznamu sledovaných stránek skrýt editace botů",
        "tog-watchlisthideminor": "Na seznamu sledovaných stránek skrýt malé editace",
        "tog-watchlisthideliu": "Na seznamu sledovaných stránek skrýt editace přihlášených uživatelů",
-       "tog-watchlistreloadautomatically": "Při změně nastavení automaticky aktualizovat seznam sledovaných stránek (vyžaduje JavaScript)",
+       "tog-watchlistreloadautomatically": "Při změně filtru automaticky aktualizovat seznam sledovaných stránek (vyžaduje JavaScript)",
        "tog-watchlisthideanons": "Na seznamu sledovaných stránek skrýt editace nepřihlášených uživatelů",
        "tog-watchlisthidepatrolled": "Skrýt prověřené editace ve sledovaných stránkách",
        "tog-watchlisthidecategorization": "Skrýt kategorizaci stránek",
        "directoryreadonlyerror": "Adresář „$1“ je pouze pro čtení.",
        "directorynotreadableerror": "Adresář „$1“ nelze číst.",
        "filenotfound": "Nebylo možné najít soubor „$1“.",
-       "unexpected": "Neočekávaná hodnota: \"$1\"=\"$2\".",
+       "unexpected": "Neočekávaná hodnota: „$1“=„$2“.",
        "formerror": "Chyba: nebylo možné odeslat formulář",
        "badarticleerror": "Tuto činnost nelze na této stránce provést.",
        "cannotdelete": "Nebylo možné smazat stránku nebo soubor „$1“.\nMožná už byl(a) smazán(a) někým jiným.",
        "title-invalid-empty": "Požadovaný název stránky je prázdný nebo obsahuje pouze název jmenného prostoru.",
        "title-invalid-utf8": "Požadovaný název stránky obsahuje neplatnou sekvenci UTF-8.",
        "title-invalid-interwiki": "Požadovaný název stránky obsahuje interwiki odkaz, který nelze v názvech používat.",
-       "title-invalid-talk-namespace": "Požadovaný název stránky odkazuje na diskusní stránku, která neexistuje.",
+       "title-invalid-talk-namespace": "Požadovaný název stránky odkazuje na diskusní stránku, která nemůže existovat.",
        "title-invalid-characters": "Požadovaný název stránky obsahuje neplatné znaky: „$1“.",
        "title-invalid-relative": "Název obsahuje relativní cestu. Relativní názvy stránek (./, ../) jsou neplatné, protože často budou nedostupné, když je zpracuje prohlížeč uživatele.",
        "title-invalid-magic-tilde": "Požadovaný název stránky obsahuje neplatnou magickou posloupnost vlnovek (<nowiki>~~~</nowiki>).",
        "title-invalid-too-long": "Požadovaný název stránky je příliš dlouhý. V kódování UTF-8 nesmí být delší než $1 {{PLURAL:$1|bajt|bajty|bajtů}}.",
-       "title-invalid-leading-colon": "Požadovaný název stránku na začátku obsahuje neplatnou dvojtečku.",
+       "title-invalid-leading-colon": "Požadovaný název stránky na začátku obsahuje neplatnou dvojtečku.",
        "perfcached": "Následující data jsou z cache a nemusí být plně aktuální. Cache může obsahovat maximálně {{PLURAL:$1|jeden výsledek|$1 výsledky|$1 výsledků}}.",
        "perfcachedts": "Následující data jsou z cache, která byla naposledy aktualizována $1. Cache může obsahovat maximálně {{PLURAL:$4|jeden výsledek|$4 výsledky|$4 výsledků}}.",
        "querypage-no-updates": "Aktualizace této stránky je vypnuta. Data nyní nebudou obnovována.",
        "editinginterface": "<strong>Upozornění:</strong> Editujete stránku, která definuje texty rozhraní.\nZměny této stránky ovlivní vzhled uživatelského rozhraní všem uživatelům této wiki.",
        "translateinterface": "Pro přidávání a změny překladů pro všechny wiki použijte [//translatewiki.net/ translatewiki.net], projekt pro lokalizaci MediaWiki.",
        "cascadeprotected": "Tato stránka je zamčena, neboť je vložena na {{PLURAL:$1|následující stránku, zamčenou|následující stránky, zamčené}} kaskádovým zámkem:\n$2",
-       "namespaceprotected": "Nemáte povoleno editovat stránky ve jmenném prostoru '''$1'''.",
+       "namespaceprotected": "Nemáte povoleno editovat stránky ve jmenném prostoru <strong>$1</strong>.",
        "customcssprotected": "Nemáte povoleno editovat tuto stránku s CSS, protože obsahuje osobní nastavení jiného uživatele.",
        "customjsprotected": "Nemáte povoleno editovat tuto stránku s JavaScriptem, protože obsahuje osobní nastavení jiného uživatele.",
        "mycustomcssprotected": "Nemáte oprávnění editovat tuto stránku s CSS.",
        "nosuchuser": "Neexistuje uživatel se jménem „$1“. U uživatelských jmen se rozlišují malá/velká písmena. Zkontrolujte zápis, nebo si [[Special:UserLogin/signup|vytvořte nový účet]].",
        "nosuchusershort": "Neexistuje uživatel se jménem „$1“. Zkontrolujte zápis.",
        "nouserspecified": "Musíte zadat uživatelské jméno.",
-       "login-userblocked": "Tento uživatel je zablokován. Přihlášení není dovoleno.",
+       "login-userblocked": "{{GENDER:$1|Tento uživatel je zablokován|Tato uživatelka je zablokována}}. Přihlášení není dovoleno.",
        "wrongpassword": "Bylo zadáno nesprávné heslo.\nZkuste to znovu.",
        "wrongpasswordempty": "Bylo zadáno prázdné heslo. Zkuste to znovu.",
        "passwordtooshort": "Heslo musí být dlouhé nejméně $1 {{PLURAL:$1|znak|znaky|znaků}}.",
        "noemail": "{{GENDER:$1|Uživatel|Uživatelka}} „$1“ nemá zaregistrovanou e-mailovou adresu.",
        "noemailcreate": "Musíte uvést platnou e-mailovou adresu",
        "passwordsent": "Dočasné heslo bylo zasláno na e-mailovou adresu registrovanou pro „$1“. Přihlaste se, prosím, znovu, jakmile ho obdržíte.",
-       "blocked-mailpassword": "Vaší IP adrese byla zablokována možnost editace, a současně s tím je zablokována funkce pro zaslání nového hesla.",
+       "blocked-mailpassword": "Vaší IP adrese byla zablokována možnost editace. Kvůli ochraně před zneužitím není dovoleno z této IP adresy žádat o zaslání nového hesla.",
        "eauthentsent": "Na zadanou adresu byl zaslán potvrzovací e-mail.\nŽádné další zprávy vám však na tuto adresu nebudou odeslány, dokud podle instrukcí v e-mailu nepotvrdíte, že tato adresa skutečně patří vám.",
        "throttled-mailpassword": "Během {{PLURAL:$1|poslední hodiny|posledních $1 hodin}} již bylo heslo jednou zasláno.\nKvů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",
        "botpasswords-insert-failed": "Nepodařilo se přidat název bota „$1“. Nebyl už přidán?",
        "botpasswords-update-failed": "Nepodařilo se aktualizovat název bota „$1“. Nebyl smazán?",
        "botpasswords-created-title": "Heslo pro bota vytvořeno",
-       "botpasswords-created-body": "Heslo pro bota „$1“ bylo vytvořeno.",
+       "botpasswords-created-body": "Heslo pro bota jménem „$1“ {{GENDER:$2|uživatele|uživatelky}} „$2“ bylo vytvořeno.",
        "botpasswords-updated-title": "Heslo pro bota aktualizováno",
-       "botpasswords-updated-body": "Heslo pro bota „$1“ bylo aktualizováno.",
+       "botpasswords-updated-body": "Heslo pro bota jménem „$1“ {{GENDER:$2|uživatele|uživatelky}} „$2“ bylo aktualizováno.",
        "botpasswords-deleted-title": "Heslo pro bota smazáno",
-       "botpasswords-deleted-body": "Heslo pro bota „$1“ bylo smazáno.",
+       "botpasswords-deleted-body": "Heslo pro bota jménem „$1“ {{GENDER:$2|uživatele|uživatelky}} „$2“ bylo smazáno.",
        "botpasswords-newpassword": "Nové přihlašovací heslo pro bota <strong>$1</strong> je <strong>$2</strong>. <em>Zaznamenejte si je pro budoucí použití.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider není dostupný.",
        "botpasswords-restriction-failed": "Toto přihlášení bylo zamítnuto omezením hesel pro boty.",
        "missing-revision": "Revize #$1 stránky s názvem „{{FULLPAGENAME}}“ neexistuje.\n\nToto je obvykle způsobeno tím, že jste následovali zastaralý odkaz na historickou verzi stránky, jež byla smazána.\nPodrobnosti mohou být uvedeny v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} knize smazaných stránek].",
        "userpage-userdoesnotexist": "Uživatelský účet „$1“ není zaregistrován.\nZkontrolujte, zda skutečně chcete tuto stránku vytvořit či editovat.",
        "userpage-userdoesnotexist-view": "Uživatelský účet „$1“ není zaregistrován.",
-       "blocked-notice-logextract": "Tento uživatel je momentálně zablokován.\nZde je pro přehled zobrazen nejnovější záznam z knihy zablokování:",
+       "blocked-notice-logextract": "{{GENDER:$1|Tento uživatel|Tato uživatelka}} je momentálně {{GENDER:$1|zablokován|zablokována}}.\nZde je pro přehled zobrazen nejnovější záznam z knihy zablokování:",
        "clearyourcache": "<strong>Poznámka:</strong> Po uložení musíte smazat cache vašeho prohlížeče, jinak změny neuvidíte.\n* <strong>Firefox / Safari:</strong> Při kliknutí na <em>Aktualizovat</em> držte <em>Shift</em> nebo stiskněte <em>Ctrl-F5</em> nebo <em>Ctrl-R</em> (na Macu <em>⌘-R</em>)\n* <strong>Google Chrome:</strong> Stiskněte <em>Ctrl-Shift-R</em> (na Macu <em>⌘-Shift-R</em>)\n* <strong>Internet Explorer:</strong> Při kliknutí na <em>Aktualizovat</em> držte <em>Ctrl</em> nebo stiskněte <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Smažte obsah cache v menu <em>Nástroje → Nastavení</em>",
        "usercssyoucanpreview": "<strong>Tip:</strong> Použijte tlačítko „{{int:showpreview}}“ k testování vašeho nového CSS před uložením.",
        "userjsyoucanpreview": "<strong>Tip:</strong> Použijte tlačítko „{{int:showpreview}}“ k testování vašeho nového JavaScriptu před uložením.",
        "undo-summary": "Zrušena verze $1 od uživatele [[Special:Contributions/$2|$2]] ([[User talk:$2|diskuse]])",
        "undo-summary-username-hidden": "Zrušena verze $1 od skrytého uživatele",
        "cantcreateaccounttitle": "Nelze vytvořit uživatelský účet",
-       "cantcreateaccount-text": "Zakládání nových účtů z této IP adresy ('''$1''') bylo zablokováno uživatelem [[User:$3|$3]].\n\n$3 uvádí toto zdůvodnění: ''$2''",
+       "cantcreateaccount-text": "Zakládání nových účtů z této IP adresy (<strong>$1</strong>) bylo zablokováno {{GENDER:$3|uživatelem|uživatelkou}} [[User:$3|$3]].\n\n$3 uvádí toto zdůvodnění: <em>$2</em>",
        "cantcreateaccount-range-text": "Zakládání nových účtů z IP adres v rozsahu <strong>$1</strong>, který obsahuje i vaši IP adresu (<strong>$4</strong>), bylo zablokováno {{GENDER:$3|uživatelem|uživatelkou}} [[User:$3|$3]].\n\n$3 uvádí toto zdůvodnění: <em>$2</em>",
        "viewpagelogs": "Zobrazit protokolovací záznamy k této stránce",
        "nohistory": "O této stránce neexistuje historie editací.",
        "recentchangeslinked-page": "Název stránky:",
        "recentchangeslinked-to": "Zobrazit změny na stránkách odkazujících na zadanou stránku",
        "recentchanges-page-added-to-category": "Stránka [[:$1]] zařazena do kategorie",
-       "recentchanges-page-added-to-category-bundled": "Stránka [[:$1]] a {{PLURAL:$2|jedna další zařazeny|$2 další zařazeny|$2 dalších zařazeno}} do kategorie",
+       "recentchanges-page-added-to-category-bundled": "Stránka [[:$1]] a [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedna další zařazeny|$2 další zařazeny|$2 dalších zařazeno}}]] do kategorie",
        "recentchanges-page-removed-from-category": "Stránka [[:$1]] vyřazena z kategorie",
-       "recentchanges-page-removed-from-category-bundled": "Stránka [[:$1]] a {{PLURAL:$2|jedna další vyřazeny|$2 další vyřazeny|$2 dalších vyřazeno}} z kategorie",
+       "recentchanges-page-removed-from-category-bundled": "Stránka [[:$1]] a [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedna další vyřazeny|$2 další vyřazeny|$2 dalších vyřazeno}}]] z kategorie",
        "autochange-username": "Automatická změna MediaWiki",
        "upload": "Načíst soubor",
        "uploadbtn": "Načíst soubor",
        "ignorewarning": "Ignorovat varování a načíst soubor.",
        "ignorewarnings": "Ignorovat všechna varování",
        "minlength1": "Jméno souboru musí mít alespoň jeden znak.",
-       "illegalfilename": "Název souboru \"$1\" obsahuje znaky, které nejsou povoleny v názvech stránek. Prosím přejmenujte soubor a zkuste jej nahrát znovu.",
+       "illegalfilename": "Název souboru „$1“ obsahuje znaky, které nejsou povoleny v názvech stránek. Prosím přejmenujte soubor a zkuste jej nahrát znovu.",
        "filename-toolong": "Jména souborů nemohou být delší než 240 bajtů.",
        "badfilename": "Jméno souboru bylo změněno na „$1“.",
        "filetype-mime-mismatch": "Přípona souboru „.$1“ neodpovídá rozpoznanému MIME typu souboru ($2).",
        "filetype-bad-ie-mime": "Nelze načíst tento soubor, neboť Internet Explorer by ho považoval za „$1“, což je nedovolený a potenciálně nebezpečný typ souboru.",
        "filetype-unwanted-type": "„.$1“''' je nežádoucí formát souborů. {{PLURAL:$3|Upřednostňovaný formát souborů je|Upřednostňované formáty souborů jsou}} $2.",
        "filetype-banned-type": "'''„.$1“''' {{PLURAL:$4|je nedovolený formát souborů|jsou nedovolené formáty souborů}}.\n{{PLURAL:$3|Povolený formát souborů je|Povolené formáty souborů jsou}} $2.",
-       "filetype-missing": "Soubor nemá příponu (např. \".jpg\").",
+       "filetype-missing": "Soubor nemá příponu (např. „.jpg“).",
        "empty-file": "Načtený soubor je prázdný.",
        "file-too-large": "Načtený soubor je příliš velký.",
        "filename-tooshort": "Název souboru je příliš krátký.",
        "uploadstash-badtoken": "Operace se nezdařila. Možná vypršela platnost vašeho oprávnění k editaci. Zkuste to znovu.",
        "uploadstash-errclear": "Soubory se nepodařilo vymazat.",
        "uploadstash-refresh": "Aktualizovat seznam souborů",
+       "uploadstash-thumbnail": "zobrazit náhled",
        "invalid-chunk-offset": "Neplatný posun bloku",
        "img-auth-accessdenied": "Přístup odepřen",
        "img-auth-nopathinfo": "Chybí PATH_INFO.\nVáš server není nastaven tak, aby tuto informaci poskytoval.\nMožná funguje pomocí CGI a img_auth na něm nemůže fungovat.\nVizte https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "changecontentmodel-title-label": "Název stránky",
        "changecontentmodel-model-label": "Nový model obsahu",
        "changecontentmodel-reason-label": "Důvod:",
+       "changecontentmodel-submit": "Změnit",
        "changecontentmodel-success-title": "Model obsahu byl změněn",
        "changecontentmodel-success-text": "Model obsahu stránky [[:$1]] byl změněn.",
        "changecontentmodel-cannot-convert": "Obsah stránky [[:$1]] nelze zkonvertovat na typ $2.",
        "ipb-unblock": "Odblokovat uživatele nebo IP adresu",
        "ipb-blocklist": "Zobrazit probíhající bloky",
        "ipb-blocklist-contribs": "Příspěvky {{GENDER:$1|uživatele|uživatelky}} $1",
+       "ipb-blocklist-duration-left": "zbývá $1",
        "unblockip": "Odblokovat uživatele",
        "unblockiptext": "Tímto formulářem je možno obnovit právo blokované IP adresy či uživatele opět přispívat do {{grammar:2sg|{{SITENAME}}}}.",
        "ipusubmit": "Odblokovat",
        "autoblocker": "Automatické zablokování kvůli tomu, že vaši IP adresu nedávno {{GENDER:$1|používal uživatel|používala uživatelka}} „[[User:$1|$1]]“.\nDůvod zablokování {{GENDER:$1|uživatele $1|uživatelky $1}}: „$2“",
        "blocklogpage": "Kniha zablokování",
        "blocklog-showlog": "{{GENDER:$1|Tento uživatel byl dříve blokován.|Tato uživatelka byla dříve blokována.|Tento uživatel byl dříve blokován.}}\nZde je pro přehled zobrazen výpis z knihy zablokování:",
-       "blocklog-showsuppresslog": "Tento uživatel byl zablokován a skryt. Zde je pro přehled zobrazen výpis záznamu utajení:",
+       "blocklog-showsuppresslog": "{{GENDER:$1|Tento uživatel byl zablokován a skryt|Tato uživatelka byla zablokována a skryta}}. Zde je pro přehled zobrazen výpis záznamu utajení:",
        "blocklogentry": "blokuje „[[$1]]“ s časem vypršení $2 $3",
        "reblock-logentry": "mění nastavení bloku „[[$1]]“ s časem vypršení $2 $3",
        "blocklogtext": "Toto je kniha úkonů blokování a odblokování uživatelů.\nAutomaticky blokované IP adresy nejsou vypsány.\nVizte též [[Special:BlockList|seznam všech probíhajících bloků]].",
        "ipb_expiry_temp": "Blokování skrytých uživatelských jmen by měla být trvalá.",
        "ipb_hide_invalid": "Tento účet nelze utajit; má více než $1 {{PLURAL:$1|editaci|editace|editací}}.",
        "ipb_already_blocked": "„$1“ již je zablokován.",
-       "ipb-needreblock": "$1 je již {{GENDER:zablokován|zablokována}}. Chcete změnit nastavení bloku?",
+       "ipb-needreblock": "$1 je již {{GENDER:$1|zablokován|zablokována|zablokován(a)}}. Chcete změnit nastavení bloku?",
        "ipb-otherblocks-header": "{{PLURAL:$1|Jiné zablokování|Jiná zablokování}}",
        "unblock-hideuser": "Tohoto uživatele nemůžete odblokovat, protože jeho uživatelské jméno bylo skryto.",
        "ipb_cant_unblock": "Chyba: Blokování s ID $1 nebylo nalezeno. Uživatel již možná byl odblokován.",
        "import-logentry-upload-detail": "{{PLURAL:$1|naimportována $1 revize|naimportovány $1 revize|naimportováno $1 revizí}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|naimportována $1 revize|naimportovány $1 revize|naimportováno $1 revizí}} z $2",
        "javascripttest": "Testování JavaScriptu",
-       "javascripttest-pagetext-noframework": "Tato stránka je vyhrazena pro spouštění testů JavaScriptu.",
-       "javascripttest-pagetext-unknownframework": "Neznámá testovací knihovna „$1“.",
        "javascripttest-pagetext-unknownaction": "Neznámá akce „$1“.",
-       "javascripttest-pagetext-frameworks": "Zvolte jednu z následujících testovacích knihoven: $1",
-       "javascripttest-pagetext-skins": "Zvolte vzhled, pod kterým se mají testy spustit:",
        "javascripttest-qunit-intro": "Vizte [$1 dokumentaci testování] na mediawiki.org",
        "tooltip-pt-userpage": "{{GENDER:|Vaše uživatelská}} stránka",
        "tooltip-pt-anonuserpage": "Uživatelská stránka pro IP adresu, ze které editujete",
        "tooltip-pt-anoncontribs": "Seznam editací provedených z této IP adresy",
        "tooltip-pt-login": "Doporučujeme vám přihlásit se, ovšem není to povinné.",
        "tooltip-pt-logout": "Odhlásit se",
-       "tooltip-pt-createaccount": "Doporučujeme vytvořit si účet a přihlásit se, není to však povinné",
+       "tooltip-pt-createaccount": "Doporučujeme vytvořit si účet a přihlásit se, ovšem není to povinné",
        "tooltip-ca-talk": "Diskuse ke stránce",
        "tooltip-ca-edit": "Editovat tuto stránku",
        "tooltip-ca-addsection": "Začít novou sekci",
        "tooltip-ca-nstab-media": "Zobrazit stránku souboru",
        "tooltip-ca-nstab-special": "Toto je speciální stránka, kterou nelze editovat.",
        "tooltip-ca-nstab-project": "Zobrazit stránku o wiki",
-       "tooltip-ca-nstab-image": "Zobrazit stránku obrázku",
+       "tooltip-ca-nstab-image": "Zobrazit stránku souboru",
        "tooltip-ca-nstab-mediawiki": "Zobrazit systémovou zprávu",
        "tooltip-ca-nstab-template": "Zobrazit šablonu",
        "tooltip-ca-nstab-help": "Zobrazit stránku nápovědy",
        "version-libraries-description": "Popis",
        "version-libraries-authors": "Autoři",
        "redirect": "Přesměrování podle ID souboru, uživatele, stránky, revize nebo protokolovacího záznamu",
-       "redirect-legend": "Přesměrování na soubor či stránku",
        "redirect-summary": "Tato speciální stránka přesměrovává na soubor (podle názvu), stránku (podle ID stránky nebo revize), uživatele (podle číselného uživatelského ID) nebo protokolovací záznam (podle ID záznamu). Použití: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]],[[{{#Special:Redirect}}/user/101]] nebo [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Přejít",
        "redirect-lookup": "Najít:",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|zamknul|zamknula}} stránku $3 $4 [kaskádovým zámkem]",
        "logentry-protect-modify": "$1 {{GENDER:$2|změnil|změnila}} úroveň ochrany stránky $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|změnil|změnila}} úroveň ochrany stránky $3 $4 [kaskádový zámek]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|změnil|změnila}} členství $3 ve skupinách z $4 na $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|změnil|změnila}} členství {{GENDER:$3|uživatele|uživatelky}} $3 ve skupinách z $4 na $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|změnil|změnila}} členství $3 ve skupinách",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|byl automaticky povýšen|byla automaticky povýšena}} z $4 na $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|načetl|načetla}} $3",
        "api-error-unknownerror": "Neznámá chyba: „$1“.",
        "api-error-uploaddisabled": "Načítání souborů je na této wiki vypnuto.",
        "api-error-verification-error": "Soubor je možná poškozen nebo má špatnou příponu.",
+       "api-error-was-deleted": "Soubor s tímto názvem byl již dříve načten a později smazán.",
        "duration-seconds": "$1 {{PLURAL:$1|sekunda|sekundy|sekund}}",
        "duration-minutes": "$1 {{PLURAL:$1|minuta|minuty|minut}}",
        "duration-hours": "$1 {{PLURAL:$1|hodina|hodiny|hodin}}",
        "special-characters-group-ipa": "Mezinárodní fonetická abeceda (IPA)",
        "special-characters-group-symbols": "Symboly",
        "special-characters-group-greek": "Řecká abeceda",
+       "special-characters-group-greekextended": "Rozšíření řečtiny",
        "special-characters-group-cyrillic": "Cyrilice",
        "special-characters-group-arabic": "Arabské písmo",
        "special-characters-group-arabicextended": "Rozšíření arabštiny",
        "sessionprovider-generic": "relace pomocí $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "relace pomocí cookies",
        "sessionprovider-nocookies": "Možná jsou zakázány cookies. Ujistěte se, že máte cookies povoleny a zkuste to znovu.",
-       "randomrootpage": "Náhodná kořenová stránka"
+       "randomrootpage": "Náhodná kořenová stránka",
+       "log-action-filter-block": "Typ zablokování:",
+       "log-action-filter-delete": "Typ smazání:",
+       "log-action-filter-patrol": "Typ prověření:",
+       "log-action-filter-protect": "Typ zamčení:",
+       "log-action-filter-upload": "Typ nahrání:",
+       "log-action-filter-all": "Všechny",
+       "log-action-filter-block-block": "Zablokování",
+       "log-action-filter-block-reblock": "Změna zablokování",
+       "log-action-filter-block-unblock": "Odblokování",
+       "log-action-filter-delete-delete": "Smazání stránky",
+       "log-action-filter-delete-restore": "Obnovení stránky",
+       "log-action-filter-delete-event": "Smazání záznamu",
+       "log-action-filter-delete-revision": "Smazání revize",
+       "log-action-filter-patrol-patrol": "Manuální prověření",
+       "log-action-filter-patrol-autopatrol": "Automatické prověření",
+       "log-action-filter-protect-protect": "Zamknutí",
+       "log-action-filter-protect-modify": "Změna zámku",
+       "log-action-filter-protect-unprotect": "Odemknutí",
+       "log-action-filter-upload-upload": "Nové načtení",
+       "log-action-filter-upload-overwrite": "Znovunačtení"
 }
index 07babc7..3ff54a8 100644 (file)
@@ -15,7 +15,8 @@
                        "아라",
                        "Macofe",
                        "Matma Rex",
-                       "Diafol"
+                       "Diafol",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Tanlinellu cysylltiadau:",
@@ -50,6 +51,7 @@
        "tog-watchlisthidebots": "Cuddio golygiadau bot yn fy rhestr wylio",
        "tog-watchlisthideminor": "Cuddio golygiadau bychain rhag y rhestr wylio",
        "tog-watchlisthideliu": "Cuddio golygiadau gan ddefnyddwyr mewngofnodedig rhag y rhestr wylio",
+       "tog-watchlistreloadautomatically": "Ail-lwyther y Rhestr wylio yn otomatigpan newider ffiltr (angen JavaScript)",
        "tog-watchlisthideanons": "Cuddio golygiadau gan ddefnyddwyr anhysbys rhag y rhestr wylio",
        "tog-watchlisthidepatrolled": "Cuddio golygiadau sydd wedi derbyn ymweliad patrôl rhag y rhestr wylio",
        "tog-watchlisthidecategorization": "Cuddiwych y categoriau",
        "october-date": "$1 Hydref",
        "november-date": "$1 Tachwedd",
        "december-date": "$1 Rhagfyr",
+       "period-am": "AM",
+       "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categori|Categori|Categorïau|Categorïau|Categorïau|Categorïau}}",
        "category_header": "Erthyglau yn y categori \"$1\"",
        "subcategories": "Is-gategorïau",
        "newpassword": "Cyfrinair newydd:",
        "retypenew": "Ail-deipiwch y cyfrinair newydd:",
        "resetpass_submit": "Gosod y cyfrinair a mewngofnodi",
-       "changepassword-success": "Llwyddodd y newid i'ch cyfrinair!",
+       "changepassword-success": "Newidiwyd eich cyfrinair!",
        "changepassword-throttled": "Rydych wedi ceisio logio mewn yn rhy aml.\nArhoswch am $1 cyn trio eto.",
+       "botpasswords-label-delete": "Diddymu neu ddileu",
+       "botpasswords-label-resetpassword": "Ailosod y cyfrinair",
+       "botpasswords-label-grants": "Nawdd perthnasol:",
        "resetpass_forbidden": "Ni ellir newid cyfrineiriau",
        "resetpass-no-info": "Ni allwch fynd at y dudalen hon yn uniongyrchol heblaw eich bod wedi mewngofnodi.",
        "resetpass-submit-loggedin": "Newidier y cyfrinair",
        "sig_tip": "Eich llofnod gyda stamp amser",
        "hr_tip": "Llinell lorweddol (peidiwch â'i gor-ddefnyddio)",
        "summary": "Crynodeb:",
-       "subject": "Pwnc/pennawd:",
+       "subject": "Pwnc:",
        "minoredit": "Golygiad bychan yw hwn",
        "watchthis": "Gwylier y dudalen hon",
        "savearticle": "Cadw'r dudalen",
        "missingsummary": "'''Sylwer:''' Nid ydych wedi gosod nodyn yn y blwch 'Crynodeb'.\nOs y pwyswch eto ar 'Cadw'r dudalen' caiff y golygiad ei gadw heb nodyn.",
        "selfredirect": "<strong>Gofal:</strong> Rydych yn ailgyfeirio'r dudalen hon ati hi ei hun!  Gwirwch yr hyn rydych yn ceisio'i wneud. Os cliciwch \"{{int:savearticle}}\" eto yna caiff y dudalen ailgyfeirio (wallus!) ei chreu beth bynnag.",
        "missingcommenttext": "Rhowch eich sylwadau isod.",
-       "missingcommentheader": "'''Nodyn:''' Nid ydych wedi cynnig unrhywbeth yn y blwch 'Pwnc/Pennawd:'. Os y cliciwch \"{{int:savearticle}}\" eto fe gedwir y golygiad heb bennawd.",
+       "missingcommentheader": "<strong>Nodyn atgoffa:</strong> \nNid ydych wedi cynnig unrhywbeth yn y blwch 'Pwnc:'. Os y cliciwch \"{{int:savearticle}}\" eto fe gedwir y golygiad heb bennawd.",
        "summary-preview": "Rhagolwg o'r crynodeb:",
-       "subject-preview": "Rhagolwg pwnc/pennawd:",
+       "subject-preview": "Rhagolwg pwnc:",
        "blockedtitle": "Mae'r defnyddiwr hwn wedi cael ei flocio",
        "blockedtext": "'''Mae eich enw defnyddiwr neu gyfeiriad IP wedi cael ei flocio.'''\n\n$1 a osododd y bloc.\nY rheswm a roddwyd dros y blocio yw: ''$2''.\n\n*Dechreuodd y bloc am: $8\n*Bydd y bloc yn dod i ben am: $6\n*Bwriadwyd blocio: $7\n\nGallwch gysylltu â $1 neu un arall o'r [[{{MediaWiki:Grouppage-sysop}}|gweinyddwyr]] i drafod y bloc.\nSylwch mai dim ond y rhai sydd wedi gosod cyfeiriad e-bost yn eu [[Special:Preferences|dewisiadau defnyddiwr]], a hwnnw heb ei flocio, sydd yn gallu 'anfon e-bost at ddefnyddiwr' trwy'r wici.\n$3 yw eich cyfeiriad IP presennol. Cyfeirnod y bloc yw #$5.\nPan yn ysgrifennu at weinyddwr, cofiwch gynnwys yr holl fanylion uchod, os gwelwch yn dda.",
        "autoblockedtext": "Rhoddwyd bloc yn awtomatig ar eich cyfeiriad IP oherwydd iddo gael ei ddefnyddio gan ddefnyddiwr arall, a bod bloc wedi ei roi ar hwnnw gan $1.\nY rheswm a roddwyd dros y bloc oedd:\n\n:''$2''\n\n*Dechreuodd y bloc am: $8\n*Daw'r bloc i ben am: $6\n*Bwriadwyd blocio: $7\n\nGallwch gysylltu â $1 neu un arall o'r [[{{MediaWiki:Grouppage-sysop}}|gweinyddwyr]] i drafod y bloc.\n\nSylwch mai dim ond y rhai sydd wedi gosod cyfeiriad e-bost yn eu [[Special:Preferences|dewisiadau defnyddiwr]], a hwnnw heb ei flocio, sydd yn gallu 'anfon e-bost at ddefnyddiwr' trwy'r wici.\n\nEich cyfeiriad IP presennol yw $3. Cyfeirnod y bloc yw $5. Nodwch y manylion hyn wrth drafod y bloc.",
        "notextmatches": "Does dim testun yn cyfateb",
        "prevn": "{{PLURAL:$1||yr $1 cynt|y $1 gynt|y $1 chynt|y $1 chynt|y $1 cynt}}",
        "nextn": "y {{PLURAL:$1|$1}} nesaf",
+       "prev-page": "tudalen flaenorol",
+       "next-page": "tudalen nesaf",
        "prevn-title": "Y $1 {{PLURAL:$1|canlyiad|canlyniad|ganlyniad|chanlyniad|chanlyniad|canlyniad}} cynt",
        "nextn-title": "Y $1 {{PLURAL:$1|canlyiad|canlyniad|ganlyniad|chanlyniad|chanlyniad|canlyniad}} nesaf",
        "shown-title": "Dangos $1 {{PLURAL:$1|canlyiad|canlyniad|ganlyniad|chanlyniad|chanlyniad|canlyniad}} y dudalen",
        "userrights": "Rheoli galluoedd defnyddwyr",
        "userrights-lookup-user": "Rheoli grwpiau defnyddiwr",
        "userrights-user-editname": "Rhowch enw defnyddiwr:",
-       "editusergroup": "Golygu Grwpiau Defnyddwyr",
+       "editusergroup": "Golygu Grwpiau {{GENDER:$1|Defnyddwyr}}",
        "editinguser": "Newid galluoedd {{GENDER:$1|y defnyddiwr}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Golygu grwpiau defnyddwyr",
-       "saveusergroups": "Cadw'r Grwpiau Defnyddwyr",
+       "saveusergroups": "Cadw'r Grwpiau {{GENDER:$1|Defnyddwyr}}",
        "userrights-groupsmember": "Yn aelod o:",
        "userrights-groupsmember-auto": "Ac ynghlwm wrth aelodaeth y grwpiau uchod, yn aelod o:",
        "userrights-groups-help": "Gallwch newid y grwpiau y perthyn y defnyddiwr hwn iddynt:\n* Mae defnyddiwr yn perthyn i grŵp pan mae tic yn y bocs.\n* Nid yw defnyddiwr yn perthyn i grŵp pan nad oes tic yn y bocs.\n* Mae * yn golygu na fyddwch yn gallu dad-wneud unrhyw newid yn y grŵp hwnnw.",
        "userrights-changeable-col": "Grwpiau y gallwch eu newid",
        "userrights-unchangeable-col": "Grwpiau na allwch eu newid",
        "userrights-conflict": "Gwrthdaro oherwydd newid i hawliau defnyddiwr! Adolygwch eich newidiadau a'u cadarnhau.",
-       "userrights-removed-self": "Rydych wedi llwyddo rhoi'r gorau i'ch galluoedd. Gan hynny, nid ydych yn cael myned i'r dudalen hon bellach.",
+       "userrights-removed-self": "Rydych wedi rhoi'r gorau i'ch galluoedd. Gan hynny, ni allwch gyrchu'r ddalen hon bellach.",
        "group": "Grŵp:",
        "group-user": "Defnyddwyr",
        "group-autoconfirmed": "Defnyddwyr wedi eu cadarnhau'n awtomatig",
        "right-sendemail": "Anfon e-bost at ddefnyddwyr eraill",
        "right-passwordreset": "Gweld e-byst sy'n ailosod cyfrinair",
        "right-managechangetags": "Creu a dileu [[Special:Tags|tagiau]] o'r gronfa ddata",
+       "grant-group-email": "Danfon ebost",
+       "grant-basic": "Hawliau sylfaenol",
+       "grant-viewdeleted": "Gweld ffeiliau a ddilewyd",
+       "grant-viewmywatchlist": "Gweld eich Rhestr Wylio",
        "newuserlogpage": "Lòg creu cyfrifon defnyddwyr newydd",
        "newuserlogpagetext": "Dyma restr o'r defnyddwyr newydd sydd wedi ymuno â'r wici.",
        "rightslog": "Lòg galluoedd defnyddiwr",
        "recentchanges-legend-heading": "<strong>Allwedd:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (gweler hefyd [[Special:NewPages|restr y tudalennau newydd]])",
        "recentchanges-legend-plusminus": "(''±123'')",
+       "recentchanges-submit": "Dangos",
        "rcnotefrom": "Isod rhestrir pob newid er <strong>$3, $4</strong> (ymddengys <strong>$1</strong> ohonynt).",
        "rclistfrom": "Dangos newidiadau newydd, gan ddechrau ers $3 $2",
        "rcshowhideminor": "$1 golygiadau bychain",
        "rcshowhidemine": "$1 fy ngolygiadau",
        "rcshowhidemine-show": "Dangoser",
        "rcshowhidemine-hide": "Cuddier",
+       "rcshowhidecategorization": "Categorieiddio tudalen $1",
+       "rcshowhidecategorization-show": "Dangos",
+       "rcshowhidecategorization-hide": "Cuddio",
        "rclinks": "Dangos y $1 newid diweddaraf yn ystod y(r) $2 diwrnod diwethaf<br />$3",
        "diff": "gwahan",
        "hist": "hanes",
        "recentchangeslinked-page": "Tudalen:",
        "recentchangeslinked-to": "Dangos newidiadau i'r tudalennau â chyswllt arnynt sy'n arwain at y dudalen a enwir",
        "recentchanges-page-added-to-category": "Ychwanegwyd [[:$1]] at y categori",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] ac {{PLURAL:$2|un ddalen|$2 dalen}} wedi'u hychwanegu at y categori",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] ac [[Special:WhatLinksHere/$1|{{PLURAL:$2|un ddalen|$2 dalen}}]] wedi'u hychwanegu at y categori",
+       "recentchanges-page-removed-from-category": "Symudwyd [[:$1]] o'r categori",
        "upload": "Uwchlwytho ffeil",
        "uploadbtn": "Uwchlwytho ffeil",
        "reuploaddesc": "Dileu'r uwchlwytho a dychwelyd i'r ffurflen uwchlwytho",
        "upload-too-many-redirects": "Roedd gormod o ailgyfeiriadau yn yr URL",
        "upload-http-error": "Digwyddodd gwall HTTP: $1",
        "upload-copy-upload-invalid-domain": "Ni ellir uwchlwytho ffeiliau o'r parth hwn.",
+       "upload-dialog-title": "Uwchlwytho ffeil",
+       "upload-dialog-button-cancel": "Canslo",
+       "upload-dialog-button-done": "Wedi cwbwlhau",
+       "upload-dialog-button-save": "Wedi ei gadw",
+       "upload-dialog-button-upload": "Uwchlwytho",
+       "upload-form-label-infoform-title": "Manylion",
+       "upload-form-label-infoform-name": "Enw",
+       "upload-form-label-infoform-description": "Disgrifiad",
+       "upload-form-label-usage-title": "Defnydd",
+       "upload-form-label-usage-filename": "Enw'r ffeil",
+       "foreign-structured-upload-form-label-own-work": "Dyma fy ngwaith fy hun",
+       "foreign-structured-upload-form-label-infoform-categories": "Categoriau",
+       "foreign-structured-upload-form-label-infoform-date": "Dyddiad",
+       "foreign-structured-upload-form-label-own-work-message-local": "Rwy'n cadarnhau fy mod yn uwchlwytho'r ffeil yma gan ddilyn amodau a pholisiau trwyddedu {{SITENAME}}.",
+       "foreign-structured-upload-form-label-not-own-work-local-local": "Efallai y carwch hefyd roi gynnig ar [[Special:Upload|y ddalen uwchlwytho diofyn]].",
+       "foreign-structured-upload-form-label-own-work-message-default": "Rwy'n cadarnhau fy mod yn uwchlwytho'r ffeil yma i fan sy'n cael ei rannu gan nifer. Rwy'n cadarnhau hefyd y gwnaf hyn gan ddilyn yr amodau a'r polisiau trwyddedu sydd yno.",
+       "foreign-structured-upload-form-label-own-work-message-shared": "Cadarnhaf mai fi yw perchennog hawlfraint y ffeil hon, a chytunaf  yn ddi-droi'n ôl i ryddhau'r ffeil hon i Gomin Wicimedia dan drwydded [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0], a chytunaf gyda'r[https://wikimediafoundation.org/wiki/Terms_of_Use Amodau Defnyddio].",
        "backend-fail-stream": "Wedi methu ffrydio'r ffeil $1.",
        "backend-fail-backup": "Wedi methu gwneud copi wrth gefn o'r ffeil $1.",
        "backend-fail-notexists": "Nid yw'r ffeil $1 ar gael.",
        "backend-fail-read": "Wedi methu darllen y ffeil $1.",
        "backend-fail-create": "Wedi methu ysgrifennu'r ffeil $1.",
        "backend-fail-maxsize": "Ni ellid ysgrifennu'r ffeil $1 oherwydd ei bod yn fwy na{{PLURAL:$2||g un beit| $2 feit| $2 beit| $2 beit| $2 beit}} o faint.",
-       "backend-fail-readonly": "Ar hyn o bryd gellir darllen y storfa \"$1\" yn unig. Y rheswm dros hyn yw: \"''$2''\"",
+       "backend-fail-readonly": "Ar hyn o bryd gellir darllen y storfa \"$1\" yn unig. Y rheswm dros hyn yw:\n<em>$2</em>",
        "backend-fail-synced": "Mae'r ffeil \"$1\" mewn cyflwr anghyson oddi mewn i'r storfeydd tu ôl i'r llenni.",
        "backend-fail-connect": "Ni ellid cysylltu â'r storfa tu ôl i'r llenni yn \"$1\".",
        "backend-fail-internal": "Cafwyd gwall anhysbys yn y storfa tu ôl i'r llenni yn \"$1\".",
        "uploadstash-summary": "O'r dudalen hon gallwch gyrchu'r ffeiliau sydd wedi cael eu huwchlwytho (neu wrthi'n cael eu huwchlwytho) ond nad ydynt wedi eu cyhoeddi ar y wici eto. Nid oes neb yn gallu gweld y ffeiliau heblaw am y defnyddiwr a'u huwchlwythodd.",
        "uploadstash-clear": "Clirio'r celc ffeiliau",
        "uploadstash-nofiles": "Nid oes unrhyw ffeiliau mewn celc gennych.",
-       "uploadstash-badtoken": "Ni lwyddodd y weithred, efallai oherwydd bod eich cymwysterau golygu wedi dod i ben. Ceisiwch eto.",
+       "uploadstash-badtoken": "Ni lwyddodd y weithred. Efallai oherwydd bod eich cymwysterau golygu wedi dod i ben. Ceisiwch eto.",
        "uploadstash-errclear": "Ni lwyddwyd i glirio'r ffeiliau.",
        "uploadstash-refresh": "Adnewyddu rhestr y ffeiliau",
        "invalid-chunk-offset": "Atred annilys i'r talpiau",
        "listfiles-delete": "dileu",
        "listfiles-summary": "Rhestr yr holl ffeiliau sydd wedi eu huwchlwytho sydd ar y dudalen hon.",
        "listfiles_search_for": "Chwilio am enw'r ddelwedd:",
+       "listfiles-userdoesnotexist": "Ni yw cyfrif defnyddiwr \"$1\" wedi'i gofrestru.",
        "imgfile": "ffeil",
        "listfiles": "Rhestr o'r holl ffeiliau",
        "listfiles_thumb": "Mân-lun",
        "randomincategory-nopages": "Nid oes unrhyw dudalennau yn y categori [[:Category:$1]].",
        "randomincategory-category": "Categori:",
        "randomincategory-legend": "Tudalen ar hap o blith tudalennau'r categori",
+       "randomincategory-submit": "Ewch",
        "randomredirect": "Tudalen ailgyfeirio ar hap",
        "randomredirect-nopages": "Does dim tudalennau ailgyfeirio yn y parth \"$1\".",
        "statistics": "Ystadegau",
        "mostrevisions": "Tudalennau yn nhrefn nifer y newidiadau iddynt",
        "prefixindex": "Pob tudalen yn ôl parth",
        "prefixindex-namespace": "Pob tudalen â rhagddodiad penodol (y parth $1)",
+       "prefixindex-submit": "Dangos",
        "prefixindex-strip": "Diosg y rhagddodiad wrth restru",
        "shortpages": "Erthyglau byr",
        "longpages": "Tudalennau hirion",
        "protectedpages-performer": "Y diogelwr",
        "protectedpages-params": "Paramedrau'r diogelu",
        "protectedpages-reason": "Rheswm",
+       "protectedpages-submit": "Dangos y dalenau",
        "protectedpages-unknown-timestamp": "Anhysbys",
        "protectedpages-unknown-performer": "Defnyddiwr anhysbys",
        "protectedtitles": "Teitlau wedi eu diogelu",
        "protectedtitlesempty": "Ar hyn o bryd nid oes unrhyw deitlau wedi eu diogelu a'r paramedrau hyn.",
+       "protectedtitles-submit": "Dangos y teitlau",
        "listusers": "Rhestr defnyddwyr",
        "listusers-editsonly": "Dangos y defnyddwyr hynny sydd wedi golygu rhywbeth yn unig",
        "listusers-creationsort": "Trefnwch yn ôl dyddiad creu",
        "usereditcount": "$1 {{PLURAL:$1|golygiad|golygiad|olygiad|golygiad|golygiad|o olygiadau}}",
        "usercreated": "{{GENDER:$3|Crëwyd}} ar $1 am $2",
        "newpages": "Erthyglau newydd",
+       "newpages-submit": "Dangos",
        "newpages-username": "Enw defnyddiwr:",
        "ancientpages": "Erthyglau hynaf",
        "move": "Symud",
        "apihelp": "Cymorth API",
        "apihelp-no-such-module": "Ni chafwyd hyd i fodiwl \"$1\".",
        "apisandbox": "Pwll tywod API",
+       "apisandbox-fullscreen": "Ehangu'r panel",
+       "apisandbox-unfullscreen": "Dangos y ddalen",
+       "apisandbox-submit": "Gwnewch gais",
+       "apisandbox-reset": "Clirio",
+       "apisandbox-retry": "Ailgeisio",
        "booksources": "Ffynonellau llyfrau",
        "booksources-search-legend": "Chwilier am lyfrau",
        "booksources-search": "Chwilio",
        "import-nonewrevisions": "Ni fewnforwyd unrhyw ddiwygiadau (y cwbl eisoes yn bresennol, neu wedi eu hepgor oherwydd eu bod yn wallus).",
        "xml-error-string": "$1 ar linell $2, col $3 (beit $4): $5",
        "import-upload": "Uwchlwytho data XML",
-       "import-token-mismatch": "Collwyd data'r sesiwn. Ceisiwch eto.",
+       "import-token-mismatch": "Collwyd y data.\n\nEfallai i chi allgofnodi (logio allan).<strong>Cadarnhewch eich bod yn dal wedi mewngofnodi a cheisiwch eto</strong>\nOs yw'n parhau i fethu, ceisiwch [[Special:UserLogout|allgofnodi]] a mewngofnodwch drachefn, a gwirwch fod eich porwr yn caniatau cwcis o'r wefan hon.",
        "import-invalid-interwiki": "Ni ellir uwchlwytho o'r wici dewisedig.",
        "import-error-edit": "Ni fewnforiwyd y dudalen \"$1\" oherwydd nad yw'r gallu i'w golygu gennych.",
        "import-error-create": "Ni fewnforiwyd y dudalen \"$1\" oherwydd nad yw'r hawl i'w chreu gennych.",
        "pageinfo-category-files": "Nifer y ffeiliau",
        "markaspatrolleddiff": "Marcio ei bod wedi derbyn ymweliad patrôl",
        "markaspatrolledtext": "Marcio bod y dudalen wedi derbyn ymweliad patrôl",
+       "markaspatrolledtext-file": "Marcio fod fersiwn y ffeil wedi cael ymweliad",
        "markedaspatrolled": "Gosodwyd marc ei bod wedi derbyn ymweliad patrôl",
        "markedaspatrolledtext": "Wedi gosod marc bod y golygiad dewisedig o [[:$1]] wedi derbyn ymweliad patrôl.",
        "rcpatroldisabled": "Patrol y Newidiadau Diweddar wedi'i analluogi",
        "expand_templates_generate_xml": "Dangos y goeden dosrannu XML",
        "expand_templates_generate_rawhtml": "Dangos HTML crai",
        "expand_templates_preview": "Rhagolwg",
-       "pagelanguage": "Dewis iaith y dudalen",
+       "pagelanguage": "Newidiwch iaith ddalen",
        "pagelang-name": "Tudalen",
        "pagelang-language": "Iaith",
        "pagelang-use-default": "Defnyddier yr iaith arferol",
        "pagelang-select-lang": "Dewis iaith",
+       "pagelang-submit": "Ei wneud",
        "right-pagelang": "Newidiwch iaith y dudalen",
        "action-pagelang": "newidiwch iaith y dudalen",
        "log-name-pagelang": "Newidiwch iaith y log",
        "mediastatistics-header-text": "Testun",
        "mediastatistics-header-executable": "Gweithredadwy",
        "mediastatistics-header-archive": "Fformat wedi'i gywasgu",
+       "mediastatistics-header-total": "Pob ffeil",
        "json-warn-trailing-comma": "Tynnwyd $1 {{PLURAL:$1|coma}} o JSON",
        "json-error-unknown": "Roedd gwall gyda JSON. Gwall: $1",
        "json-error-depth": "Aethpwyd dros y dyfnder mwyaf a ganiateir",
index 8263cf6..068164e 100644 (file)
@@ -56,7 +56,8 @@
                        "Mads Haupt",
                        "Stefan2",
                        "Ribewiki",
-                       "Jens Jensen"
+                       "Jens Jensen",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Understreg henvisninger:",
        "recentchangeslinked-page": "Sidenavn:",
        "recentchangeslinked-to": "Vis ændringer i sider der henviser til den angivne side i stedet",
        "recentchanges-page-added-to-category": "[[:$1]] tilføjet til kategori",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] og {{PLURAL:$2|én side|$2 sider}} tilføjet til kategori",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] og [[Special:WhatLinksHere/$1|{{PLURAL:$2|én side|$2 sider}}]] tilføjet til kategori",
        "upload": "Læg en fil op",
        "uploadbtn": "Læg en fil op",
        "reuploaddesc": "Tilbage til formularen til at lægge filer op.",
index 5196fe7..2b1453d 100644 (file)
        "editfont-style": "Schriftart für den Text im Bearbeitungsfenster:",
        "editfont-default": "Browserstandard",
        "editfont-monospace": "Schrift mit fester Zeichenbreite",
-       "editfont-sansserif": "Serifenlose Groteskschrift",
+       "editfont-sansserif": "Schrift ohne Serifen",
        "editfont-serif": "Schrift mit Serifen",
        "sunday": "Sonntag",
        "monday": "Montag",
        "noemail": "{{GENDER:$1|Benutzer|Benutzerin}} „$1“ hat keine E-Mail-Adresse angegeben.",
        "noemailcreate": "Du musst eine gültige E-Mail-Adresse angeben.",
        "passwordsent": "Ein neues, temporäres Passwort wurde an die E-Mail-Adresse von Benutzer „$1“ gesandt.\nBitte melde dich damit an, sobald du es erhalten hast. Das alte Passwort bleibt weiterhin gültig.",
-       "blocked-mailpassword": "Die von dir verwendete IP-Adresse ist für das Ändern von Seiten gesperrt. Um einen Missbrauch zu verhindern, wurde die Möglichkeit zur Anforderung eines neuen Passwortes ebenfalls gesperrt.",
+       "blocked-mailpassword": "Deine IP-Adresse ist für das Bearbeiten gesperrt. Um Missbrauch zu vermeiden, ist die Verwendung der Passwortzurücksetzung von dieser IP-Adresse nicht erlaubt.",
        "eauthentsent": "Eine Bestätigungs-E-Mail wurde an die angegebene Adresse verschickt.\n\nBevor eine E-Mail von anderen Benutzern über die E-Mail-Funktion empfangen werden kann, muss die Adresse und ihre tatsächliche Zugehörigkeit zu diesem Benutzerkonto erst bestätigt werden. Bitte befolge die Hinweise in der Bestätigungs-E-Mail.",
        "throttled-mailpassword": "Es wurde innerhalb der letzten {{PLURAL:$1|Stunde|$1 Stunden}} bereits eine Passwortzurücksetzungs-E-Mail angefordert. Um einen Missbrauch der Funktion zu verhindern, kann nur {{PLURAL:$1|einmal pro Stunde|alle $1 Stunden}} eine Passwortzurücksetzungs-E-Mail angefordert werden.",
        "mailerror": "Fehler beim Senden der E-Mail: $1",
        "botpasswords-insert-failed": "Der Botname „$1“ konnte nicht hinzugefügt werden. Wurde er bereits hinzugefügt?",
        "botpasswords-update-failed": "Der Botname „$1“ konnte nicht aktualisiert werden. Wurde er gelöscht?",
        "botpasswords-created-title": "Botpasswort erstellt",
-       "botpasswords-created-body": "Das Botpasswort „$1“ wurde erstellt.",
+       "botpasswords-created-body": "Das Botpasswort für den Botnamen „$1“ des Benutzers „$2“ wurde erstellt.",
        "botpasswords-updated-title": "Botpasswort aktualisiert",
-       "botpasswords-updated-body": "Das Botpasswort „$1“ wurde aktualisiert.",
+       "botpasswords-updated-body": "Das Botpasswort für den Botnamen „$1“ des Benutzers „$2“ wurde aktualisiert.",
        "botpasswords-deleted-title": "Botpasswort gelöscht",
-       "botpasswords-deleted-body": "Das Botpasswort „$1“ wurde gelöscht.",
+       "botpasswords-deleted-body": "Das Botpasswort für den Botnamen „$1“ des Benutzers „$2“ wurde gelöscht.",
        "botpasswords-newpassword": "Das neue Passwort zur Anmeldung mit <strong>$1</strong> ist <strong>$2</strong>. <em>Bitte halte dies für die Zukunft fest.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider ist nicht verfügbar.",
        "botpasswords-restriction-failed": "Beschränkungen des Botpassworts verhindern diese Anmeldung.",
        "resetpass-validity-soft": "Dein Passwort ist nicht gültig: $1\n\nBitte wähle jetzt ein neues Passwort oder klicke auf „{{int:resetpass-submit-cancel}}“, um es später zurückzusetzen.",
        "passwordreset": "Passwort zurücksetzen",
        "passwordreset-text-one": "Fülle dieses Formular aus, um ein temporäres Passwort per E-Mail zu erhalten.",
-       "passwordreset-text-many": "{{PLURAL:$1|Füll eines der Felder aus, um ein temporäres Passwort per E-Mail zugesandt zu bekommen.}}",
+       "passwordreset-text-many": "{{PLURAL:$1|Fülle eines der Felder aus, um ein temporäres Passwort per E-Mail zugesandt zu bekommen.}}",
        "passwordreset-disabled": "Das Zurücksetzen von Passwörtern wurde in diesem Wiki deaktiviert.",
        "passwordreset-emaildisabled": "Die E-Mail-Funktionen wurden auf diesem Wiki deaktiviert.",
        "passwordreset-username": "Benutzername:",
        "recentchangeslinked-page": "Seite:",
        "recentchangeslinked-to": "Zeige nur Änderungen an Seiten, die auf diese Seite verlinken",
        "recentchanges-page-added-to-category": "[[:$1]] zur Kategorie hinzugefügt",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] und {{PLURAL:$2|eine weitere Seite|$2 weitere Seiten}} zur Kategorie hinzugefügt",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] und [[Special:WhatLinksHere/$1|{{PLURAL:$2|eine weitere Seite|$2 weitere Seiten}}]] zur Kategorie hinzugefügt",
        "recentchanges-page-removed-from-category": "[[:$1]] von der Kategorie entfernt",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] und {{PLURAL:$2|eine weitere Seite|$2 weitere Seiten}} von der Kategorie entfernt",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] und [[Special:WhatLinksHere/$1|{{PLURAL:$2|eine weitere Seite|$2 weitere Seiten}}]] von der Kategorie entfernt",
        "autochange-username": "Automatische MediaWiki-Änderung",
        "upload": "Datei hochladen",
        "uploadbtn": "Datei hochladen",
        "uploadstash-badtoken": "Das Entfernen der vorab gespeicherten Dateien ist fehlgeschlagen, da vielleicht deine Sitzungsdaten abgelaufen sind. Bitte versuche es erneut.",
        "uploadstash-errclear": "Das Entfernen der vorab gespeicherten Dateien ist fehlgeschlagen.",
        "uploadstash-refresh": "Liste der Dateien aktualisieren",
+       "uploadstash-thumbnail": "Vorschaubild ansehen",
        "invalid-chunk-offset": "Ungültiger Startpunkt",
        "img-auth-accessdenied": "Zugriff verweigert",
        "img-auth-nopathinfo": "Die Angabe PATH_INFO fehlt.\nDer Server ist nicht dafür eingerichtet, diese Information weiterzugeben.\nSie könnte CGI-gestützt sein und kann daher „img_auth“ (Authentifizierung des Dateiaufrufs) nicht unterstützen.\nSiehe auch https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization (englisch).",
        "changecontentmodel-title-label": "Seitentitel",
        "changecontentmodel-model-label": "Neues Inhaltsmodell",
        "changecontentmodel-reason-label": "Grund:",
+       "changecontentmodel-submit": "Ändern",
        "changecontentmodel-success-title": "Das Inhaltsmodell wurde geändert",
        "changecontentmodel-success-text": "Der Inhaltstyp von [[:$1]] wurde geändert.",
        "changecontentmodel-cannot-convert": "Der Inhalt von [[:$1]] kann nicht zum Typ $2 konvertiert werden.",
        "ipb-unblock": "IP-Adresse/Benutzer freigeben",
        "ipb-blocklist": "Alle aktuellen Sperren anzeigen",
        "ipb-blocklist-contribs": "Benutzerbeiträge von „{{GENDER:$1|$1}}“",
+       "ipb-blocklist-duration-left": "noch $1",
        "unblockip": "Benutzer freigeben",
        "unblockiptext": "Mit diesem Formular kannst du eine IP-Adresse oder einen Benutzer freigeben.",
        "ipusubmit": "Freigeben",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|Version|Versionen}} importiert",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|Version|Versionen}} von $2 importiert",
        "javascripttest": "JavaScript-Test",
-       "javascripttest-pagetext-noframework": "Diese Seite ist JavaScript-Tests vorbehalten.",
-       "javascripttest-pagetext-unknownframework": "Unbekanntes Framework „$1“.",
        "javascripttest-pagetext-unknownaction": "Unbekannte Aktion „$1“.",
-       "javascripttest-pagetext-frameworks": "Bitte wähle eine der folgenden Prüfumgebungen aus: $1",
-       "javascripttest-pagetext-skins": "Wähle eine Benutzeroberfläche zur Durchführung der Tests aus:",
        "javascripttest-qunit-intro": "Siehe die [$1 Dokumentation zu Tests] auf mediawiki.org",
        "tooltip-pt-userpage": "{{GENDER:|Deine}} Benutzerseite",
        "tooltip-pt-anonuserpage": "Benutzerseite der IP-Adresse von der aus du Änderungen durchführst",
        "version-libraries-description": "Beschreibung",
        "version-libraries-authors": "Autoren",
        "redirect": "Weiterleitung auf Benutzerseite, Seite, Seitenversion, Datei oder Logbucheintrag",
-       "redirect-legend": "Weiterleitung auf eine Benutzerseite, Seite, Seitenversion, Datei oder einen Logbucheintrag",
        "redirect-summary": "Diese Spezialseite leitet auf eine Benutzerseite (numerische Benutzerkennung angegeben), Seite (Seitenkennung angegeben), Seitenversion (Versionskennung angegeben), Datei (Dateiname angegeben) oder einen Logbucheintrag (Logbuchkennung angegeben) weiter. Benutzung: [[{{#Special:Redirect}}/user/101]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/file/Example.jpg]] oder [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Los",
        "redirect-lookup": "Suchen:",
        "blankpage": "Leere Seite",
        "intentionallyblankpage": "Diese Seite enthält absichtlich keinen Inhalt.",
        "external_image_whitelist": " #Diese Zeile nicht verändern.<pre>\n#Untenstehend können Fragmente regulärer Ausdrücke (der Teil zwischen den //) eingegeben werden.\n#Diese werden mit den URLs von Bildern aus externen Quellen verglichen.\n#Ein positiver Vergleich führt zur Anzeige des Bildes, andernfalls wird das Bild nur als Link angezeigt.\n#Zeilen, die mit einem # beginnen, werden als Kommentar behandelt.\n#Es wird nicht zwischen Groß- und Kleinschreibung unterschieden.\n\n#Fragmente regulärer Ausdrücke nach dieser Zeile eintragen. Diese Zeile nicht verändern.</pre>",
-       "tags": "Gültige Änderungsmarkierungen",
+       "tags": "Änderungsmarkierungen",
        "tag-filter": "[[Special:Tags|Markierungs]]-Filter:",
        "tag-filter-submit": "Filter",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Markierung|Markierungen}}]]: $2)",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|schützte}} die Seite $3 $4 [kaskadierend]",
        "logentry-protect-modify": "$1 {{GENDER:$2|änderte}} den Schutzstatus der Seite $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|änderte}} den Schutzstatus der Seite $3 $4 [kaskadierend]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|änderte}} die Gruppenzugehörigkeit für $3 von $4 zu $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|änderte}} die Gruppenzugehörigkeit für {{GENDER:$3|$3}} von $4 zu $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|änderte}} die Gruppenzugehörigkeit für $3",
        "logentry-rights-autopromote": "$1 wurde automatisch von $4 zu $5 {{GENDER:$2|zugeordnet}}",
        "logentry-upload-upload": "$1 {{GENDER:$2|lud}} $3 hoch",
        "api-error-unknownerror": "Unbekannter Fehler: „$1“",
        "api-error-uploaddisabled": "Das Hochladen ist in diesem Wiki deaktiviert.",
        "api-error-verification-error": "Die hochzuladende Datei ist entweder fehlerhaft oder hat keine Dateinamenserweiterung.",
+       "api-error-was-deleted": "Eine Datei mit diesem Namen wurde kürzlich hochgeladen und anschließend gelöscht.",
        "duration-seconds": "$1 {{PLURAL:$1|Sekunde|Sekunden}}",
        "duration-minutes": "$1 {{PLURAL:$1|Minute|Minuten}}",
        "duration-hours": "$1 {{PLURAL:$1|Stunde|Stunden}}",
        "special-characters-group-ipa": "Internationales Phonetisches Alphabet (IPA)",
        "special-characters-group-symbols": "Symbole",
        "special-characters-group-greek": "Griechisch",
+       "special-characters-group-greekextended": "Erweitertes Griechisch",
        "special-characters-group-cyrillic": "Kyrillisch",
        "special-characters-group-arabic": "Arabisch",
        "special-characters-group-arabicextended": "Arabisch, erweitert",
        "sessionprovider-generic": "$1-Sitzungen",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookiebasierten Sitzungen",
        "sessionprovider-nocookies": "Cookies sind eventuell deaktiviert. Stelle sicher, dass Cookies aktiviert sind und versuche es erneut.",
-       "randomrootpage": "Zufällige Stammseite"
+       "randomrootpage": "Zufällige Stammseite",
+       "log-action-filter-block": "Sperrtyp:",
+       "log-action-filter-delete": "Löschtyp:",
+       "log-action-filter-patrol": "Kontrolltyp:",
+       "log-action-filter-protect": "Schutztyp:",
+       "log-action-filter-upload": "Hochladetyp:",
+       "log-action-filter-all": "Alle",
+       "log-action-filter-block-block": "Sperren",
+       "log-action-filter-block-reblock": "Sperrveränderung",
+       "log-action-filter-block-unblock": "Freigaben",
+       "log-action-filter-delete-delete": "Seitenlöschung",
+       "log-action-filter-delete-restore": "Seitenwiederherstellung",
+       "log-action-filter-delete-event": "Logbucheintrag-Löschung",
+       "log-action-filter-delete-revision": "Versionslöschung",
+       "log-action-filter-patrol-patrol": "Manuelle Kontrolle",
+       "log-action-filter-patrol-autopatrol": "Automatische Kontrolle",
+       "log-action-filter-protect-protect": "Schutz",
+       "log-action-filter-protect-modify": "Schutzveränderung",
+       "log-action-filter-protect-unprotect": "Freigaben",
+       "log-action-filter-upload-upload": "Neue Hochladung",
+       "log-action-filter-upload-overwrite": "Wiederhochladung"
 }
index 4625c89..059ce8b 100644 (file)
        "newarticle": "(Newe)",
        "newarticletext": "To yew gıre tıkna be ra yew pela ke hewna çıniya.\nSeba afernayışê pele ra, qutiya metnê cêrêni bıgurene (seba melumati qaytê [$1 pela peşti] ke).\nEke be ğeletine ameya tiya, wa gocega <strong>peyser</strong>i programê xo de bıtıkne.",
        "anontalkpagetext": "----''No pel, pel o karbero hesab a nêkerdeyan o, ya zi karbero hesab akerdeyan o labele pê hesabê xo nêkewto de. No sebeb ra ma IP adres şuxulneni û ney IP adresan herkes eşkeno bıvino. Eke şıma qayil niye ina bo xo ri [[Special:UserLogin/signup|yew hesab bıvıraze]] veyaxut [[Special:UserLogin|hesab akere]].''",
-       "noarticletext": "Ena pele de hewna theba çıniyo.\nTı şenay zerreyê pelanê binan de [[Special:Search/{{PAGENAME}}|seba sernameyê ena pele cı geyre]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} qeydan miyan de cı geyre],\nya zi [{{fullurl:{{FULLPAGENAME}}|action=edit}} ena pele bıvurne]</span>.",
+       "noarticletext": "Ena pele de hewna theba çıniyo.\nTı şenay zerreyê pelanê binan de [[Special:Search/{{PAGENAME}}|seba sernameyê ena pele cı geyre]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} qeydan miyan de cı geyre],\nya zi [{{fullurl:{{FULLPAGENAME}}|action=edit}} ena pele vıraze]</span>.",
        "noarticletext-nopermission": "Ena pele de hewna theba çıniyo.\nTı şenay zerreyê pelanê binan de [[Special:Search/{{PAGENAME}}|seba sernameyê na pele cı geyre]], ya zi <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} qeydan miyan de cı geyre]</span>, ema destur çıniyo ke na pele vırazê.",
        "missing-revision": "Rewizyonê name dê pela da #$1 \"{{FULLPAGENAME}}\" dı çıniyo.\n\nNo normal de tarix dê pelanê besterneyan dı ena xırabin asena.\nDetayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} tiya dı] aseno.",
        "userpage-userdoesnotexist": "Hesabê karberi \"<nowiki>$1</nowiki>\" qeyd nêbiyo.\nKerem ke, tı ke wazenay na pele bafernê/bıvurnê, qontrol ke.",
index 16d8c33..0141f08 100644 (file)
@@ -45,7 +45,8 @@
                        "Stam.nikos",
                        "Giorgos456",
                        "SucreRouge",
-                       "Gts-tg"
+                       "Gts-tg",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Υπογράμμιση συνδέσμων:",
        "recentchangeslinked-page": "Όνομα σελίδας:",
        "recentchangeslinked-to": "Εμφάνιση αλλαγών σε σελίδες συνδεδεμένες με την δεδομένη σελίδα αντί αυτής",
        "recentchanges-page-added-to-category": "Η σελίδα [[:$1]] προστέθηκε στην κατηγορία",
-       "recentchanges-page-added-to-category-bundled": "Η σελίδα [[:$1]] και {{PLURAL:$2|μία ακόμα σελίδα|$2 ακόμα σελίδες}} προστέθηκαν στην κατηγορία",
+       "recentchanges-page-added-to-category-bundled": "Η σελίδα [[:$1]] και [[Special:WhatLinksHere/$1|{{PLURAL:$2|μία ακόμα σελίδα|$2 ακόμα σελίδες}}]] προστέθηκαν στην κατηγορία",
        "recentchanges-page-removed-from-category": "Η σελίδα [[:$1]] αφαιρέθηκε από την κατηγορία",
        "recentchanges-page-removed-from-category-bundled": "Η σελίδα [[:$1]] και {{PLURAL:$2|μία ακόμα σελίδα|$2 ακόμα σελίδες}} αφαιρέθηκαν από την κατηγορία",
        "autochange-username": "Αυτόματη αλλαγή MediaWiki",
index 5526e2e..6449c61 100644 (file)
        "noemail": "There is no email address recorded for user \"$1\".",
        "noemailcreate": "You need to provide a valid email address.",
        "passwordsent": "A new password has been sent to the email address registered for \"$1\".\nPlease log in again after you receive it.",
-       "blocked-mailpassword": "Your IP address is blocked from editing, and so is not allowed to use the password recovery function to prevent abuse.",
+       "blocked-mailpassword": "Your IP address is blocked from editing. To prevent abuse, it is not allowed to use password recovery from this IP address.",
        "eauthentsent": "A confirmation email has been sent to the specified email address.\nBefore any other email is sent to the account, you will have to follow the instructions in the email, to confirm that the account is actually yours.",
        "throttled-mailpassword": "A password reset email has already been sent, within the last {{PLURAL:$1|hour|$1 hours}}.\nTo prevent abuse, only one password reset email will be sent per {{PLURAL:$1|hour|$1 hours}}.",
        "signupstart": "",
        "botpasswords-insert-failed": "Failed to add bot name \"$1\". Was it already added?",
        "botpasswords-update-failed": "Failed to update bot name \"$1\". Was it deleted?",
        "botpasswords-created-title": "Bot password created",
-       "botpasswords-created-body": "The bot password \"$1\" was created.",
+       "botpasswords-created-body": "The bot password for bot name \"$1\" of user \"$2\" was created.",
        "botpasswords-updated-title": "Bot password updated",
-       "botpasswords-updated-body": "The bot password \"$1\" was updated.",
+       "botpasswords-updated-body": "The bot password for bot name \"$1\" of user \"$2\" was updated.",
        "botpasswords-deleted-title": "Bot password deleted",
-       "botpasswords-deleted-body": "The bot password \"$1\" was deleted.",
+       "botpasswords-deleted-body": "The bot password for bot name \"$1\" of user \"$2\" was deleted.",
        "botpasswords-newpassword": "The new password to log in with <strong>$1</strong> is <strong>$2</strong>. <em>Please record this for future reference.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider is not available.",
        "botpasswords-restriction-failed": "Bot password restrictions prevent this login.",
        "recentchangeslinked-page": "Page name:",
        "recentchangeslinked-to": "Show changes to pages linked to the given page instead",
        "recentchanges-page-added-to-category": "[[:$1]] added to category",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] and {{PLURAL:$2|one page|$2 pages}} added to category",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] and [[Special:WhatLinksHere/$1|{{PLURAL:$2|one page|$2 pages}}]] added to category",
        "recentchanges-page-removed-from-category": "[[:$1]] removed from category",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] and {{PLURAL:$2|one page|$2 pages}} removed from category",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] and [[Special:WhatLinksHere/$1|{{PLURAL:$2|one page|$2 pages}}]] removed from category",
        "autochange-username": "MediaWiki automatic change",
        "upload": "Upload file",
        "uploadbtn": "Upload file",
        "uploadstash-summary": "This page provides access to files that are uploaded or in the process of uploading, but are not yet published to the wiki. These files are not visible to anyone but the user who uploaded them.",
        "uploadstash-clear": "Clear stashed files",
        "uploadstash-nofiles": "You have no stashed files.",
-       "uploadstash-badtoken": "Performing that action failed. Perhaps because your editing credentials expired. Please try again.",
+       "uploadstash-badtoken": "Performing that action failed, perhaps because your editing credentials expired. Please try again.",
        "uploadstash-errclear": "Clearing the files failed.",
        "uploadstash-refresh": "Refresh the list of files",
+       "uploadstash-thumbnail": "view thumbnail",
        "invalid-chunk-offset": "Invalid chunk offset",
        "img-auth-accessdenied": "Access denied",
        "img-auth-nopathinfo": "Missing PATH_INFO.\nYour server is not set up to pass this information.\nIt may be CGI-based and cannot support img_auth.\nSee https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "changecontentmodel-title-label": "Page title",
        "changecontentmodel-model-label": "New content model",
        "changecontentmodel-reason-label": "Reason:",
+       "changecontentmodel-submit": "Change",
        "changecontentmodel-success-title": "The content model was changed",
        "changecontentmodel-success-text": "The content type of [[:$1]] has been changed.",
        "changecontentmodel-cannot-convert": "The content on [[:$1]] cannot be converted to a type of $2.",
        "unblock-summary": "",
        "blockip": "Block {{GENDER:$1|user}}",
        "blockip-legend": "Block user",
-       "blockiptext": "Use the form below to block write access from a specific IP address or username.\nThis should be done only to prevent vandalism, and in accordance with [[{{MediaWiki:Policy-url}}|policy]].\nFill in a specific reason below (for example, citing particular pages that were vandalized).\nYou can block IP ranges using the [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR] syntax; the largest allowed range is /$1 for IPv4 and /$2 for IPv6.",
+       "blockiptext": "Use the form below to block write access from a specific IP address or username.\nThis should be done only to prevent vandalism, and in accordance with [[{{MediaWiki:Policy-url}}|policy]].\nFill in a specific reason below (for example, citing particular pages that were vandalized).\nYou can block IP address ranges using the [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR] syntax; the largest allowed range is /$1 for IPv4 and /$2 for IPv6.",
        "ipaddressorusername": "IP address or username:",
        "ipbexpiry": "Expiration:",
        "ipbreason": "Reason:",
        "ipb-unblock": "Unblock a username or IP address",
        "ipb-blocklist": "View existing blocks",
        "ipb-blocklist-contribs": "Contributions for {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 left",
        "unblockip": "Unblock user",
        "unblockiptext": "Use the form below to restore write access to a previously blocked IP address or username.",
        "ipusubmit": "Remove this block",
        "unblock-hideuser": "You cannot unblock this user, as their username has been hidden.",
        "ipb_cant_unblock": "Error: Block ID $1 not found. It may have been unblocked already.",
        "ipb_blocked_as_range": "Error: The IP address $1 is not blocked directly and cannot be unblocked.\nIt is, however, blocked as part of the range $2, which can be unblocked.",
-       "ip_range_invalid": "Invalid IP range.",
+       "ip_range_invalid": "Invalid IP address range.",
        "ip_range_toolarge": "Range blocks larger than /$1 are not allowed.",
        "proxyblocker": "Proxy blocker",
        "proxyblockreason": "Your IP address has been blocked because it is an open proxy.\nPlease contact your Internet service provider or technical support of your organization and inform them of this serious security problem.",
        "import-logentry-interwiki": "transwikied $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revision|revisions}} imported from $2",
        "javascripttest": "JavaScript testing",
-       "javascripttest-backlink": "< $1",
-       "javascripttest-title": "$1",
-       "javascripttest-pagetext-noframework": "This page is reserved for running JavaScript tests.",
-       "javascripttest-pagetext-unknownframework": "Unknown testing framework \"$1\".",
        "javascripttest-pagetext-unknownaction": "Unknown action \"$1\".",
-       "javascripttest-pagetext-frameworks": "Please choose one of the following testing frameworks: $1",
-       "javascripttest-pagetext-skins": "Choose a skin to run the tests with:",
-       "javascripttest-qunit-name": "QUnit",
        "javascripttest-qunit-intro": "See [$1 testing documentation] on mediawiki.org.",
        "accesskey-pt-userpage": ".",
        "accesskey-pt-anonuserpage": ".",
        "version-libraries-description": "Description",
        "version-libraries-authors": "Authors",
        "redirect": "Redirect by file, user, page, revision, or log ID",
-       "redirect-legend": "Redirect to a file or page",
        "redirect-text": "",
        "redirect-summary": "This special page redirects to a file (given the filename), a page (given a revision ID or page ID), a user page (given a numeric user ID), or a log entry (given the log ID). Usage: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], or [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Go",
        "redirect-not-exists": "Value not found",
        "fileduplicatesearch": "Search for duplicate files",
        "fileduplicatesearch-summary": "Search for duplicate files based on hash values.",
-       "fileduplicatesearch-legend": "Search for a duplicate",
        "fileduplicatesearch-filename": "Filename:",
        "fileduplicatesearch-submit": "Search",
        "fileduplicatesearch-info": "$1 × $2 pixel<br />File size: $3<br />MIME type: $4",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|protected}} $3 $4 [cascading]",
        "logentry-protect-modify": "$1 {{GENDER:$2|changed}} protection level for $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|changed}} protection level for $3 $4 [cascading]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|changed}} group membership for $3 from $4 to $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|changed}} group membership for {{GENDER:$3|$3}} from $4 to $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|changed}} group membership for $3",
        "logentry-rights-autopromote": "$1 was automatically {{GENDER:$2|promoted}} from $4 to $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|uploaded}} $3",
        "api-error-unknownerror": "Unknown error: \"$1\".",
        "api-error-uploaddisabled": "Uploading is disabled on this wiki.",
        "api-error-verification-error": "This file might be corrupt, or have the wrong extension.",
+       "api-error-was-deleted": "A file of this name has been previously uploaded and subsequently deleted.",
        "duration-seconds": "$1 {{PLURAL:$1|second|seconds}}",
        "duration-minutes": "$1 {{PLURAL:$1|minute|minutes}}",
        "duration-hours": "$1 {{PLURAL:$1|hour|hours}}",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "Symbols",
        "special-characters-group-greek": "Greek",
+       "special-characters-group-greekextended": "Greek extended",
        "special-characters-group-cyrillic": "Cyrillic",
        "special-characters-group-arabic": "Arabic",
        "special-characters-group-arabicextended": "Arabic extended",
        "sessionprovider-generic": "$1 sessions",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookie-based sessions",
        "sessionprovider-nocookies": "Cookies may be disabled. Ensure you have cookies enabled and start again.",
-       "randomrootpage": "Random root page"
+       "randomrootpage": "Random root page",
+       "log-action-filter-block": "Type of block:",
+       "log-action-filter-contentmodel": "Type of contentmodel modification:",
+       "log-action-filter-delete": "Type of deletion:",
+       "log-action-filter-import": "Type of import:",
+       "log-action-filter-managetags": "Type of tag management action:",
+       "log-action-filter-move": "Type of move:",
+       "log-action-filter-newusers": "Type of account creation:",
+       "log-action-filter-patrol": "Type of patrol:",
+       "log-action-filter-protect": "Type of protection:",
+       "log-action-filter-rights": "Type of right change",
+       "log-action-filter-suppress": "Type of suppression",
+       "log-action-filter-upload": "Type of upload:",
+       "log-action-filter-all": "All",
+       "log-action-filter-block-block": "Block",
+       "log-action-filter-block-reblock": "Block modification",
+       "log-action-filter-block-unblock": "Unblock",
+       "log-action-filter-contentmodel-change": "Change of Contentmodel",
+       "log-action-filter-contentmodel-new": "Creation of page with non-standard Contentmodel",
+       "log-action-filter-delete-delete": "Page deletion",
+       "log-action-filter-delete-restore": "Page undeletion",
+       "log-action-filter-delete-event": "Log deletion",
+       "log-action-filter-delete-revision": "Revision deletion",
+       "log-action-filter-import-interwiki": "Transwiki import",
+       "log-action-filter-import-upload": "Import by XML upload",
+       "log-action-filter-managetags-create": "Tag creation",
+       "log-action-filter-managetags-delete": "Tag deletion",
+       "log-action-filter-managetags-activate": "Tag activation",
+       "log-action-filter-managetags-deactivate": "Tag deactivation",
+       "log-action-filter-move-move": "Move without overwriting of redirects",
+       "log-action-filter-move-move_redir": "Move with overwriting of redirects",
+       "log-action-filter-newusers-create": "Creation by anonymous user",
+       "log-action-filter-newusers-create2": "Creation by registered user",
+       "log-action-filter-newusers-autocreate": "Automatic creation",
+       "log-action-filter-newusers-byemail": "Creation with password sent by e-mail",
+       "log-action-filter-patrol-patrol": "Manual patrol",
+       "log-action-filter-patrol-autopatrol": "Automatic patrol",
+       "log-action-filter-protect-protect": "Protection",
+       "log-action-filter-protect-modify": "Protection modification",
+       "log-action-filter-protect-unprotect": "Unprotection",
+       "log-action-filter-protect-move_prot": "Moved protection",
+       "log-action-filter-rights-rights": "Manual change",
+       "log-action-filter-rights-autopromote": "Automatic change",
+       "log-action-filter-suppress-event": "Log suppression",
+       "log-action-filter-suppress-revision": "Revision suppression",
+       "log-action-filter-suppress-delete": "Page suppression",
+       "log-action-filter-suppress-block": "User supppression by block",
+       "log-action-filter-suppress-reblock": "User suppression by reblock",
+       "log-action-filter-upload-upload": "New upload",
+       "log-action-filter-upload-overwrite": "Reupload"
 }
index 148f851..2a819ea 100644 (file)
        "thursday": "ĵaŭdo",
        "friday": "vendredo",
        "saturday": "sabato",
-       "sun": "Dim",
-       "mon": "Lun",
-       "tue": "Mar",
+       "sun": "dim",
+       "mon": "lun",
+       "tue": "mar",
        "wed": "Mer",
        "thu": "Ĵaŭ",
        "fri": "Ven",
-       "sat": "Sab",
+       "sat": "sab",
        "january": "januaro",
        "february": "februaro",
        "march": "marto",
        "october-gen": "oktobro",
        "november-gen": "novembro",
        "december-gen": "decembro",
-       "jan": "Jan",
-       "feb": "Feb",
-       "mar": "Mar",
-       "apr": "Apr",
-       "may": "Maj",
-       "jun": "Jun",
-       "jul": "Jul",
-       "aug": "Aŭg",
-       "sep": "Sep",
-       "oct": "Okt",
-       "nov": "Nov",
-       "dec": "Dec",
+       "jan": "jan",
+       "feb": "feb",
+       "mar": "mar",
+       "apr": "apr",
+       "may": "maj",
+       "jun": "jun",
+       "jul": "jul",
+       "aug": "aŭg",
+       "sep": "sep",
+       "oct": "okt",
+       "nov": "nov",
+       "dec": "dec",
        "january-date": "$1-a de januaro",
        "february-date": "$1-a de februaro",
        "march-date": "$1-a de marto",
        "anontalk": "Diskuto",
        "navigation": "Navigado",
        "and": "&#32;kaj",
-       "qbfind": "Trovi",
+       "qbfind": "Serĉi",
        "qbbrowse": "Foliumi",
        "qbedit": "Redakti",
        "qbpageoptions": "Ĉi tiu paĝo",
        "search": "Serĉi",
        "searchbutton": "Serĉi",
        "go": "Ek!",
-       "searcharticle": "Ek!",
+       "searcharticle": "Ek",
        "history": "Historio de versioj",
        "history_short": "Historio",
        "updatedmarker": "ĝisdatigita de post mia lasta vizito",
        "unprotectthispage": "Ŝanĝi protektadon de ĉi tiu paĝo",
        "newpage": "Nova paĝo",
        "talkpage": "Diskuti la paĝon",
-       "talkpagelinktext": "Diskuto",
+       "talkpagelinktext": "diskuto",
        "specialpage": "Speciala Paĝo",
        "personaltools": "Personaj iloj",
        "articlepage": "Rigardi artikolon",
        "copyrightpage": "{{ns:project}}:Aŭtorrajto",
        "currentevents": "Aktualaĵoj",
        "currentevents-url": "Project:Aktualaĵoj",
-       "disclaimers": "Malgarantio",
+       "disclaimers": "Malgarantioj",
        "disclaimerpage": "Project:Malgarantia paĝo",
        "edithelp": "Helpo pri redaktado",
        "helppage-top-gethelp": "Helpo",
        "createacct-yourpasswordagain": "Konfirmu pasvorton",
        "createacct-yourpasswordagain-ph": "Retajpu pasvorton",
        "remembermypassword": "Memori mian ensalutadon ĉe ĉi tiu komputilo (daŭrante maksimume $1 {{PLURAL:$1|tagon|tagojn}})",
-       "userlogin-remembermypassword": "Memoru mian ensaluton",
+       "userlogin-remembermypassword": "Memori mian ensaluton",
        "userlogin-signwithsecure": "Uzu sekurigitan konekton",
        "cannotloginnow-title": "Nuntempe ne eblas ensaluti",
        "cannotloginnow-text": "Ne eblas ensaluti dum uzado de $1.",
        "userlogin-joinproject": "Aliĝu al {{SITENAME}}",
        "nologin": "Ĉu vi ne havas konton? $1.",
        "nologinlink": "Krei konton",
-       "createaccount": "Krei novan konton",
+       "createaccount": "Krei konton",
        "gotaccount": "Ĉu vi jam havas konton? '''$1'''.",
        "gotaccountlink": "Ensaluti",
        "userlogin-resetlink": "Ĉu vi forgesis ensalutajn detalojn?",
        "nocookieslogin": "{{SITENAME}} uzas kuketojn por akcepti uzantojn. Kuketoj esta malaktivigitaj ĉe vi. Bonvolu aktivigi ilin kaj provu denove.",
        "nocookiesfornew": "La uzantokonto ne estis kreita, ĉar ne konfirmeblas ĝia fonto. Certiginte ke kuketoj estas ebligitaj, reŝargu tiun ĉi paĝon kaj reprovu.",
        "noname": "Vi ne tajpis validan salutnomon.",
-       "loginsuccesstitle": "Ensalutado sukcesis",
+       "loginsuccesstitle": "Ensalutis",
        "loginsuccess": "Vi ensalutis ĉe {{SITENAME}} kiel uzanto \"$1\".",
        "nosuchuser": "Neniu uzanto havas nomon \"$1\".\nNomoj por uzantoj estas usklecodistingaj.\nKontrolu vian literumadon, aŭ [[Special:UserLogin/signup|kreu novan konton]].",
        "nosuchusershort": "Ne ekzistas uzanto kun la nomo \"$1\". Bonvolu kontroli vian ortografion.",
        "createacct-another-realname-tip": "La vera nomo estas nenecesa.\nSe vi decidas indiki ĝin, ĝi estos uzata por montri atribuadon de viaj kontribuoj.",
        "pt-login": "Ensaluti",
        "pt-login-button": "Ensaluti",
-       "pt-createaccount": "Krei novan konton",
+       "pt-createaccount": "Krei konton",
        "pt-userlogout": "Elsaluti",
        "php-mail-error-unknown": "Nekonata eraro en la funkcio mail() de PHP",
        "user-mail-no-addy": "Provis sendi retpoŝton sen retpoŝtadreso.",
        "botpasswords-label-resetpassword": "Rekomencigi la pasvorton",
        "botpasswords-label-restrictions": "Limigoj de uzado:",
        "botpasswords-bad-appid": "La robota nomo \"$1\" estas malvalida.",
+       "botpasswords-insert-failed": "Aldono de la robota nomo \"$1\" ne sukcesis. Ĉu ĝi jam estis aldonita?",
+       "botpasswords-update-failed": "Ĝisdatigo de la robota nomo \"$1\" ne sukcesis. Ĉu ĝi estis forigita?",
        "botpasswords-created-title": "Robota pasvorto kreita",
-       "botpasswords-created-body": "La robota pasvorto \"$1\" estis sukcese kreita.",
+       "botpasswords-created-body": "La robota pasvorto por robota nomo \"$1\" de la uzanto \"$2\" estis kreita.",
        "botpasswords-updated-title": "Robota pasvorto ĝisdatigita",
-       "botpasswords-updated-body": "La robota pasvorto \"$1\" estis sukcese ĝisdatigita.",
+       "botpasswords-updated-body": "La robota pasvorto por robota nomo \"$1\" de la uzanto \"$2\" estis ĝisdatigita.",
        "botpasswords-deleted-title": "Robota pasvorto forigita",
-       "botpasswords-deleted-body": "La robota pasvorto \"$1\" estis forigita.",
+       "botpasswords-deleted-body": "La robota pasvorto por robota nomo \"$1\" de la uzanto \"$2\" estis forigita.",
        "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",
        "bold_tip": "Grasa teksto",
        "italic_sample": "Kursiva teksto",
        "italic_tip": "Kursiva teksto",
-       "link_sample": "Ligtitolo",
+       "link_sample": "Titolo de la ligilo",
        "link_tip": "Interna ligilo",
        "extlink_sample": "http://www.example.com ligtitolo",
        "extlink_tip": "Ekstera ligilo (memoru http:// prefikson)",
        "mergehistory-empty": "Neniuj versioj estas kunigeblaj.",
        "mergehistory-done": "$3 {{PLURAL:$3|versio|versioj}} de $1 sukcese estis {{PLURAL:$3|kunigita|kunigitaj}} en [[:$2]].",
        "mergehistory-fail": "Ne povis fari la historian kunigon; bonvolu konstati la paĝajn kaj tempajn parametrojn.",
+       "mergehistory-fail-bad-timestamp": "Tempomarko estas malvalida.",
+       "mergehistory-fail-invalid-source": "Fonta paĝo estas malvalida.",
+       "mergehistory-fail-invalid-dest": "Cela paĝo estas malvalida.",
        "mergehistory-fail-toobig": "Ne eblas kunigi historiojn ĉar pli ol sojlo de $1 {{PLURAL:$1|revizio|revizioj}} estus {{PLURAL:$1|movita|movitaj}}.",
        "mergehistory-no-source": "Fontpaĝo $1 ne ekzistas.",
        "mergehistory-no-destination": "Celpaĝo $1 ne ekzistas.",
        "searchmenu-new": "<strong>Krei la paĝon \"[[:$1]]\" en ĉi tiu vikio!</strong>{{PLURAL:$2|0=|Vidu ankaŭ la paĝon trovitan per via serĉo.|Vidu ankaŭ la trovitajn serĉrezultojn.}}",
        "searchprofile-articles": "Enhavaj paĝoj",
        "searchprofile-images": "Plurmedio",
-       "searchprofile-everything": "Ĉio",
+       "searchprofile-everything": "Ĉion",
        "searchprofile-advanced": "Progresa",
        "searchprofile-articles-tooltip": "Serĉo en $1",
        "searchprofile-images-tooltip": "Serĉi dosierojn",
        "right-managechangetags": "Kreado kaj forigado de [[Special:Tags|etikedoj]] de datumbazo",
        "right-applychangetags": "Aldoni [[Special:Tags|etikedojn]] al propraj ŝanĝoj",
        "right-changetags": "Aldoni kaj forigi arbitrajn [[Special:Tags|etikedojn]] ĉe unuopaj revizioj kaj protokoleroj",
+       "grant-group-email": "Sendi retpoŝton",
+       "grant-createaccount": "Krei kontojn",
        "newuserlogpage": "Protokolo de uzanto-kreado",
        "newuserlogpagetext": "Jen protokolo de lastaj kreadoj de uzantoj.",
        "rightslog": "Protokolo de uzanto-rajtoj",
        "recentchanges-submit": "Montri",
        "rcnotefrom": "Malsupre estas la {{PLURAL:$5|ŝanĝo|ŝanĝoj}} ekde <strong>$3, $4</strong> (montrante ĝis <strong>$1</strong>).",
        "rclistfrom": "Montri novajn ŝanĝojn ekde \"$3 $2\"",
-       "rcshowhideminor": "$1 redaktetojn",
+       "rcshowhideminor": "$1 etajn redaktojn",
        "rcshowhideminor-show": "Montri",
        "rcshowhideminor-hide": "Kaŝi",
        "rcshowhidebots": "$1 robotojn",
        "rc-enhanced-expand": "Montri detalojn (per JavaScript)",
        "rc-enhanced-hide": "Kaŝi detalojn",
        "rc-old-title": "originale kreita kiel \"$1\"",
-       "recentchangeslinked": "Rilataj paĝoj",
+       "recentchangeslinked": "Rilataj ŝanĝoj",
        "recentchangeslinked-feed": "Rilataj paĝoj",
-       "recentchangeslinked-toolbox": "Rilataj paĝoj",
+       "recentchangeslinked-toolbox": "Rilataj ŝanĝoj",
        "recentchangeslinked-title": "Ŝanĝoj rilataj al \"$1\"",
        "recentchangeslinked-summary": "Jen listo de ŝanĝoj faritaj lastatempe al paĝoj ligitaj el specifa paĝo (aŭ al membroj de specifa kategorio).\nPaĝoj en [[Special:Watchlist|via atentaro]] estas '''grasaj'''.",
        "recentchangeslinked-page": "Nomo de paĝo:",
        "filehist-deleteone": "forigi",
        "filehist-revert": "restarigi",
        "filehist-current": "nuna",
-       "filehist-datetime": "Dato/Tempo",
+       "filehist-datetime": "Dato/tempo",
        "filehist-thumb": "Bildeto",
        "filehist-thumbtext": "Bildeto por versio ekde $1",
        "filehist-nothumb": "Neniu bildeto",
        "randomincategory-submit": "Ek!",
        "randomredirect": "Hazarda alidirekto",
        "randomredirect-nopages": "Estas neniuj alidirektiloj en la nomspaco \"$1\".",
-       "statistics": "Statistiko",
+       "statistics": "Statistikoj",
        "statistics-header-pages": "Paĝaj statistikoj",
        "statistics-header-edits": "Redaktaj statistikoj",
        "statistics-header-users": "Pri la uzantaro",
        "apisandbox-intro": "Uzu tiun ĉi paĝon por eksperimenti kun '''MediaWiki API'''.\nVidu [//www.mediawiki.org/wiki/API:Main_page la API-dokumentadon] por pli da detaloj pri la uzo de API. Ekz-e: [//www.mediawiki.org/wiki/API#A_simple_example atingi la enhavon de la Ĉefpaĝo]. Elektu agon por vidi pliajn ekzemplojn.\n\nNotu ke, kvankam ĉi tiu estas provejo, agoj kiun vi faros en ĉi tiu paĝo povas modifi la vikion.",
        "apisandbox-submit": "Fari mendon",
        "apisandbox-reset": "Nuligi",
-       "apisandbox-examples": "Ekzemplo",
-       "apisandbox-results": "Rezulto",
+       "apisandbox-examples": "Ekzemploj",
+       "apisandbox-dynamic-parameters": "Aldonaj parametroj",
+       "apisandbox-dynamic-parameters-add-label": "Aldoni parametron:",
+       "apisandbox-dynamic-parameters-add-placeholder": "Nomo de parametro",
+       "apisandbox-dynamic-error-exists": "Parametro nomata \"$1\" jam ekzistas.",
+       "apisandbox-results": "Rezultoj",
        "apisandbox-request-url-label": "Mendi URL-on.",
        "apisandbox-request-time": "Tempo de peto: $1",
-       "booksources": "Libroservoj",
+       "booksources": "Librofontoj",
        "booksources-search-legend": "Serĉi librofontojn",
        "booksources-search": "Serĉi",
        "booksources-text": "Jen ligilaro al aliaj TTT-ejoj, kiuj vendas librojn,\nkaj/aŭ informumos pri la libro ligita.\nLa {{SITENAME}} ne estas komerce ligita al tiuj vendejoj, kaj la listo ne estu\nkomprenata kiel rekomendo aŭ reklamo.",
        "log-title-wildcard": "Serĉi titolojn komencantajn kun ĉi tiu teksto",
        "showhideselectedlogentries": "Montri/kaŝi elektitajn protokolerojn",
        "log-edit-tags": "Redakti etikedojn ĉe elektitaj protokoleroj",
+       "checkbox-select": "Elektu: $1",
+       "checkbox-all": "Ĉiuj",
+       "checkbox-none": "Neniu",
+       "checkbox-invert": "Inversigi",
        "allpages": "Ĉiuj paĝoj",
        "nextpage": "Sekvanta paĝo ($1)",
        "prevpage": "Antaŭa paĝo ($1)",
        "allpagesto": "Montri paĝoj finante de:",
        "allarticles": "Ĉiuj paĝoj",
        "allinnamespace": "Ĉiuj paĝoj ($1 nomspaco)",
-       "allpagessubmit": "Ek!",
+       "allpagessubmit": "Ek",
        "allpagesprefix": "Montri paĝojn kun prefikso:",
        "allpagesbadtitle": "La donata paĝo estis nevalida aŭ havis interlingvan aŭ intervikian prefikson. Ĝi eble enhavas unu aŭ plurajn signojn kiu ne povas esti uzataj en titoloj.",
        "allpages-bad-ns": "{{SITENAME}} ne havas nomspacon \"$1\".",
        "rollbackfailed": "Malfaro malsukcesis",
        "cantrollback": "Ne povas restarigi antaŭan redakton; la redaktinto lasta estas la sola aŭtoro de la paĝo.",
        "alreadyrolled": "Ne povas restarigi la lastan redakton de [[:$1]] de la [[User:$2|$2]] ([[User talk:$2|diskuto]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\npro tio, ke oni intertempe redaktis aŭ restarigis la paĝon.\nLa lasta redaktinto estis [[User:$3|$3]] ([[User talk:$3|diskuto]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
-       "editcomment": "La resumo de la komento estis: <em>$1</em>.",
+       "editcomment": "La resumo de la redakto estis: <em>$1</em>.",
        "revertpage": "Malfaris redaktojn de [[Special:Contributions/$2|$2]] ([[User talk:$2|diskuto]]) al la lasta versio de [[User:$1|$1]]",
        "revertpage-nouser": "Restarigis redaktojn de (salutnomo forigita) al lasta revizio de {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Restaris redaktojn de $1; ŝanĝis al lasta versio de $2.",
        "sessionfailure": "Ŝajnas, ke estas problemo kun via ensalutado;\nĈi ago estis nuligita por malhelpi fiensalutadon.\nBonvolu alklaki la reirbutonon kaj reŝargi la paĝon el kiu vi venas, kaj provu denove.",
        "changecontentmodel-title-label": "Titolo de paĝo",
        "changecontentmodel-reason-label": "Kialo:",
+       "changecontentmodel-submit": "Ŝanĝi",
        "logentry-contentmodel-change-revertlink": "restarigi",
        "logentry-contentmodel-change-revert": "restarigi",
        "protectlogpage": "Protokolo pri protektoj",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|revizio importita|revizioj importitaj}}",
        "import-logentry-interwiki-detail": "Importis $1 {{PLURAL:$1|revizion|reviziojn}} de $2",
        "javascripttest": "Ĝavoskripta testado",
-       "javascripttest-pagetext-noframework": "Ĉi tiu paĝo estas konservita por funkciigi testojn de JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Nekonta test-framo \"$1\".",
        "javascripttest-pagetext-unknownaction": "Nekonata ago \"$1\".",
-       "javascripttest-pagetext-frameworks": "Bonvolu elekti unu el la jenaj test-framoj: $1",
-       "javascripttest-pagetext-skins": "Elektu kun kio etoso irigi la testojn:",
        "javascripttest-qunit-intro": "Vidu [$1 testa dokumentaro] en mediawiki.org.",
        "tooltip-pt-userpage": "Via uzantpaĝo",
        "tooltip-pt-anonuserpage": "La uzantopaĝo por la IP adreso sub kiu vi estas redaktanta",
        "tooltip-search": "Serĉi tra {{SITENAME}}",
        "tooltip-search-go": "Iru al paĝo kun ĉi preciza nomo se ĝi ekzistas",
        "tooltip-search-fulltext": "Serĉi la paĝojn por ĉi tiu teksto",
-       "tooltip-p-logo": "Ĉefpaĝo",
-       "tooltip-n-mainpage": "Viziti la Ä\88efpaĝon",
-       "tooltip-n-mainpage-description": "Iri al la ĉefpaĝon",
+       "tooltip-p-logo": "Viziti la ĉefpaĝon",
+       "tooltip-n-mainpage": "Viziti la Ä\89efpaĝon",
+       "tooltip-n-mainpage-description": "Viziti la ĉefpaĝon",
        "tooltip-n-portal": "Pri la projekto, kion vi povas fari, kie vi povas trovi ion",
        "tooltip-n-currentevents": "Trovi fonajn informojn pri nunaj eventoj",
        "tooltip-n-recentchanges": "Listo de la lastaj ŝanĝoj en la vikio.",
        "tooltip-t-contributions": "Listo de kontribuoj de {{GENDER:$1|ĉi tiu uzanto}}",
        "tooltip-t-emailuser": "Sendi retmesaĝon al tiu ĉi uzanto",
        "tooltip-t-info": "Pli da informo pri ĉi tiu paĝo",
-       "tooltip-t-upload": "Alŝuti bildojn aŭ dosierojn",
+       "tooltip-t-upload": "Alŝuti dosierojn",
        "tooltip-t-specialpages": "Listo de ĉiuj specialaj paĝoj",
        "tooltip-t-print": "Printebla versio de ĉi tiu paĝo",
        "tooltip-t-permalink": "Konstanta ligilo al ĉi versio de la paĝo",
        "tooltip-ca-nstab-mediawiki": "Rigardi la sisteman mesaĝon",
        "tooltip-ca-nstab-template": "Rigardi la ŝablonon",
        "tooltip-ca-nstab-help": "Rigardi la helppaĝon",
-       "tooltip-ca-nstab-category": "Vidu la paĝon de kategorioj",
+       "tooltip-ca-nstab-category": "Vidi la paĝon de la kategorio",
        "tooltip-minoredit": "Marki tiun ŝanĝon kiel etan",
        "tooltip-save": "Konservi viajn ŝanĝojn",
        "tooltip-preview": "Antaŭrigardi viajn ŝanĝojn. Bonvolu uzi tion antaŭ ol konservi ilin!",
        "version-libraries-description": "Priskribo",
        "version-libraries-authors": "Aŭtoroj",
        "redirect": "Alidirektilo laŭ dosiero, uzanto, paĝo aŭ identigilo de revizio.",
-       "redirect-legend": "Alidirektilo al dosiero aŭ paĝo",
        "redirect-summary": "Tiu ĉi paĝo alidirektas al dosiero (laŭ ĝia nomo), paĝo (laŭ ĝia revizio-numero aŭ paĝo-identigilo) aŭ al uzantopaĝo (laŭ numera uzanto-identigilo). Uzado: [[{{#Special:Redirect}}/file/Ekzemplo.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], aŭ [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Ek",
        "redirect-lookup": "Traserĉi:",
        "limitreport-expansiondepth": "Plej alta profundeco de etendo",
        "limitreport-expensivefunctioncount": "Nombro de kostaj sintaks-analizilaj funkcioj",
        "expandtemplates": "Ŝablonetendilo",
-       "expand_templates_intro": "Ĉi tiu speciala paĝo traktas tekston kaj ampleksigas ĉiujn ŝablonojn en ĝi rekursie.\nĜi ankaŭ ampleksigas sintaksajn funkciojn kiel\n<code><nowiki>{{</nowiki>#language:…}}</code> kaj variablojn kiel\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. Fakte preskaŭ iujn ajn en duoblaj krampoj.",
+       "expand_templates_intro": "Ĉi tiu speciala paĝo prenas tekston kaj rikure etendas ĉiujn ŝablonojn en ĝi.\nĜi etendas ankaŭ sintaksajn funkciojn kiel\n<code><nowiki>{{</nowiki>#language:…}}</code> kaj variablojn kiel\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nFakte, ĝi etendas preskaŭ ĉion en duoblaj krampoj.",
        "expand_templates_title": "Kunteksta titolo, por {{FULLPAGENAME}}, ktp.:",
        "expand_templates_input": "Enigita teksto:",
        "expand_templates_output": "Rezulto",
index e6f517a..4c215cc 100644 (file)
                        "YoViajo",
                        "Asierog",
                        "Mgpena",
-                       "Transonlohk"
+                       "Transonlohk",
+                       "Eloy"
                ]
        },
        "tog-underline": "Subrayar los enlaces:",
        "copyrightpage": "{{ns:project}}:Derechos de autor",
        "currentevents": "Actualidad",
        "currentevents-url": "Project:Actualidad",
-       "disclaimers": "Aviso legal",
-       "disclaimerpage": "Project:Limitación general de responsabilidad",
+       "disclaimers": "Descargos",
+       "disclaimerpage": "Project:Descargo general",
        "edithelp": "Ayuda de edición",
        "helppage-top-gethelp": "Ayuda",
        "mainpage": "Página principal",
        "nocookieslogin": "{{SITENAME}} utiliza <em>cookies</em> para la autenticación de usuarios. Las <em>cookies</em> están desactivadas en tu navegador. Por favor, actívalas e inténtalo de nuevo.",
        "nocookiesfornew": "No se pudo crear la cuenta de usuario, porque no pudimos confirmar su origen.\nAsegúrate de que tienes las cookies activadas, luego recarga esta página e inténtalo de nuevo.",
        "noname": "No se ha especificado un nombre de usuario válido.",
-       "loginsuccesstitle": "Has accedido correctamente",
+       "loginsuccesstitle": "Has accedido",
        "loginsuccess": "<strong>Has accedido a {{SITENAME}} como «$1».</strong>",
        "nosuchuser": "No existe ningún usuario llamado «$1».\nLos nombres de usuario son sensibles a las mayúsculas.\nRevisa tu ortografía, o [[Special:UserLogin/signup|crea una cuenta nueva]].",
        "nosuchusershort": "No existe ningún usuario llamado «$1». Comprueba que lo has escrito correctamente.",
        "noemail": "No hay una dirección de correo electrónico registrada para «$1».",
        "noemailcreate": "Necesitas proporcionar una dirección de correo electrónico válida.",
        "passwordsent": "Se ha enviado una nueva contraseña al correo electrónico de «$1».\nPor favor, identifícate de nuevo tras recibirla.",
-       "blocked-mailpassword": "Tu dirección IP está bloqueada, y no se te permite el uso de la función de recuperación de contraseñas para prevenir abusos.",
+       "blocked-mailpassword": "Tu dirección IP está bloqueada para editar. Para prevenir abusos, no se permite el uso de la función de recuperación de contraseñas desde esta dirección IP.",
        "eauthentsent": "Se ha enviado un correo electrónico de confirmación a la dirección especificada.\nAntes de que se envíe cualquier otro correo a la cuenta tienes que seguir las instrucciones enviadas en el mensaje para así confirmar que la dirección te pertenece.",
        "throttled-mailpassword": "Ya se ha enviado un recordatorio de contraseña en {{PLURAL:$1|la última hora|las últimas $1 horas}}.\nPara evitar los abusos, solo se enviará un recordatorio de contraseña cada {{PLURAL:$1|hora|$1 horas}}.",
        "mailerror": "Error al enviar el mensaje: $1",
        "botpasswords-label-delete": "Borrar",
        "botpasswords-label-resetpassword": "Restablecer la contraseña",
        "botpasswords-label-grants": "Permisos aplicables:",
+       "botpasswords-help-grants": "Cada concesión le da acceso a los permisos listados que el usuario ya posea. Véase la [[Special:ListGrants|lista de concesiones]] para más información.",
        "botpasswords-label-restrictions": "Restricciones de uso:",
        "botpasswords-label-grants-column": "Concedido",
        "botpasswords-bad-appid": "El nombre del bot \"$1\" no es válido.",
        "botpasswords-insert-failed": "No se pudo agregar el nombre del bot \"$1\". ¿Ya ha sido añadido?",
        "botpasswords-update-failed": "No se pudo actualizar el nombre del bot \"$1\". ¿Ha sido borrado?",
        "botpasswords-created-title": "Se creó la contraseña de bot",
-       "botpasswords-created-body": "Se creó la contraseña de bot \"$1\".",
-       "botpasswords-updated-title": "La contraseña de bot ha sido actualizada",
-       "botpasswords-updated-body": "Se actualizó la contraseña de bot \"$1\".",
-       "botpasswords-deleted-title": "La contraseña de bot ha sido eliminada",
-       "botpasswords-deleted-body": "La contraseña de bot \"$1\" ha sido eliminada.",
+       "botpasswords-created-body": "Se creó la contraseña del bot llamado \"$1\" del usuario \"$2\".",
+       "botpasswords-updated-title": "Se actualizó la contraseña de bot",
+       "botpasswords-updated-body": "Se actualizó la contraseña del bot llamado \"$1\" del usuario \"$2\".",
+       "botpasswords-deleted-title": "Se eliminó la contraseña de bot",
+       "botpasswords-deleted-body": "Se eliminó la contraseña del bot llamado \"$1\" del usuario \"$2\".",
        "botpasswords-newpassword": "La nueva contraseña para iniciar sesión con <strong>$1</strong> es <strong>$2</strong>. <em>Conserva estos datos para usos futuros.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider no está disponible.",
        "botpasswords-restriction-failed": "Las restricciones de la contraseña de bot impiden este inicio de sesión.",
        "previewnote": "<strong>Recuerda que esto no es más que una previsualización.</strong>\nAún no se han guardado tus cambios.",
        "continue-editing": "Ir al área de edición",
        "previewconflict": "Esta previsualización muestra cómo aparecerá el texto en el área de edición superior una vez guardados los cambios.",
-       "session_fail_preview": "<strong>Lo sentimos, no hemos podido procesar tu edición debido a una pérdida de los datos de sesión.</strong>\nPor favor, inténtalo de nuevo.\nSi el problema persiste, prueba a [[Special:UserLogout|cerrar sesión]] y volver a acceder.",
+       "session_fail_preview": "Lo sentimos, no hemos podido procesar tu edición debido a una pérdida de los datos de sesión.\n\nPuede que se haya cerrado tu sesión. <strong> Verifica que hayas accedido e inténtalo de nuevo</strong>.\nSi el problema persiste, prueba a [[Special:UserLogout|cerrar sesión]] y volver a acceder. Y verifica que tu navegador permita las cookies de este sitio.",
        "session_fail_preview_html": "Lo sentimos, no hemos podido procesar tu edición debido a una pérdida de datos de sesión.\n\n<em>La previsualización está oculta como prevención frente a ataques JavaScript, puesto que este wiki tiene habilitado el HTML en bruto.</em>\n\n<strong>Si se trata de un intento legítimo de modificación, inténtalo de nuevo.</strong>\nSi aún así no funcionase, prueba a [[Special:UserLogout|cerrar sesión]] y volver a acceder, y verifica que tu navegador acepte cookies de este sitio.",
        "token_suffix_mismatch": "<strong>Tu edición ha sido rechazada porque tu cliente ha mezclado los signos de puntuación en la clave de edición.</strong>\nSe rechazó la edición para evitar la corrupción del texto de la página.\nEsto sucede en ocasiones si se usa un servicio de proxy anónimo defectuoso.",
        "edit_form_incomplete": "<strong>Una parte del formulario de edición no ha llegado al servidor. Comprueba que tus cambios están intactos e inténtalo de nuevo.</strong>",
        "mergehistory-empty": "No hay revisiones fusionables.",
        "mergehistory-done": "Se {{PLURAL:$3|fusionó una revisión|fusionaron $3 revisiones}} de $1 en [[:$2]].",
        "mergehistory-fail": "No se puede realizar la fusión de historiales, por favor revisa la página y los parámetros de tiempo.",
+       "mergehistory-fail-bad-timestamp": "La marca de tiempo no es válida.",
        "mergehistory-fail-invalid-source": "La página de origen no es válida.",
        "mergehistory-fail-invalid-dest": "La página de destino no es válida.",
+       "mergehistory-fail-no-change": "La fusión historiales no fusionó ninguna revisión. Vuelve a comprobar los parámetros de página y tiempo.",
        "mergehistory-fail-permission": "Permisos insuficientes para fusionar el historial.",
        "mergehistory-fail-self-merge": "Las páginas de origen y destino son la misma.",
+       "mergehistory-fail-timestamps-overlap": "Las revisiones de origen se superponen o vienen después de las de destino.",
        "mergehistory-fail-toobig": "No se puede fusionar el historial ya que más del límite de $1 {{PLURAL:$1|revisión|revisiones}} se moverían.",
        "mergehistory-no-source": "La página origen $1 no existe.",
        "mergehistory-no-destination": "La página destino $1 no existe.",
        "right-managechangetags": "Crear y eliminar [[Special:Tags|etiquetas]] en la base de datos",
        "right-applychangetags": "Aplicar [[Special:Tags|etiquetas]] junto con los cambios propios",
        "right-changetags": "Agregar y quitar [[Special:Tags|etiquetas]] arbitrarias a revisiones individuales y entradas del registro",
-       "grant-generic": "Paquete de derechos \"$1\"",
+       "grant-generic": "Paquete de permisos \"$1\"",
        "grant-group-page-interaction": "Interactuar con páginas",
        "grant-group-file-interaction": "Interactuar con multimedia",
        "grant-group-watchlist-interaction": "Interactuar con tu lista de seguimiento",
        "recentchangeslinked-page": "Nombre de la página:",
        "recentchangeslinked-to": "Mostrar los cambios en páginas enlazadas con la página seleccionada",
        "recentchanges-page-added-to-category": "[[:$1]] añadida a la categoría",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] y {{PLURAL:$2|una página|$2 páginas}} añadidas a la categoría",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] y [[Special:WhatLinksHere/$1|{{PLURAL:$2|una página añadida|$2 páginas añadidas}}]] a la categoría",
        "recentchanges-page-removed-from-category": "[[:$1]] eliminada de la categoría",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] y {{PLURAL:$2|una página|$2 páginas}} eliminadas de la categoría",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] y [[Special:WhatLinksHere/$1|{{PLURAL:$2|una página eliminada|$2 páginas eliminadas}}]] de la categoría",
        "autochange-username": "Cambio automático de MediaWiki",
        "upload": "Subir archivo",
        "uploadbtn": "Subir un archivo",
        "uploaded-script-svg": "Se encontró el elemento habilitado para secuencias de órdenes «$1» en el archivo SVG cargado.",
        "uploaded-hostile-svg": "Se encontró código CSS no seguro en el elemento de estilo del archivo SVG cargado.",
        "uploaded-event-handler-on-svg": "No está permitido configurar atributos controladores de eventos <code>$1=\"$2\"</code> en los archivos SVG.",
-       "uploaded-href-unsafe-target-svg": "Se encontró un \"href\" hacia un destino inseguro <code><$1 $2=\"$3\"></code> en el archivo SVG cargado.",
+       "uploaded-href-attribute-svg": "Los atributos <code>href</code> en archivos SVG sólo tienen permitido enlazar a objetivos http:// o https://, se encontró <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-href-unsafe-target-svg": "Se encontró un <code>href</code> hacia un destino inseguro <code><$1 $2=\"$3\"></code> en el archivo SVG cargado.",
        "uploaded-animate-svg": "Se encontró un etiqueta \"animate\" que puede estar cambiando \"href\", mediante el atributo \"from\" <code>&lt;$1 $2=\"$3\"&gt;</code> en el archivo SVG cargado.",
        "uploaded-setting-event-handler-svg": "Está bloqueada la configuración de atributos controladores de eventos. Se encontró <code>&lt;$1 $2=\"$3\"&gt;</code> en el archivo SVG cargado.",
        "uploaded-setting-href-svg": "Está bloqueado el uso de la etiqueta \"set\" para añadir un atributo \"href\" al elemento padre.",
        "uploadinvalidxml": "No se pudo analizar el XML del archivo cargado.",
        "uploadvirus": "¡El archivo contiene un virus!\nDetalles: $1",
        "uploadjava": "El archivo es un ZIP que contiene un archivo .class de Java.\nNo se permite subir archivos Java, porque pueden causar que se puedan saltar restricciones de seguridad.",
-       "upload-source": "Archivo origen",
-       "sourcefilename": "Nombre del archivo origen:",
+       "upload-source": "Archivo de origen",
+       "sourcefilename": "Nombre del archivo de origen:",
        "sourceurl": "URL de origen:",
        "destfilename": "Nombre del archivo de destino:",
        "upload-maxfilesize": "Tamaño máximo del archivo: $1",
        "upload-options": "Opciones de subida",
        "watchthisupload": "Vigilar este archivo",
        "filewasdeleted": "Un archivo con este nombre se subió con anterioridad y posteriormente ha sido borrado. Deberías revisar el $1 antes de subirlo de nuevo.",
+       "filename-thumb-name": "Esto luce como el título de una miniatura. Por favor, no vuelva a subir miniaturas a la misma wiki. Si no es el caso, por favor corrija el nombre del archivo por uno que tenga más sentido, y no tenga el prefijo de miniatura.",
        "filename-bad-prefix": "El nombre del archivo que estás subiendo comienza por <strong>«$1»</strong>, un nombre nada descriptivo de su contenido. Es un típico nombre de los que asignan automáticamente las cámaras digitales.\nElige un nombre más descriptivo para tu archivo.",
        "filename-prefix-blacklist": " #<!-- deja esta línea exactamente como está --> <pre>\n# La sintaxis de esta página es la siguiente:\n#   * Todo texto que se encuentre después del carácter \"#\" hasta el final de la línea se tratará como un comentario y será ignorado\n#   * Cualquier línea que no esté en blanco será interpretada como un prefijo típico en nombres de archivo que suelen asignar automáticamente las cámaras digitales\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # algunos teléfonos móviles / celulares\nIMG # genérico\nJD # Jenoptik\nMGP # Pentax\nPICT # misc.\n #</pre> <!-- deja esta línea exactamente como está -->",
        "upload-proto-error": "Protocolo incorrecto",
        "foreign-structured-upload-form-label-not-own-work-local-local": "Quizás también quieras probar [[Special:Upload|la página predeterminada de subidas]].",
        "foreign-structured-upload-form-label-own-work-message-default": "Entiendo que voy a subir este archivo a un repositorio compartido. Confirmo que estoy haciéndolo que siguiendo los términos de servicio y políticas de licenciamiento de allí.",
        "foreign-structured-upload-form-label-not-own-work-message-default": "Si usted no es capaz de cargar este archivo en virtud de las políticas del repositorio compartido, por favor cierre este cuadro de diálogo y probar con otro método.",
+       "foreign-structured-upload-form-label-not-own-work-local-default": "Puede que también quieras usar [[Special:Upload|la página de subidas en {{SITENAME}}]], si se puede subir este archivo bajo sus políticas.",
        "foreign-structured-upload-form-label-own-work-message-shared": "Doy fe que soy dueño de los derechos de autor de este archivo, y acepto irrevocablemente liberar este archivo a Wikimedia Commons bajo la licencia [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0], y acepto los [https://wikimediafoundation.org/wiki/Terms_of_Use Términos de Uso].",
        "foreign-structured-upload-form-label-not-own-work-message-shared": "Si no es dueño de los derechos de autor de este archivo, o desea publicarlo bajo una licencia diferentes, considere usar el [https://commons.wikimedia.org/wiki/Special:UploadWizard Asistente de Carga de Commons].",
-       "foreign-structured-upload-form-label-not-own-work-local-shared": "Puede que también quiera usar  [[Special:Upload|la página de carga {{SITENAME}}]], si el sitio permite la subida de este archivo bajo sus políticas.",
+       "foreign-structured-upload-form-label-not-own-work-local-shared": "Puede que también quieras usar [[Special:Upload|la página de subidas en {{SITENAME}}]], si el sitio permite la subida de este archivo bajo sus políticas.",
        "backend-fail-stream": "No se pudo transmitir el archivo «$1».",
        "backend-fail-backup": "No se pudo hacer copia de seguridad del archivo «$1».",
        "backend-fail-notexists": "El archivo  $1  no existe.",
        "backend-fail-notsame": "Ya existe un archivo distinto en \"$1\".",
        "backend-fail-invalidpath": "$1 no es una ruta de almacenamiento válida",
        "backend-fail-delete": "No se pudo borrar el archivo «$1».",
-       "backend-fail-describe": "No pudieron cambiar los metadatos del archivo \"$1\".",
-       "backend-fail-alreadyexists": "El archivo  $1  ya existe.",
-       "backend-fail-store": "No se pudo almacenar el archivo $1 en $2.",
-       "backend-fail-copy": "No se pudo copiar el archivo $1 a $2.",
-       "backend-fail-move": "No se pudo trasladar el archivo $1 a $2.",
+       "backend-fail-describe": "No se pudieron cambiar los metadatos del archivo \"$1\".",
+       "backend-fail-alreadyexists": "El archivo \"$1\" ya existe.",
+       "backend-fail-store": "No se pudo almacenar el archivo \"$1\" en \"$2\".",
+       "backend-fail-copy": "No se pudo copiar el archivo \"$1\" a \"$2\".",
+       "backend-fail-move": "No se pudo trasladar el archivo \"$1\" a \"$2\".",
        "backend-fail-opentemp": "No se pudo crear archivo temporal.",
        "backend-fail-writetemp": "No se pudo escribir en el archivo temporal.",
        "backend-fail-closetemp": "No se pudo cerrar el archivo temporal.",
        "backend-fail-read": "No se pudo leer el archivo «$1».",
-       "backend-fail-create": "No se pudo escribir el archivo $1.",
+       "backend-fail-create": "No se pudo escribir el archivo \"$1\".",
        "backend-fail-maxsize": "No se pudo escribir el archivo \"$1\" porque es mayor a {{PLURAL:$2|un byte|$2 bytes}}.",
        "backend-fail-readonly": "El servidor (back-end) de almacenamiento \"$1\" está actualmente en estado de sólo lectura. La razón aducida es: <em>$2</em>",
        "backend-fail-synced": "El archivo \"$1\" se encuentra en un estado incoherente dentro de los servidores (backends) de almacenamiento interno",
        "uploadstash-badtoken": "No se pudo realizar la acción. Es posible que haya finalizado el tiempo de espera de la sesión. Inténtalo de nuevo.",
        "uploadstash-errclear": "Falló el borrado de los archivos.",
        "uploadstash-refresh": "Actualizar la lista de archivos",
+       "uploadstash-thumbnail": "ver miniatura",
        "invalid-chunk-offset": "Desplazamiento inválido del fragmento",
        "img-auth-accessdenied": "Acceso denegado",
        "img-auth-nopathinfo": "Falta PATH_INFO.\nEl servidor no está configurado para proporcionar esta información.\nEs posible que esté basado en CGI y que no sea compatible con img_auth.\nConsulte https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "listfiles_date": "Fecha",
        "listfiles_name": "Nombre",
        "listfiles_user": "Usuario",
-       "listfiles_size": "Tamaño (bytes)",
+       "listfiles_size": "Tamaño",
        "listfiles_description": "Descripción",
        "listfiles_count": "Versiones",
        "listfiles-show-all": "Incluir versiones antiguas de las imágenes",
        "filehist-nothumb": "Sin miniatura",
        "filehist-user": "Usuario",
        "filehist-dimensions": "Dimensiones",
-       "filehist-filesize": "Tamaño",
+       "filehist-filesize": "Tamaño del archivo",
        "filehist-comment": "Comentario",
        "imagelinks": "Usos del archivo",
        "linkstoimage": "{{PLURAL:$1|La siguiente página enlaza|Las siguientes páginas enlazan}} a este archivo:",
        "linkstoimage-more": "Hay más de {{PLURAL:$1|una página que enlaza|$1 páginas que enlazan}} con este archivo.\nLa lista siguiente sólo muestra {{PLURAL:$1|la primera página que enlaza|las primeras $1 páginas que enlazan}} con este archivo.\nTambién puedes consultar la [[Special:WhatLinksHere/$2|lista completa]].",
        "nolinkstoimage": "No hay páginas que enlacen a esta imagen.",
-       "morelinkstoimage": "Vea [[Special:WhatLinksHere/$1|más enlaces]] a este archivo.",
+       "morelinkstoimage": "Mira [[Special:WhatLinksHere/$1|más enlaces]] a este archivo.",
        "linkstoimage-redirect": "$1 (archivo de redirección) $2",
        "duplicatesoffile": "{{PLURAL:$1|El siguiente archivo es un duplicado|Los siguientes $1 archivos son duplicados}} de éste ([[Special:FileDuplicateSearch/$2|más detalles]]):",
        "sharedupload": "Este archivo es de $1 y puede ser usado por otros proyectos.",
        "randomincategory-category": "Categoría:",
        "randomincategory-legend": "Página aleatoria en categoría",
        "randomincategory-submit": "Ir",
-       "randomredirect": "Ir a una redirección cualquiera",
+       "randomredirect": "Redirección aleatoria",
        "randomredirect-nopages": "No hay redirecciones en el espacio de nombres «$1».",
        "statistics": "Estadísticas",
        "statistics-header-pages": "Estadísticas de páginas",
        "statistics-header-edits": "Estadísticas de ediciones",
-       "statistics-header-users": "Estadísticas de usuario",
+       "statistics-header-users": "Estadísticas de usuarios",
        "statistics-header-hooks": "Otras estadísticas",
        "statistics-articles": "Páginas de contenido",
        "statistics-pages": "Páginas",
        "statistics-pages-desc": "Todas las páginas en el wiki, incluyendo páginas de discusión, redirecciones, etc.",
        "statistics-files": "Archivos subidos",
        "statistics-edits": "Ediciones en páginas desde que {{SITENAME}} fue instalado",
-       "statistics-edits-average": "Media de ediciones por página",
+       "statistics-edits-average": "Promedio de ediciones por página",
        "statistics-users": "[[Special:ListUsers|Usuarios]] registrados",
        "statistics-users-active": "Usuarios activos",
        "statistics-users-active-desc": "Usuarios que han ejecutado una acción en {{PLURAL:$1|el último día|los últimos $1 días}}",
        "withoutinterwiki-summary": "Las siguientes páginas no enlazan a versiones en otros idiomas:",
        "withoutinterwiki-legend": "Prefijo",
        "withoutinterwiki-submit": "Mostrar",
-       "fewestrevisions": "Artículos con menos ediciones",
+       "fewestrevisions": "Páginas con el menor número de revisiones",
        "nbytes": "$1 {{PLURAL:$1|byte|bytes}}",
        "ncategories": "$1 {{PLURAL:$1|categoría|categorías}}",
        "ninterwikis": "$1 {{PLURAL:$1|interwiki|interwikis}}",
        "nrevisions": "$1 {{PLURAL:$1|revisión|revisiones}}",
        "nimagelinks": "Usado en {{PLURAL:$1|una página|$1 páginas}}",
        "ntransclusions": "usado en {{PLURAL:$1|una página|$1 páginas}}",
-       "specialpage-empty": "Esta página está vacía.",
+       "specialpage-empty": "No hay resultados para este informe.",
        "lonelypages": "Páginas huérfanas",
        "lonelypagestext": "Las siguientes páginas no están enlazadas ni transcluidas en otras páginas de {{SITENAME}}.",
        "uncategorizedpages": "Páginas sin categorizar",
        "uncategorizedcategories": "Categorías sin categorizar",
-       "uncategorizedimages": "Imágenes sin categorizar",
+       "uncategorizedimages": "Archivos sin categorizar",
        "uncategorizedtemplates": "Plantillas sin categorizar",
        "unusedcategories": "Categorías sin uso",
-       "unusedimages": "Imágenes sin uso",
+       "unusedimages": "Archivos sin uso",
        "wantedcategories": "Categorías requeridas",
        "wantedpages": "Páginas requeridas",
        "wantedpages-summary": "Lista de páginas inexistentes con el mayor número de enlaces a ellas, excluyendo páginas que son solo redirecciones a ellas. Para ver una lista de páginas inexistentes con redirecciones apuntando a ellas, consulta [[{{#special:BrokenRedirects}}|la lista de redirecciones rotas]].",
        "wantedfiletext-nocat": "Los siguientes archivos están en uso, pero no existen. Es posible que algunos de ellos estén almacenados en repositorios externos y se hayan incluido aquí por error; dichas entradas aparecen <del>tachadas</del>.",
        "wantedfiletext-nocat-noforeign": "Los siguientes archivos están en uso, pero no existen.",
        "wantedtemplates": "Plantillas requeridas",
-       "mostlinked": "Artículos más enlazados",
+       "mostlinked": "Páginas más enlazadas",
        "mostlinkedcategories": "Categorías más enlazadas",
        "mostlinkedtemplates": "Páginas más transcluidas",
        "mostcategories": "Páginas con más categorías",
        "newpages": "Páginas nuevas",
        "newpages-submit": "Mostrar",
        "newpages-username": "Nombre de usuario",
-       "ancientpages": "Artículos más antiguos",
+       "ancientpages": "Páginas más antiguas",
        "move": "Trasladar",
        "movethispage": "Trasladar esta página",
        "unusedimagestext": "Los siguientes archivos existen pero no están insertados en ninguna página.\nTen en cuenta que otros sitios web pueden enlazar un archivo directamente por la URL, y por tanto pueden estar listados aquí a pesar de estar siendo usados de forma activa.",
        "apihelp": "Ayuda de la API",
        "apihelp-no-such-module": "No se encontró el módulo \"$1\".",
        "apisandbox": "Zona de pruebas API",
+       "apisandbox-jsonly": "Se requiere JavaScript para utilizar la zona de pruebas de API.",
        "apisandbox-api-disabled": "La API está desactivada en este sitio.",
-       "apisandbox-intro": "Usa esta página para experimentar con la '''API de servicio web de MediaWiki'''.\nPara más detalles sobre el uso de la API, visita [//www.mediawiki.org/wiki/API:Main_page su documentación]. Ejemplo: [//www.mediawiki.org/wiki/API#A_simple_example obtener el contenido de una Página principal]. Selecciona una acción para ver más ejemplos.\n\nObserva que, aunque sea una página de pruebas, las acciones que realices en esta página pueden modificar el wiki.",
+       "apisandbox-intro": "Usa esta página para experimentar con la <strong>API de servicio web de MediaWiki</strong>.\nPara más detalles sobre el uso de la API, visita [[mw:API:Main page|su documentación]]. Ejemplo: [//www.mediawiki.org/wiki/API#A_simple_example obtener el contenido de una Página principal]. Selecciona una acción para ver más ejemplos.\n\nObserva que, aunque sea una página de pruebas, las acciones que realices en esta página pueden modificar el wiki.",
        "apisandbox-fullscreen": "Expandir panel",
+       "apisandbox-fullscreen-tooltip": "Expande el panel de la zona de pruebas hasta llenar la ventana del navegador.",
        "apisandbox-unfullscreen": "Mostrar página",
+       "apisandbox-unfullscreen-tooltip": "Reduce el panel de la zona de pruebas, para que los enlaces de navegación MediaWiki estén disponibles.",
        "apisandbox-submit": "Realizar solicitud",
        "apisandbox-reset": "Limpiar",
        "apisandbox-retry": "Reintentar",
+       "apisandbox-loading": "Cargando la información para el módulo API \"$1\"...",
+       "apisandbox-load-error": "Ocurrió un error al cargar la información para el módulo API \"$1\": $2",
        "apisandbox-no-parameters": "Este módulo API no tiene parámetros.",
        "apisandbox-helpurls": "Enlaces de ayuda",
        "apisandbox-examples": "Ejemplos",
        "apisandbox-dynamic-parameters": "Parámetros adicionales",
        "apisandbox-dynamic-parameters-add-label": "Añadir parámetro:",
        "apisandbox-dynamic-parameters-add-placeholder": "Nombre del parámetro",
+       "apisandbox-dynamic-error-exists": "Ya existe un parámetro llamado \"$1\".",
        "apisandbox-deprecated-parameters": "Parámetros desaconsejados",
+       "apisandbox-fetch-token": "Auto-llenar el token",
        "apisandbox-submit-invalid-fields-title": "Algunos campos no son válidos",
        "apisandbox-submit-invalid-fields-message": "Por favor, corrige los campos señalados e inténtalo de nuevo.",
        "apisandbox-results": "Resultados",
        "showhideselectedlogentries": "Cambiar la visibilidad de las entradas del registro seleccionadas",
        "log-edit-tags": "Editar las etiquetas de las entradas del registro seleccionadas",
        "checkbox-select": "Seleccionar: $1",
-       "checkbox-all": "Todas",
-       "checkbox-none": "Ninguna",
-       "checkbox-invert": "Invertir",
+       "checkbox-all": "todas",
+       "checkbox-none": "ninguna",
+       "checkbox-invert": "invertir",
        "allpages": "Todas las páginas",
-       "nextpage": "Siguiente página ($1)",
+       "nextpage": "Página siguiente ($1)",
        "prevpage": "Página anterior ($1)",
        "allpagesfrom": "Mostrar páginas que empiecen por:",
        "allpagesto": "Mostrar páginas terminadas con:",
        "activeusers-hidesysops": "Ocultar administradores",
        "activeusers-noresult": "No se encontraron usuarios.",
        "activeusers-submit": "Mostrar usuarios activos",
-       "listgrouprights": "Permisos del grupo de usuarios",
-       "listgrouprights-summary": "La siguiente es una lista de los grupos de usuario definidos en esta wiki y de sus privilegios de acceso asociados.\nPuede haber información adicional sobre privilegios individuales en [[{{MediaWiki:Listgrouprights-helppage}}]]",
+       "listgrouprights": "Permisos de los grupos de usuarios",
+       "listgrouprights-summary": "La siguiente es una lista de los grupos de usuarios definidos en esta wiki y de sus permisos de acceso asociados.\nPuede haber [[{{MediaWiki:Listgrouprights-helppage}}|información adicional]] sobre permisos individuales.",
        "listgrouprights-key": "Leyenda:\n* <span class=\"listgrouprights-granted\">Derecho concedido</span>\n* <span class=\"listgrouprights-revoked\">Derecho revocado</span>",
        "listgrouprights-group": "Grupo",
        "listgrouprights-rights": "Derechos",
-       "listgrouprights-helppage": "Help:Derechos de grupos",
-       "listgrouprights-members": "(ver los miembros de este grupo)",
+       "listgrouprights-helppage": "Help:Permisos de grupos",
+       "listgrouprights-members": "(lista de miembros)",
        "listgrouprights-addgroup": "Agregar {{PLURAL:$2|grupo|grupos}}: $1",
        "listgrouprights-removegroup": "Eliminar {{PLURAL:$2|grupo|grupos}}: $1",
        "listgrouprights-addgroup-all": "Agregar todos los grupos",
        "listgrouprights-namespaceprotection-header": "Restricciones del espacio de nombres",
        "listgrouprights-namespaceprotection-namespace": "Espacio de nombres",
        "listgrouprights-namespaceprotection-restrictedto": "Derechos de usuario para editar",
-       "listgrants": "Subvenciones",
+       "listgrants": "Concesiones",
+       "listgrants-summary": "La siguiente es una lista de concesiones con sus permisos de usuario asociados. Los usuarios pueden autorizar aplicaciones para que usen sus cuentas, pero con permisos limitados basados en las concesiones que el usuario le dio a la aplicación. De todas formas, una aplicación actuando a nombre de un usuario no puede hacer uso de permisos que el usuario no posea.\nPuede haber [[{{MediaWiki:Listgrouprights-helppage}}|información adicional]] sobre permisos individuales.",
        "listgrants-grant": "Conceder",
        "listgrants-rights": "Derechos",
        "trackingcategories": "Categorías de seguimiento",
        "addedwatchtext-short": "La página \"$1\" ha sido añadida a tu lista de seguimiento.",
        "removewatch": "Quitar de la lista de seguimiento",
        "removedwatchtext": "Se han eliminado «[[:$1]]» y su página de discusión de tu [[Special:Watchlist|lista de seguimiento]].",
-       "removedwatchtext-short": "La página \"$1\" ha sido eliminado de tu lista de seguimiento.",
+       "removedwatchtext-short": "La página \"$1\" ha sido eliminada de tu lista de seguimiento.",
        "watch": "Vigilar",
        "watchthispage": "Vigilar esta página",
        "unwatch": "Dejar de vigilar",
        "unwatchthispage": "Dejar de vigilar",
-       "notanarticle": "No es un artículo",
+       "notanarticle": "No es una página de contenido",
        "notvisiblerev": "La última revisión de un usuario diferente ha sido borrada",
        "watchlist-details": "{{PLURAL:$1|$1 página|$1 páginas}} en tu lista de seguimiento, sin contar las de discusión.",
        "wlheader-enotif": "La notificación por correo está activada.",
        "watcherrortext": "Ocurrió un error al cambiar la configuración de tu lista de seguimiento para «$1».",
        "enotif_reset": "Marcar todas las páginas como visitadas",
        "enotif_impersonal_salutation": "usuario de {{SITENAME}}",
-       "enotif_subject_deleted": "$2 ha borrado la página $1 de {{SITENAME}}",
-       "enotif_subject_created": "$2 ha creado la página $1 en {{SITENAME}}",
-       "enotif_subject_moved": "$2 ha trasladado la página $1 de {{SITENAME}}",
-       "enotif_subject_restored": "$2 ha restaurado la página $1 de {{SITENAME}}",
-       "enotif_subject_changed": "$2 ha modificado la página $1 de {{SITENAME}}",
+       "enotif_subject_deleted": "$2 {{GENDER:$2|borró}} la página $1 de {{SITENAME}}",
+       "enotif_subject_created": "$2 {{GENDER:$2|creó}} la página $1 de {{SITENAME}}",
+       "enotif_subject_moved": "$2 {{GENDER:$2|trasladó}} la página $1 de {{SITENAME}}",
+       "enotif_subject_restored": "$2 {{GENDER:$2|restauró}} la página $1 de {{SITENAME}}",
+       "enotif_subject_changed": "$2 {{GENDER:$2|cambió}} la página $1 de {{SITENAME}}",
        "enotif_body_intro_deleted": "La página $1 de {{SITENAME}} ha sido borrada el $PAGEEDITDATE por {{GENDER:$2|$2}}, véase $3.",
        "enotif_body_intro_created": "La página $1 de {{SITENAME}} ha sido creada el $PAGEEDITDATE por {{GENDER:$2|$2}}, véase $3 para la revisión actual.",
        "enotif_body_intro_moved": "La página $1 de {{SITENAME}} ha sido trasladada el $PAGEEDITDATE por {{GENDER:$2|$2}}, véase $3 para la revisión actual.",
        "enotif_body_intro_restored": "La página $1 de {{SITENAME}} ha sido restaurada el $PAGEEDITDATE por {{GENDER:$2|$2}}, véase $3 para la revisión actual.",
        "enotif_body_intro_changed": "La página $1 de {{SITENAME}} ha sido cambiada el $PAGEEDITDATE por {{GENDER:$2|$2}}, véase $3 para la revisión actual.",
-       "enotif_lastvisited": "Consulta $1 para ver todos los cambios realizados desde tu última visita.",
+       "enotif_lastvisited": "Consulta $1 para ver todos los cambios desde tu última visita.",
        "enotif_lastdiff": "Consulta $1 para ver este cambio.",
        "enotif_anon_editor": "usuario anónimo $1",
        "enotif_body": "Hola, $WATCHINGUSERNAME:\n\n$PAGEINTRO $NEWPAGE\n\nResumen del editor: $PAGESUMMARY $PAGEMINOREDIT\n\nContacta al editor:\ncorreo: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nNo enviaremos más notificaciones si ocurre más actividad, a menos que visites esta página con la sesión iniciada. También puedes restablecer los estados de notificación para todas las páginas en tu lista de seguimiento.\n\nAtentamente, el sistema de notificaciones de {{SITENAME}}\n\n--\nPara cambiar tus ajustes de notificación por correo, visita\n{{canonicalurl:{{#special:Preferences}}}}\n\nPara cambiar los ajustes de tu lista de seguimiento, visita\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPara quitar la página de tu lista de seguimiento, visita\n$UNWATCHURL\n\nPara ayuda y comentarios:\n$HELPPAGE",
        "created": "creada",
        "changed": "modificada",
-       "deletepage": "Borrar esta página",
+       "deletepage": "Borrar página",
        "confirm": "Confirmar",
        "excontent": "el contenido era: «$1»",
        "excontentauthor": "el contenido era: «$1», y el único autor fue «[[Special:Contributions/$2|$2]]» ([[User talk:$2|discusión]])",
        "changecontentmodel-title-label": "Título de página",
        "changecontentmodel-model-label": "Modelo de contenido nuevo",
        "changecontentmodel-reason-label": "Motivo:",
+       "changecontentmodel-submit": "Cambiar",
        "changecontentmodel-success-title": "Se cambió el modelo de contenido",
        "changecontentmodel-success-text": "Se ha cambiado el tipo de contenido de [[:$1]].",
        "changecontentmodel-cannot-convert": "El contenido de [[:$1]] no se puede convertir a un tipo de $2.",
        "maximum-size": "Tamaño máximo:",
        "pagesize": "(bytes)",
        "restriction-edit": "Editar",
-       "restriction-move": "Pueden trasladar",
+       "restriction-move": "Trasladar",
        "restriction-create": "Crear",
        "restriction-upload": "Subir",
        "restriction-level-sysop": "completamente protegida",
        "restriction-level-autoconfirmed": "semiprotegida",
        "restriction-level-all": "cualquier nivel",
-       "undelete": "Restaurar una página borrada",
+       "undelete": "Ver páginas borradas",
        "undeletepage": "Ver y restaurar páginas borradas",
        "undeletepagetitle": "<strong>Las siguientes son las revisiones borradas de [[:$1|$1]]</strong>.",
        "viewdeletedpage": "Ver páginas borradas",
        "undelete-header": "En el [[Special:Log/delete|registro de borrados]] se listan las páginas eliminadas.",
        "undelete-search-title": "Buscar páginas borradas",
        "undelete-search-box": "Buscar páginas borradas",
-       "undelete-search-prefix": "Mostrar páginas que empiecen por:",
+       "undelete-search-prefix": "Mostrar páginas que empiecen con:",
        "undelete-search-submit": "Buscar",
        "undelete-no-results": "No se encontraron páginas borradas para ese criterio de búsqueda.",
        "undelete-filename-mismatch": "No se puede restaurar la revisión con marca de tiempo $1: no concuerda el nombre del archivo.",
        "sp-contributions-uploads": "subidas",
        "sp-contributions-logs": "registros",
        "sp-contributions-talk": "discusión",
-       "sp-contributions-userrights": "gestión de permisos del usuario",
+       "sp-contributions-userrights": "gestión de permisos de usuario",
        "sp-contributions-blocked-notice": "Este usuario está actualmente bloqueado. La última entrada del registro de bloqueos es presentada debajo para mayor referencia:",
        "sp-contributions-blocked-notice-anon": "Esta dirección IP se encuentra actualmente bloqueada.\nA continuación se muestra la última entrada del registro de bloqueos para mayor referencia.",
        "sp-contributions-search": "Buscar contribuciones",
        "ipb-unblock": "Desbloquear un usuario o una IP",
        "ipb-blocklist": "Ver bloqueos vigentes",
        "ipb-blocklist-contribs": "Contribuciones de {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 restantes",
        "unblockip": "Desbloquear usuario",
        "unblockiptext": "Use el formulario a continuación para devolver los permisos de escritura a una dirección IP que ha sido bloqueada.",
        "ipusubmit": "Desactivar este bloqueo",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importadas}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisión importada|revisiones importadas}} desde $2",
        "javascripttest": "Pruebas de JavaScript",
-       "javascripttest-pagetext-noframework": "Esta página está reservada para ejecutar pruebas de JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Marco de pruebas desconocido \"$1\".",
        "javascripttest-pagetext-unknownaction": "La acción «$1» es desconocida.",
-       "javascripttest-pagetext-frameworks": "Selecciona uno de los marcos de pruebas siguientes: $1",
-       "javascripttest-pagetext-skins": "Elige una apariencia con la que ejecutar las pruebas:",
        "javascripttest-qunit-intro": "Consulta la [$1 documentación sobre las pruebas] en mediawiki.org.",
        "tooltip-pt-userpage": "Tu página de {{GENDER:|usuario|usuaria}}",
        "tooltip-pt-anonuserpage": "La página de usuario de la IP desde la que editas",
        "months": "{{PLURAL:$1|$1 mes|$1 meses}}",
        "years": "{{PLURAL:$1|$1 año|$1 años}}",
        "ago": "hace $1",
-       "just-now": "Ahora mismo",
+       "just-now": "ahora mismo",
        "hours-ago": "hace $1 {{PLURAL:$1|hora|horas}}",
        "minutes-ago": "hace {{PLURAL:$1|un minuto|$1 minutos}}",
        "seconds-ago": "hace $1 {{PLURAL:$1|segundo|segundos}}",
-       "monday-at": "El lunes a las $1",
-       "tuesday-at": "El martes a las $1",
-       "wednesday-at": "El miércoles a las $1",
-       "thursday-at": "El jueves a las $1",
-       "friday-at": "El viernes a las $1",
-       "saturday-at": "El sábado a las $1",
-       "sunday-at": "El domingo a las $1",
-       "yesterday-at": "Ayer a las $1",
+       "monday-at": "el lunes a las $1",
+       "tuesday-at": "el martes a las $1",
+       "wednesday-at": "el miércoles a las $1",
+       "thursday-at": "el jueves a las $1",
+       "friday-at": "el viernes a las $1",
+       "saturday-at": "el sábado a las $1",
+       "sunday-at": "el domingo a las $1",
+       "yesterday-at": "ayer a las $1",
        "bad_image_list": "El formato es el siguiente:\n\nSolo se reconocen elementos de lista (líneas que comienzan con «*»).\nEl primer enlace de cada línea debe ser un enlace al archivo que se quiere bloquear.\nTodos los demás enlaces en la misma línea se tomarán como excepciones (es decir, páginas donde sí se puede usar el archivo).",
        "metadata": "Metadatos",
        "metadata-help": "Este archivo contiene información adicional, probablemente añadida por la cámara digital o el escáner usado para crearlo o digitalizarlo.\nSi el archivo ha sido modificado desde su estado original, pueden haberse perdido algunos detalles.",
        "exif-attributionurl": "Cuando reutilices este trabajo, por favor enlaza a",
        "exif-preferredattributionname": "Al volver a utilizar este trabajo, por favor da crédito",
        "exif-pngfilecomment": "Comentario de archivo PNG",
-       "exif-disclaimer": "Aviso legal",
+       "exif-disclaimer": "Descargo",
        "exif-contentwarning": "Advertencia de contenido",
        "exif-giffilecomment": "Comentario de archivo GIF",
        "exif-intellectualgenre": "Tipo de elemento",
        "version-libraries-description": "Descripción",
        "version-libraries-authors": "Autores",
        "redirect": "Redirigir por archivo, o identificador de usuario, página, revisión o registro",
-       "redirect-legend": "Redirigir a un archivo o página",
        "redirect-summary": "Esta página especial redirige a un archivo (dado un nombre), a una página (dado un identificador de revisión o de página), a una página de usuario (dado un identificador numérico de usuario) o a una entrada del registro (dado un identificador de registro). Uso: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]] o [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Ir",
        "redirect-lookup": "Buscar:",
        "tags-deactivate-not-allowed": "No es posible desactivar la etiqueta «$1».",
        "tags-deactivate-submit": "Desactivar",
        "tags-apply-no-permission": "No tienes permiso para aplicar etiquetas de cambios, junto con tus cambios.",
+       "tags-apply-blocked": "No puedes aplicar etiquetas de cambio con tus cambios mientras estés {{GENDER:|bloqueado|bloqueada}}.",
        "tags-apply-not-allowed-one": "No se permite aplicar manualmente la etiqueta «$1».",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|La siguiente etiqueta no se puede|Las siguientes etiquetas no se pueden}} aplicar manualmente: $1",
        "tags-update-no-permission": "No tienes permiso para agregar o quitar etiquetas de cambio de las revisiones individuales o las entradas del registro.",
+       "tags-update-blocked": "No puedes añadir o eliminar etiquetas de cambio mientras estés {{GENDER:|bloqueado|bloqueada}}.",
        "tags-update-add-not-allowed-one": "No se permite la adición manual de la etiqueta «$1».",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|La siguiente etiqueta no se puede|Las siguientes etiquetas no se pueden}} agregar manualmente: $1",
        "tags-update-remove-not-allowed-one": "No se permite eliminar la etiqueta «$1».",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|protegió}} a $3 $4 [en cascada]",
        "logentry-protect-modify": "$1 {{GENDER:$2|cambió}} el nivel de protección de $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|cambió}} el nivel de protección de $3 $4 [en cascada]",
-       "logentry-rights-rights": "$1 modificó los grupos a los que pertenece $3: de $4 a $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|modificó}} los grupos a los que pertenece {{GENDER:$3|$3}}: de $4 a $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|modificó}} los grupos a los que pertenece $3",
        "logentry-rights-autopromote": "$1 ha sido {{GENDER:$2|promocionado|promocionada}} automáticamente de $4 a $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|subió}} $3",
        "api-error-unknownerror": "Error desconocido: «$1».",
        "api-error-uploaddisabled": "Las subidas están desactivadas en este wiki.",
        "api-error-verification-error": "Este archivo puede estar dañado, o tiene una extensión incorrecta.",
+       "api-error-was-deleted": "Un archivo de este nombre se ha subido previamente y eliminado posteriormente.",
        "duration-seconds": "$1 {{PLURAL:$1|segundo|segundos}}",
        "duration-minutes": "$1 {{PLURAL:$1|minuto|minutos}}",
        "duration-hours": "$1 {{PLURAL:$1|hora|horas}}",
        "special-characters-group-ipa": "AFI",
        "special-characters-group-symbols": "Símbolos",
        "special-characters-group-greek": "Griego",
+       "special-characters-group-greekextended": "Griego extendido",
        "special-characters-group-cyrillic": "Cirílico",
        "special-characters-group-arabic": "Árabe",
        "special-characters-group-arabicextended": "Arábico extendido",
        "mw-widgets-titleinput-description-new-page": "la página aún no existe",
        "mw-widgets-titleinput-description-redirect": "redirigir a $1",
        "api-error-blacklisted": "Elige un título diferente, más descriptivo.",
-       "sessionmanager-tie": "No se pueden combinar múltiples tipos de autentificación de solicitudes: $1",
+       "sessionmanager-tie": "No se pueden combinar múltiples tipos de autenticación de solicitudes: $1.",
        "sessionprovider-generic": "sesiones $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesiones basadas en cookies",
        "sessionprovider-nocookies": "Puede que las cookies estén desactivadas. Actívalas y comienza de nuevo.",
-       "randomrootpage": "Página raíz aleatoria"
+       "randomrootpage": "Página raíz aleatoria",
+       "log-action-filter-block": "Tipo de bloqueo:",
+       "log-action-filter-delete": "Tipo de eliminación:",
+       "log-action-filter-patrol": "Tipo de verificación:",
+       "log-action-filter-protect": "Tipo de protección:",
+       "log-action-filter-upload": "Tipo de subida:",
+       "log-action-filter-all": "Todas",
+       "log-action-filter-block-block": "Bloquear",
+       "log-action-filter-block-reblock": "Modificación de bloqueo",
+       "log-action-filter-block-unblock": "Desbloquear",
+       "log-action-filter-delete-delete": "Eliminación de páginas",
+       "log-action-filter-delete-restore": "Restauración de páginas",
+       "log-action-filter-delete-event": "Eliminación de registros",
+       "log-action-filter-delete-revision": "Eliminación de revisión",
+       "log-action-filter-patrol-patrol": "Verificación manual",
+       "log-action-filter-patrol-autopatrol": "Verificación automática",
+       "log-action-filter-protect-protect": "Protección",
+       "log-action-filter-protect-modify": "Modificación de protección",
+       "log-action-filter-protect-unprotect": "Desprotección",
+       "log-action-filter-upload-upload": "Subida nueva",
+       "log-action-filter-upload-overwrite": "Volver a subir"
 }
index 5ce1955..ad15418 100644 (file)
        "recentchangeslinked-page": "Lehekülje nimi:",
        "recentchangeslinked-to": "Näita hoopis muudatusi lehekülgedel, mis sellele lehele lingivad",
        "recentchanges-page-added-to-category": "kategooriasse lisatud \"[[:$1]]\"",
-       "recentchanges-page-added-to-category-bundled": "kategooriasse lisatud \"[[:$1]]\" ja veel {{PLURAL:$2|üks lehekülg|$2 lehekülge}}",
+       "recentchanges-page-added-to-category-bundled": "kategooriasse lisatud \"[[:$1]]\" ja veel [[Special:WhatLinksHere/$1|{{PLURAL:$2|üks lehekülg|$2 lehekülge}}]]",
        "recentchanges-page-removed-from-category": "kategooriast eemaldatud \"[[:$1]]\"",
        "recentchanges-page-removed-from-category-bundled": "kategooriast eemaldatud \"[[:$1]]\" ja veel {{PLURAL:$2|üks lehekülg|$2 lehekülge}}",
        "autochange-username": "MediaWiki automaatne muudatus",
index e99ed78..7898f48 100644 (file)
        "newarticle": "(Berria)",
        "newarticletext": "Orrialde hau ez da existitzen oraindik. Orrialde sortu nahi baduzu, beheko koadroan idazten hasi zaitezke (ikus [$1 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.\nBere IP helbidea erabili beharko da beraz identifikatzeko.\nErabiltzaile batek baino gehiagok IP bera erabil dezakete ordea.\nErabiltzaile anonimoa bazara eta zurekin zerikusirik ez duten mezuak jasotzen badituzu, mesedez [[Special:UserLogin/signup|Izena eman]] edo [[Special:UserLogin|saioa hasi]] etorkizunean horrelakoak gerta ez daitezen.''",
-       "noarticletext": "Oraindik ez dago testurik orri honetan.\nEdukiz hornitzeko, aukera hauek dituzu: beste orri batzuetan [[Special:Search/{{PAGENAME}}|orri izenburu hau bilatzea]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} lotutako logak bilatzea],\nedo [{{fullurl:{{FULLPAGENAME}}|action=edit}} orri hau editatzea]</span>.",
+       "noarticletext": "Oraindik ez dago testurik orri honetan.\nEdukiz hornitzeko, aukera hauek dituzu: beste orri batzuetan [[Special:Search/{{PAGENAME}}|orri izenburu hau bilatzea]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} lotutako logak bilatzea],\nedo [{{fullurl:{{FULLPAGENAME}}|action=edit}} orri hau sortzea]</span>.",
        "noarticletext-nopermission": "Une honetan ez dago testurik orrialde honetan.\nBeste orrialdeetan [[Special:Search/{{PAGENAME}}|izenburu hau bilatu dezakezu]],\nedo <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} erlazionatutako erregistroak bilatu]</span>, baina ez duzu orrialde hau sortzeko baimenik.",
        "userpage-userdoesnotexist": "\"<nowiki>$1</nowiki>\" lankidea ez dago erregistatuta. Mesedez, konprobatu orri hau editatu/sortu nahi duzun.",
        "userpage-userdoesnotexist-view": "\"$1\" erabiltzaile-kontua ez dago erregistraturik.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|berrikuspen|berrikuspen}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|berrikuspen|berrikuspen}} $2-(e)tik",
        "javascripttest": "JavaScript frogatzen",
-       "javascripttest-pagetext-noframework": "Orrialde hau JavaScript frogak egiteko gordeta dago.",
-       "javascripttest-pagetext-unknownframework": "Froga eremu ez-ezaguna \"$1\".",
        "javascripttest-pagetext-unknownaction": "Ekintza ezezaguna \"$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.",
        "tooltip-pt-userpage": "{{GENDER:|Zure lankide}} orria",
        "tooltip-pt-anonuserpage": "Zure IParen lankide orrialdea",
        "tooltip-pt-anontalk": "Zure IParen eztabaida",
        "tooltip-pt-preferences": "{{GENDER:|Zure}} hobespenak",
        "tooltip-pt-watchlist": "Jarraitzen dituzun orrialdeen zerrenda.",
-       "tooltip-pt-mycontris": "Nire ekarpenen zerrenda",
+       "tooltip-pt-mycontris": "{{GENDER:|Nire}} ekarpenen zerrenda",
        "tooltip-pt-anoncontribs": "IP helbide honetatik egindako aldaketen zerrenda",
        "tooltip-pt-login": "Izen ematera gonbidatzen zaitugu.",
        "tooltip-pt-logout": "Saioa itxi",
        "tooltip-t-recentchangeslinked": "Orri honetatik lotura duten orrietako azken aldaketak",
        "tooltip-feed-rss": "Orrialde honen RSS jarioa",
        "tooltip-feed-atom": "Orrialde honen atom jarioa",
-       "tooltip-t-contributions": "Lankide honen ekarpen zerrenda ikusi",
+       "tooltip-t-contributions": "{{GENDER:$1|Lankide honen}} ekarpen zerrenda ikusi",
        "tooltip-t-emailuser": "Lankide honi e-posta mezua bidali",
        "tooltip-t-info": "Orrialde honi buruzko informazio gehiago",
        "tooltip-t-upload": "Irudiak edo media fitxategiak igo",
        "version-libraries-description": "Deskribapena",
        "version-libraries-authors": "Egileak",
        "redirect": "Birzuzendu fitxategi, lankide edo berrikuspen IDaren arabera",
-       "redirect-legend": "Orrialde edo fitxategi batera birzuzendu",
        "redirect-submit": "Joan",
        "redirect-lookup": "Ikuskatu:",
        "redirect-value": "Balioa:",
index c958574..ae34257 100644 (file)
@@ -50,7 +50,8 @@
                        "MRG90",
                        "Mahdy Saffar",
                        "Arian Ar",
-                       "Ms96"
+                       "Ms96",
+                       "Freshman404"
                ]
        },
        "tog-underline": "خط کشیدن زیر پیوندها:",
        "botpasswords-insert-failed": "شکست در افزودن نام ربات «$1». در حال حاضر اضافه شده است؟",
        "botpasswords-update-failed": "شکست در به‌روزرسانی نام رباتی «$1». حذف شده است؟",
        "botpasswords-created-title": "گذرواژه ربات ایجاد شد",
-       "botpasswords-created-body": "گذرواژهٔ رباتی «$1» ایجاد شد.",
+       "botpasswords-created-body": "گذرواژهٔ رباتی برای ربات «$1» و کاربر «$2» ایجاد شد.",
        "botpasswords-updated-title": "گذرواژه ربات به‌روز شد",
-       "botpasswords-updated-body": "گذرواژهٔ رباتی «$1» به‌روز شد.",
+       "botpasswords-updated-body": "گذرواژهٔ رباتی برای ربات «$1» و کاربر «$2» به‌روز شد.",
        "botpasswords-deleted-title": "گذرواژه ربات حذف شد",
-       "botpasswords-deleted-body": "گذرواژهٔ رباتی «$1» حذف شد.",
+       "botpasswords-deleted-body": "گذرواژهٔ رباتی برای ربات «$1» و کاربر «$2» حذف شد.",
        "botpasswords-newpassword": "<strong>$2</strong> گذرواژهٔ جدید برای ورود با <strong>$1</strong> است. <em>لطفاً این را برای ارجاع در آینده ذخیره کنید.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider موجود نیست.",
        "botpasswords-restriction-failed": "محدودیت‌های گذرواژهٔ ربات از این ورود جلوگیری می‌کند.",
        "userpage-userdoesnotexist": "حساب کاربر «<nowiki>$1</nowiki>» ثبت نشده‌است.\nلطفاً مطمئن شوید که می‌خواهید این صفحه را ایجاد یا ویرایش کنید.",
        "userpage-userdoesnotexist-view": "حساب کاربری «$1» ثبت نشده‌است.",
        "blocked-notice-logextract": "دسترسی این کاربر در حال حاضر بسته است.\nآخرین مورد سیاهه قطع دسترسی در زیر آمده‌است:",
-       "clearyourcache": "<strong>نکته:</strong> پس از ذخیرهکردن ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.\n*<strong>فایرفاکس / سافاری:</strong> کلید <em>Shift</em> را نگه دارید و روی دکمهٔ <em>Reload</em> کلیک کنید، یا کلید‌های <em>Ctrl-F5</em> یا <em>Ctrl-R</em> را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های <em>⌘-R</em>)\n*<strong>گوگل کروم:</strong> کلیدهای <em>Ctrl+Shift+R</em> را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های <em>⌘-Shift-R</em>)\n*<strong>اینترنت اکسپلورر:</strong> کلید <em>Ctrl</em> را نگه‌دارید و روی دکمهٔ <em>Refresh</em> کلیک کنید، یا کلید‌های <em>Ctrl-F5</em> را با هم فشار دهید\n*<strong>اپرا:</strong> حافظهٔ نهانی مرورگر را از طریق منوی <em>Tools &rarr; Preferences</em> پاک کنید",
-       "usercssyoucanpreview": "'''نکته:''' پیش از ذخیرهکردن پرونده سی‌اس‌اس خود، با دکمهٔ '''{{int:showpreview}}''' آن را آزمایش کنید.",
-       "userjsyoucanpreview": "'''نکته:''' پیش از ذخیرهکردن پروندهٔ جاوااسکریپت خود، با دکمهٔ '''{{int:showpreview}}''' آن را آزمایش کنید.",
+       "clearyourcache": "<strong>نکته:</strong> پس از ذخیره کردن ممکن است برای دیدن تغییرات نیاز باشد که حافظهٔ نهانی مرورگر خود را پاک کنید.\n*<strong>فایرفاکس / سافاری:</strong> کلید <em>Shift</em> را نگه دارید و روی دکمهٔ <em>Reload</em> کلیک کنید، یا کلید‌های <em>Ctrl-F5</em> یا <em>Ctrl-R</em> را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های <em>⌘-R</em>)\n*<strong>گوگل کروم:</strong> کلیدهای <em>Ctrl+Shift+R</em> را با هم فشار دهید (در رایانه‌های اپل مکینتاش کلید‌های <em>⌘-Shift-R</em>)\n*<strong>اینترنت اکسپلورر:</strong> کلید <em>Ctrl</em> را نگه‌دارید و روی دکمهٔ <em>Refresh</em> کلیک کنید، یا کلید‌های <em>Ctrl-F5</em> را با هم فشار دهید\n*<strong>اپرا:</strong> حافظهٔ نهانی مرورگر را از طریق منوی <em>Tools &rarr; Preferences</em> پاک کنید",
+       "usercssyoucanpreview": "'''نکته:''' پیش از ذخیره کردن پرونده سی‌اس‌اس خود، با دکمهٔ '''{{int:showpreview}}''' آن را آزمایش کنید.",
+       "userjsyoucanpreview": "'''نکته:''' پیش از ذخیره کردن پروندهٔ جاوااسکریپت خود، با دکمهٔ '''{{int:showpreview}}''' آن را آزمایش کنید.",
        "usercsspreview": "'''فراموش مکنید که شما فقط دارید پیش‌نمایش سی‌اس‌اس کاربری‌تان را می‌بینید.'''\n'''این سی‌اس‌اس هنوز ذخیره نشده‌است!'''",
        "userjspreview": "'''به یاد داشته باشید که شما فقط دارید جاوااسکریپت کاربری‌تان را امتحان می‌کنید/پیش‌نمایش آن را می‌بینید.'''\n'''این جاوااسکریپت هنوز ذخیره نشده‌است!'''",
        "sitecsspreview": "'''به یاد داشته باشید که شما فقط دارید پیش‌نمایش این سی‌اس‌اس را می‌بینید.'''\n'''این سی‌اس‌اس هنوز ذخیره نشده‌است!'''",
        "recentchanges-noresult": "هیچ تغییری در طول دورهٔ تعیین‌شده با این معیارها هم‌خوانی نداشت.",
        "recentchanges-feed-description": "آخرین تغییرات ویکی را در این خوراک پی‌گیری کنید.",
        "recentchanges-label-newpage": "این ویرایش صفحه‌ای تازه ایجاد کرد",
-       "recentchanges-label-minor": "این یک ویرایش جزئیاست",
+       "recentchanges-label-minor": "این یک ویرایش جزئی است",
        "recentchanges-label-bot": "این ویرایش را یک ربات انجام داده است",
        "recentchanges-label-unpatrolled": "این ویرایش هنوز گشت‌زنی نشده است",
        "recentchanges-label-plusminus": "حجم صفحه به اندازه این مقدار بایت تغییر یافته است",
        "recentchangeslinked-page": "نام صفحه:",
        "recentchangeslinked-to": "نمایش تغییرات صفحه‌هایی که به صفحهٔ داده‌شده پیوند دارند",
        "recentchanges-page-added-to-category": "[[:$1]] به رده اضافه شد",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] و {{PLURAL:$2|یک صفحه|$2 صفحه}}ٔ دیگر به رده اضافه شدند",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] و [[Special:WhatLinksHere/$1|{{PLURAL:$2|یک صفحه|$2 صفحه}}]]دیگر به رده اضافه شدند",
        "recentchanges-page-removed-from-category": "[[:$1]] از رده حذف شد",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] و {{PLURAL:$2|یک صفحه|$2 صفحه}}ٔ دیگر از رده حذف شدند",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] و [[Special:WhatLinksHere/$1|{{PLURAL:$2|یک صفحه|$2 صفحه}}]] دیگر از رده حذف شدند",
        "autochange-username": "تغییرات خودکار مدیاویکی",
        "upload": "بارگذاری پرونده",
        "uploadbtn": "بارگذاری پرونده",
        "uploadstash-badtoken": "انجام این اقدام ناموفق بود، احتمالاً به این دلیل که اعتبار ویرایش شما به اتمام رسیده است. لطفاً دوباره امتحان کنید.",
        "uploadstash-errclear": "پاک‌کردن پرونده‌ها ناموفق بود.",
        "uploadstash-refresh": "تازه کردن فهرست پرونده‌ها",
+       "uploadstash-thumbnail": "نمایش بندانگشتی",
        "invalid-chunk-offset": "جابجایی نامعتبر قطعه",
        "img-auth-accessdenied": "منع دسترسی",
        "img-auth-nopathinfo": "PATH_INFO موجود نیست.\nسرور شما برای ردکردن این مقدار تنظیم نشده‌است.\nممکن است مبتنی بر سی‌جی‌آی باشد و از img_auth پشتیبانی نکند.\nhttps://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization را ببینید.",
        "ninterwikis": "$1 {{PLURAL:$1|میان‌ویکی|میان‌ویکی}}",
        "nlinks": "$1 {{PLURAL:$1|پیوند|پیوند}}",
        "nmembers": "$1 {{PLURAL:$1|عضو|عضو}}",
-       "nmemberschanged": "$1 â\86\92 $2   {{PLURAL:$2| عضو|عضو}}",
+       "nmemberschanged": "$1 â\86\90 $2 {{PLURAL:$2| عضو|عضو}}",
        "nrevisions": "$1 {{PLURAL:$1|نسخه|نسخه}}",
        "nimagelinks": "مورد استفاده در $1 {{PLURAL:$1|صفحه|صفحه}}",
        "ntransclusions": "در $1 {{PLURAL:$1|صفحه|صفحه}} استفاده شده‌است",
        "changecontentmodel-title-label": "عنوان صفحه",
        "changecontentmodel-model-label": "نمونه محتوای جدید",
        "changecontentmodel-reason-label": "دلیل:",
+       "changecontentmodel-submit": "تغییر",
        "changecontentmodel-success-title": "نمونه محتوی تغییر یافت",
        "changecontentmodel-success-text": "نوع محتوی [[:$1]]  تغییر یافت",
        "changecontentmodel-cannot-convert": "محتوی در [[:$1]] نمی‌تواند به گونه‌ای از $2 تبدیل شود.",
        "ipb-unblock": "باز کردن نام کاربری یا نشانی آی‌پی",
        "ipb-blocklist": "دیدن قطع دسترسی‌های موجود",
        "ipb-blocklist-contribs": "مشارکت‌های $1",
+       "ipb-blocklist-duration-left": "$1 باقی مانده",
        "unblockip": "باز کردن کاربر",
        "unblockiptext": "برای بازگرداندن دسترسی نوشتن به یک نشانی آی‌پی یا نام کاربری بسته‌شده از فرم زیر استفاده کنید.",
        "ipusubmit": "باز کردن دسترسی",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} واردشده",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} واردشده از $2",
        "javascripttest": "آزمایش جاوا اسکریپت",
-       "javascripttest-pagetext-noframework": "این صفحه برای اجرای آزمایش‌های جاوا اسکریپت کنار گذاشته شده‌است.",
-       "javascripttest-pagetext-unknownframework": "چارچوب آزمایشی ناشناخته «$1».",
        "javascripttest-pagetext-unknownaction": "تابع ناشناختهٔ \"$1\".",
-       "javascripttest-pagetext-frameworks": "لطفاً یکی از چارچوب‌های آزمایش زیر را انتخاب کنید: $1",
-       "javascripttest-pagetext-skins": "پوسته‌ای را برای اجرای آزمایش‌ها انتخاب کنید:",
        "javascripttest-qunit-intro": "[$1 مستندات آزمایش] را در mediawiki.org ببینید.",
        "tooltip-pt-userpage": "صفحهٔ {{GENDER:|کاربری شما}}",
        "tooltip-pt-anonuserpage": "صفحهٔ کاربری نشانی آی‌پی‌ای که با آن ویرایش می‌کنید",
        "tooltip-ca-nstab-category": "دیدن صفحهٔ رده",
        "tooltip-minoredit": "این ویرایش را ویرایش جزئی نشانه‌گذاری کن",
        "tooltip-save": "تغییرات خود را ذخیره کنید",
-       "tooltip-preview": "پیش‌نمایش تغییرات شما، لطفاً قبل از ذخیرهکردن صفحه از این کلید استفاده کنید.",
+       "tooltip-preview": "پیش‌نمایش تغییرات شما، لطفاً قبل از ذخیره کردن صفحه از این کلید استفاده کنید.",
        "tooltip-diff": "نمایش تغییراتی که شما در متن داده‌اید.",
        "tooltip-compareselectedversions": "دیدن تفاوت‌های دو نسخهٔ انتخاب‌شده از این صفحه",
        "tooltip-watch": "این صفحه را به فهرست پی‌گیری‌هایتان بیفزایید.",
        "version-libraries-description": "توضیحات",
        "version-libraries-authors": "نویسندگان",
        "redirect": "تغییرمسیر توسط پرونده، کاربر، صفحه یا سیاههٔ شناسهٔ نسخه",
-       "redirect-legend": "تغییرمسیر به یک پرونده یا صفحه",
        "redirect-summary": "این صفحهٔ ویژه به پرونده (نام پرونده داده‌شده)، صفحه (شماره شناسهٔ صفحه یا شماره نسخهٔ داده‌شده) یا صفحهٔ کاربری (شناسهٔ عددی کاربری داده‌شده) تغییرمسیر می‌یابد. طرز استفاده: [[{{#Special:Redirect}}/file/Example.jpg]]، \n[[{{#Special:Redirect}}/page/64308]]، [[{{#Special:Redirect}}/revision/328429]] یا [[{{#Special:Redirect}}/user/101]] یا\n[[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "برو",
        "redirect-lookup": "جستجو:",
        "sessionprovider-generic": "$1 فصل",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "فصل‌های کوکی‌محور",
        "sessionprovider-nocookies": "کوکی‌ها ممکن است غیر فعال شده باشند. اطمینان کسب کنید که کوکی‌ها را فعال کرده‌اید و دوباره آغاز کنید.",
-       "randomrootpage": "صفحهٔ ریشهٔ تصادفی"
+       "randomrootpage": "صفحهٔ ریشهٔ تصادفی",
+       "log-action-filter-block": "نوع بسته شدن:",
+       "log-action-filter-delete": "نوع حذف:",
+       "log-action-filter-patrol": "نوع گشت:",
+       "log-action-filter-protect": "نوع محافظت",
+       "log-action-filter-upload": "نوع بارگذاری",
+       "log-action-filter-all": "همه",
+       "log-action-filter-block-block": "بستن",
+       "log-action-filter-block-unblock": "باز شدن",
+       "log-action-filter-delete-delete": "حذف صفحه",
+       "log-action-filter-delete-restore": "احیای صفحه",
+       "log-action-filter-delete-event": "حذف سیاهه",
+       "log-action-filter-patrol-autopatrol": "گشت خودکار",
+       "log-action-filter-protect-protect": "محافظت",
+       "log-action-filter-protect-unprotect": "خروج از محافظت",
+       "log-action-filter-upload-overwrite": "بارگذاری دوباره"
 }
index d8a5729..1782a7f 100644 (file)
@@ -47,7 +47,8 @@
                        "Macofe",
                        "Beluga",
                        "Pyscowicz",
-                       "Olimar"
+                       "Olimar",
+                       "Mikahama"
                ]
        },
        "tog-underline": "Linkkien alleviivaus:",
        "nocookieslogin": "{{SITENAME}} käyttää evästeitä sisäänkirjautumisen yhteydessä. Selaimesi ei salli evästeitä. Ota ne käyttöön, ja yritä uudelleen.",
        "nocookiesfornew": "Käyttäjätunnusta ei luotu, koska sen lähdettä ei kyetty varmistamaan. Varmista, että selaimessasi on käytössä evästeet, päivitä tämä sivu ja yritä uudelleen.",
        "noname": "Et ole määritellyt kelvollista käyttäjänimeä.",
-       "loginsuccesstitle": "Sisäänkirjautuminen onnistui",
+       "loginsuccesstitle": "Olet kirjautunut sisään",
        "loginsuccess": "'''Olet kirjautunut sivustolle {{SITENAME}} käyttäjänä $1.'''",
        "nosuchuser": "Käyttäjää ”$1” ei ole olemassa. Nimet ovat kirjainkoosta riippuvaisia. Tarkista kirjoititko nimen oikein, tai [[Special:UserLogin/signup|luo uusi käyttäjätunnus]].",
        "nosuchusershort": "Käyttäjää nimeltä ”$1” ei ole. Kirjoititko nimen oikein?",
        "newpassword": "Uusi salasana:",
        "retypenew": "Uusi salasana uudelleen:",
        "resetpass_submit": "Aseta salasana ja kirjaudu sisään",
-       "changepassword-success": "Salasanan vaihto onnistui.",
+       "changepassword-success": "Salasanasi on vaihdettu!",
        "changepassword-throttled": "Olet tehnyt liian monta äskettäistä kirjautumisyritystä.\nOdota $1 ennen kuin yrität uudelleen.",
        "botpasswords": "Botin salasanat",
        "botpasswords-disabled": "Botin salasanat on poistettu käytöstä.",
+       "botpasswords-label-appid": "Botin nimi:",
        "botpasswords-label-create": "Luo",
        "botpasswords-label-update": "Päivitä",
        "botpasswords-label-cancel": "Peru",
        "botpasswords-label-delete": "Poista",
        "botpasswords-label-resetpassword": "Uudista salasana",
        "botpasswords-label-grants": "Valittavissa olevat toimintaoikeudet:",
+       "botpasswords-label-restrictions": "Käyttörajoitukset:",
        "resetpass_forbidden": "Salasanoja ei voi vaihtaa.",
        "resetpass-no-info": "Et voi nähdä tätä sivua kirjautumatta sisään.",
        "resetpass-submit-loggedin": "Muuta salasana",
        "revdelete-unsuppress": "Poista rajoitukset palautetuilta versioilta",
        "revdelete-log": "Syy:",
        "revdelete-submit": "Toteuta {{PLURAL:$1|valittuun versioon|valittuihin versioihin}}",
-       "revdelete-success": "'''Version näkyvyys päivitetty.'''",
+       "revdelete-success": "Version näkyvyys päivitetty.",
        "revdelete-failure": "'''Version näkyvyyden muuttaminen ei onnistunut:'''\n$1",
-       "logdelete-success": "'''Lokitapahtuman näkyvyyttä on muutettu.'''",
+       "logdelete-success": "Lokitapahtuman näkyvyyttä on muutettu.",
        "logdelete-failure": "'''Lokin näkyvyyttä ei voitu asettaa:'''\n$1",
        "revdel-restore": "muuta näkyvyyttä",
        "pagehist": "Sivun muutoshistoria",
        "userrights-changeable-col": "Ryhmät, joita voit muuttaa",
        "userrights-unchangeable-col": "Ryhmät, joita et voi muuttaa",
        "userrights-conflict": "Päällekkäinen käyttöoikeuksien muutos! Tarkista tekemäsi muutokset ja vahvista ne.",
-       "userrights-removed-self": "Poistit onnistuneesti omat oikeutesi. Tämän jälkeen et enää pääse tälle sivulle.",
+       "userrights-removed-self": "Poistit omat oikeutesi. Tämän vuoksi sinulla ei enää ole oikeutta päästä tälle sivulle.",
        "group": "Ryhmä",
        "group-user": "käyttäjät",
        "group-autoconfirmed": "automaattisesti hyväksytyt käyttäjät",
        "recentchangeslinked-page": "Sivun nimi:",
        "recentchangeslinked-to": "Näytä sen sijaan muutokset sivuihin, joista on linkki tähän sivuun",
        "recentchanges-page-added-to-category": "[[:$1]] lisätty luokkaan",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] ja {{PLURAL:$2|one page|$2 pages}} lisätty luokkaan",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] ja [[Special:WhatLinksHere/$1|{{PLURAL:$2|yksi sivu|$2 sivua}}]] lisätty luokkaan",
        "recentchanges-page-removed-from-category": "[[:$1]] poistettu luokasta",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] ja {{PLURAL:$2|one page|$2 pages}} poistettu luokasta",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] ja [[Special:WhatLinksHere/$1|{{PLURAL:$2|yksi sivu|$2 sivua}}]] poistettu luokasta",
        "autochange-username": "MediaWiki automaattinen muutos",
        "upload": "Tallenna tiedosto",
        "uploadbtn": "Tallenna tiedosto",
        "uploadstash-summary": "Tämä sivu tarjoaa pääsyn tiedostoihin, jotka on tallennettu tai joiden tallennus on käynnissä, mutta joita ei ole vielä julkaistu tässä wikissä. Vain tiedostot tallentanut käyttäjä voi tarkastella näitä tiedostoja.",
        "uploadstash-clear": "Poista muistissa olevat tiedostot",
        "uploadstash-nofiles": "Sinulla ei ole muistissa olevia tiedostoja.",
-       "uploadstash-badtoken": "Toiminnon suoritus epäonnistui. Tähän voi olla syynä muokkausvaltuuksien vanhentuminen. Yritä uudelleen.",
-       "uploadstash-errclear": "Muistin tyhjennys epäonnistui.",
+       "uploadstash-badtoken": "Toiminnon suorittaminen epäonnistui. Tähän saattaa olla syynä muokkausvaltuuksiesi vanhentuminen. Yritä uudelleen.",
+       "uploadstash-errclear": "Tiedostojen tyhjentäminen epäonnistui.",
        "uploadstash-refresh": "Päivitä tiedostoluettelo",
+       "uploadstash-thumbnail": "näytä pienoiskuva",
        "invalid-chunk-offset": "Kelpaamaton siirtymä lohkoissa",
        "img-auth-accessdenied": "Pääsy estetty",
        "img-auth-nopathinfo": "PATH_INFO puuttuu.\nPalvelintasi ei ole asetettu välittämään tätä tietoa.\nSe saattaa olla CGI-pohjainen eikä voi tukea img_authia.\nLisätietoja löytyy sivulta https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "statistics-header-hooks": "Muut tilastot",
        "statistics-articles": "Sisältösivuja",
        "statistics-pages": "Sivuja",
-       "statistics-pages-desc": "Kaikki sivut, sisältäen keskustelusivut, ohjaukset ja muut.",
+       "statistics-pages-desc": "Kaikki wikissä olevat sivut, mukaan lukien keskustelusivut, ohjaussivut ynnä muut.",
        "statistics-files": "Tallennettuja tiedostoja",
        "statistics-edits": "Muokkauksia {{GRAMMAR:genitive|{{SITENAME}}}} perustamisen jälkeen",
-       "statistics-edits-average": "Keskimäärin yhtä sivua muokattu",
+       "statistics-edits-average": "Muokkausten keskiarvo yhdellä sivulla",
        "statistics-users": "Rekisteröityneitä [[Special:ListUsers|käyttäjiä]]",
        "statistics-users-active": "Aktiivisia käyttäjiä",
        "statistics-users-active-desc": "Käyttäjät, jotka ovat suorittaneet jonkin toiminnon {{PLURAL:$1|edellisen päivän|edellisten $1 päivän}} aikana.",
        "apisandbox-api-disabled": "API on poistettu käytöstä tällä sivustolla.",
        "apisandbox-intro": "Tämä on '''MediaWiki API:n''' hiekkalaatikko.\n[//www.mediawiki.org/wiki/API:Main_page API-dokumentaatio] kertoo lisää API:en käytöstä.",
        "apisandbox-fullscreen": "Laajenna paneeli",
-       "apisandbox-unfullscreen": "Näytä sivu",
+       "apisandbox-unfullscreen": "Palaa sivunäkymään",
        "apisandbox-submit": "Tee pyyntö",
        "apisandbox-reset": "Tyhjennä",
        "apisandbox-retry": "Yritä uudestaan",
        "delete-toobig": "Tällä sivulla on pitkä muokkaushistoria, yli $1 {{PLURAL:$1|versio|versiota}}. \nTämänkaltaisten sivujen poistamista on rajoitettu. Tällä ehkäistään sivuston {{SITENAME}} vaurioitumista tahattomasti.",
        "delete-warning-toobig": "Tällä sivulla on pitkä muutoshistoria – yli $1 {{PLURAL:$1|versio|versiota}}. Näin suurien muutoshistorioiden poistaminen voi haitata sivuston suorituskykyä.",
        "deleteprotected": "Et voi poistaa tätä sivua, koska se on suojattu.",
-       "deleting-backlinks-warning": "'''Varoitus:''' Sivulle, jota olet poistamassa, johtaa [[Special:WhatLinksHere/{{FULLPAGENAME}}|linkkejä muilta sivuilta]], tai sivu on sisällytetty muuhun sivuun.",
+       "deleting-backlinks-warning": "<strong>Varoitus:</strong> Sivulle, jota olet poistamassa, johtaa [[Special:WhatLinksHere/{{FULLPAGENAME}}|linkkejä muilta sivuilta]], taikka sivu on sisällytetty muuhun sivuun.",
        "rollback": "palauta aiempaan versioon",
        "rollbacklink": "palauta",
        "rollbacklinkcount": "palauta $1 {{PLURAL:$1|muutos|muutosta}}",
        "changecontentmodel-title-label": "Sivun otsikko",
        "changecontentmodel-model-label": "Uusi sisältömalli",
        "changecontentmodel-reason-label": "Syy:",
+       "changecontentmodel-submit": "Tee muutos",
        "changecontentmodel-success-title": "Sisältömallia on muutettu",
        "changecontentmodel-success-text": "Sisältötyyppiä kohteessa [[:$1]] on muutettu.",
        "changecontentmodel-cannot-convert": "Sisältöä sivulla [[:$1]] ei voida muuntaa tyypiksi $2.",
        "changecontentmodel-nodirectediting": "Sisältömalli $1 ei tue suoraa muokkaamista",
        "log-name-contentmodel": "Sisältömallin muutosloki",
        "log-description-contentmodel": "Tapahtumat, jotka liittyvät sivun sisältömalleihin",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|loi}} sivun $3 käyttäen normaalista poikkeavaa sisältömallia \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|muutti}} sivun $3 sisältömallia muodosta \"$4\" muotoon \"$5\"",
        "logentry-contentmodel-change-revertlink": "kumoa",
        "logentry-contentmodel-change-revert": "kumottu",
        "ipb-unblock": "Poista käyttäjän tai IP-osoitteen muokkausesto",
        "ipb-blocklist": "Näytä voimassa olevat estot",
        "ipb-blocklist-contribs": "Käyttäjän {{GENDER:$1|$1}} muokkaukset",
+       "ipb-blocklist-duration-left": "$1 jäljellä",
        "unblockip": "Muokkauseston poisto käyttäjältä",
        "unblockiptext": "Tällä lomakkeella voit poistaa käyttäjän tai IP-osoitteen muokkauseston.",
        "ipusubmit": "Poista tämä esto",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|versio|versiota}} tuotiin",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versio|versiota}} tuotiin wikistä $2",
        "javascripttest": "JavaScriptin testaus",
-       "javascripttest-pagetext-noframework": "Tämä sivu on varattu JavaScript-testien suorittamiseen.",
-       "javascripttest-pagetext-unknownframework": "Tuntematon testausalusta $1.",
        "javascripttest-pagetext-unknownaction": "Tuntematon toiminto \"$1\".",
-       "javascripttest-pagetext-frameworks": "Valitse yksi seuraavista testausalustoista: $1",
-       "javascripttest-pagetext-skins": "Valitse testauksessa käytettävä ulkoasu",
        "javascripttest-qunit-intro": "Katso [$1 testausohjeet] mediawiki.orgissa.",
        "tooltip-pt-userpage": "{{GENDER:|Oma käyttäjäsivusi}}",
        "tooltip-pt-anonuserpage": "IP-osoitteesi käyttäjäsivu",
        "patrol-log-page": "Muutostentarkastusloki",
        "patrol-log-header": "Tämä on loki tarkastetuista muutoksista.",
        "log-show-hide-patrol": "$1 muutostentarkastusloki",
-       "log-show-hide-tag": "$1 merkkausten loki",
+       "log-show-hide-tag": "$1 merkkausloki",
        "deletedrevision": "Poistettiin vanha versio $1",
        "filedeleteerror-short": "Tiedoston $1 poistaminen epäonnistui",
        "filedeleteerror-long": "Tiedoston poistaminen epäonnistui:\n\n$1",
        "version-libraries-description": "Kuvaus",
        "version-libraries-authors": "Tekijät",
        "redirect": "Ohjaus tiedoston, käyttäjän, sivun, sivuversion tai lokin tunnistenumeron mukaan",
-       "redirect-legend": "Ohjaus tiedostoon tai sivulle",
        "redirect-summary": "Tämä toimintosivu ohjaa tiedostoon (tiedostonimen mukaan), sivulle (version tunnistenumeron tai sivun tunnistenumeron mukaan), käyttäjäsivulle (käyttäjän tunnistenumeron mukaan) taikka lokimerkintään (lokin tunnistenumeron mukaan). Käytetään seuraavasti: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]],[[{{#Special:Redirect}}/user/101]] tai [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Siirry",
        "redirect-lookup": "Hae:",
        "tags-delete-not-allowed": "Sellaisia merkkauksia, jotka tulevat erityisestä ohjelmistolaajennuksesta, ei voi poistaa ennen kuin tämä laajennus erityisesti sallii sen.",
        "tags-delete-not-found": "Merkkausta \"$1\" ei ole olemassa.",
        "tags-delete-too-many-uses": "Tämä merkkaus \"$1\" on käytössä useammassa kuin $2 sivuversiossa, joten sitä ei voi poistaa.",
-       "tags-delete-warnings-after-delete": "Merkkaus \"$1\" poistettiin onnistuneesta, mutta {{PLURAL:$2|seuraava varoitus|seuraavat varoitukset}} ilmeni samalla:",
+       "tags-delete-warnings-after-delete": "Merkkaus \"$1\" poistettiin, mutta toimenpide sai aikaan {{PLURAL:$2|seuraavan varoituksen|seuraavat varoitukset}}:",
        "tags-activate-title": "Aktivoi merkkaus",
        "tags-activate-question": "Olet nyt aktivoimassa merkkausta \"$1\".",
        "tags-activate-reason": "Syy:",
        "tags-edit-reason": "Syy:",
        "tags-edit-revision-submit": "Toteuta muutokset {{PLURAL:$1|tähän versioon|$1 versioon}}",
        "tags-edit-logentry-submit": "Lähetä muutoksesi {{PLURAL:$1|tähän lokimerkintään|$1 lokimerkintään}}",
-       "tags-edit-success": "Muutokset on onnistuneesti toteutettu.",
+       "tags-edit-success": "Muutokset on tehty.",
        "tags-edit-failure": "Muutoksia ei voitu toteuttaa: $1",
        "tags-edit-nooldid-title": "Kohdeversio ei ole kelvollinen",
        "tags-edit-nooldid-text": "Et ole joko määrittänyt sitä kohdeversiota, johon tämä toimenpide kohdistuu, tai sitten määrättyä versiota ei ole olemassa.",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|suojasi}} kohteen $3 $4 [tarttuvasti]",
        "logentry-protect-modify": "$1 {{GENDER:$2|muutti}} suojauksen tasoa kohteessa $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|muutti}} suojauksen tasoa kohteessa $3 $4 [tarttuvasti]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|muutti}} käyttäjän $3 oikeudet ryhmistä $4 ryhmiin $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|muutti}} käyttäjän {{GENDER:$3|$3}} oikeudet ryhmistä $4 ryhmiin $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|muutti}} käyttäjän $3 jäsenyyttä ryhmässä",
        "logentry-rights-autopromote": "Käyttäjän $1 oikeudet {{GENDER:$2|muuttuivat}} automaattisesti ryhmistä $4 ryhmiin $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|tallensi}} tiedoston $3",
        "special-characters-group-ipa": "Kansainvälinen foneettinen kirjaimisto (IPA)",
        "special-characters-group-symbols": "Symbolit",
        "special-characters-group-greek": "Kreikka",
+       "special-characters-group-greekextended": "Laajennettu kreikka",
        "special-characters-group-cyrillic": "Kyrillinen",
        "special-characters-group-arabic": "Arabia",
        "special-characters-group-arabicextended": "Laajennettu arabia",
        "sessionprovider-generic": "$1 istuntoa",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "istuntoja, joissa on evästeet käytössä",
        "sessionprovider-nocookies": "Evästeet on voitu poistaa käytöstä. Varmista, että sinulla on evästeet käytössä ja yritä sitten uudelleen.",
-       "randomrootpage": "Satunnainen juurisivu"
+       "randomrootpage": "Satunnainen juurisivu",
+       "log-action-filter-block": "Eston tyyppi:",
+       "log-action-filter-delete": "Poiston tyyppi:",
+       "log-action-filter-patrol": "Tarkastuksen tyyppi:",
+       "log-action-filter-protect": "Suojauksen tyyppi:",
+       "log-action-filter-upload": "Tallennuksen tyyppi:",
+       "log-action-filter-all": "Kaikki",
+       "log-action-filter-block-block": "Eston asettaminen",
+       "log-action-filter-block-reblock": "Estoasetusten muuttaminen",
+       "log-action-filter-block-unblock": "Eston poistaminen",
+       "log-action-filter-delete-delete": "Sivun poistaminen",
+       "log-action-filter-delete-restore": "Sivun palauttaminen",
+       "log-action-filter-delete-event": "Lokimerkinnän poistaminen",
+       "log-action-filter-delete-revision": "Version piilottaminen",
+       "log-action-filter-protect-protect": "Suojauksen asettaminen",
+       "log-action-filter-protect-modify": "Suojausasetusten muuttaminen",
+       "log-action-filter-protect-unprotect": "Suojauksen poistaminen",
+       "log-action-filter-upload-upload": "Uusi tallennus",
+       "log-action-filter-upload-overwrite": "Päälletallennus"
 }
index a0ef809..ffa35ca 100644 (file)
                        "StevenJ81",
                        "The RedBurn",
                        "Fredlefred",
-                       "Lbayle"
+                       "Lbayle",
+                       "Cl3m3n7",
+                       "C13m3n7",
+                       "Gnangbade"
                ]
        },
        "tog-underline": "Soulignement des liens :",
        "viewyourtext": "Vous pouvez voir et copier le contenu de <strong>vos modifications</strong> à cette page.",
        "protectedinterface": "Cette page fournit du texte d'interface pour le logiciel sur ce wiki, et est protégée pour éviter les abus.\nPour ajouter ou modifier des traductions sur tous les wikis, veuillez utiliser [//translatewiki.net/ translatewiki.net], le projet de localisation de MediaWiki.",
        "editinginterface": "<strong>Attention :</strong> vous êtes en train de modifier une page utilisée pour créer le texte de l’interface du logiciel.\nLes changements sur cette page se répercuteront sur l’apparence de l’interface utilisateur pour les autres utilisateurs de ce wiki.",
-       "translateinterface": "Pour ajouter ou modifier des traductions pour tous les wikis, veuillez utiliser [//translatewiki.net/ translatewiki.net], le projet de localisation de MédiaWiki.",
+       "translateinterface": "Pour ajouter ou modifier des traductions pour tous les wikis, veuillez utiliser [//translatewiki.net/ translatewiki.net], le projet de localisation de MediaWiki.",
        "cascadeprotected": "Cette page est protégée contre les modifications car elle est transcluse par {{PLURAL:$1|la page suivante, qui a été protégée|les pages suivantes, qui ont été protégées}} avec l’option « protection en cascade » activée :\n$2",
        "namespaceprotected": "Vous n'avez pas la permission de modifier les pages de l'espace de noms « '''$1''' ».",
        "customcssprotected": "Vous n'avez pas la permission de modifier cette page de CSS, car elle contient les paramètres personnels d'un autre utilisateur.",
        "nocookieslogin": "{{SITENAME}} utilise des cookies pour la connexion mais vous les avez désactivés. Veuillez les activer et vous reconnecter.",
        "nocookiesfornew": "Le compte utilisateur n'a pas été créé, car nous n'avons pas pu identifier son origine.\nVérifiez que vous avez activé les cookies, rechargez la page et réessayez.",
        "noname": "Vous n'avez pas saisi un nom d'utilisateur valide.",
-       "loginsuccesstitle": "Connexion réussie",
+       "loginsuccesstitle": "Connecté",
        "loginsuccess": "Vous êtes maintenant connecté{{GENDER:$1||e}} à {{SITENAME}} en tant que « $1 ».",
        "nosuchuser": "L'utilisateur « $1 » n'existe pas.\nLes noms d'utilisateurs sont sensibles à la casse.\nVérifiez l'orthographe, ou [[Special:UserLogin/signup|créez un nouveau compte]].",
        "nosuchusershort": "Il n'y a pas de contributeur avec le nom « $1 ». Veuillez vérifier l'orthographe.",
        "noemail": "Aucune adresse de courriel n'a été enregistrée pour l'utilisateur « $1 ».",
        "noemailcreate": "Vous devez fournir une adresse de courriel valide",
        "passwordsent": "Un nouveau mot de passe a été envoyé à l'adresse de courriel de l'utilisateur « $1 ». Veuillez vous reconnecter après l'avoir reçu.",
-       "blocked-mailpassword": "Votre adresse IP est bloquée en écriture, la fonction de rappel du mot de passe est donc désactivée pour éviter les abus.",
+       "blocked-mailpassword": "Votre adresse IP est bloquée pour la modification. Pour éviter les abus, il n’est pas autorisé d’utiliser la récupération de mot de passe à partir de cette adresse IP.",
        "eauthentsent": "Un courriel de confirmation a été envoyé à l’adresse indiquée.\nAvant qu’un autre courriel ne soit envoyé à ce compte, vous devrez suivre les instructions du courriel et confirmer que le compte est bien le vôtre.",
        "throttled-mailpassword": "Un courriel de réinitialisation de votre mot de passe a déjà été envoyé durant {{PLURAL:$1|la dernière heure|les $1 dernières heures}}. Afin d'éviter les abus, un seul courriel de réinitialisation de votre mot de passe sera envoyé par {{PLURAL:$1|heure|intervalle de $1 heures}}.",
        "mailerror": "Erreur lors de l'envoi du courriel : $1",
        "newpassword": "Nouveau mot de passe :",
        "retypenew": "Confirmer le nouveau mot de passe :",
        "resetpass_submit": "Changer le mot de passe et se connecter",
-       "changepassword-success": "Votre mot de passe a été changé avec succès !",
+       "changepassword-success": "Votre mot de passe a été modifié !",
        "changepassword-throttled": "Vous avez fait trop de tentatives de connexion récemment.\nVeuillez attendre $1 avant de réessayer.",
        "botpasswords": "Mots de passe de robots",
        "botpasswords-summary": "<em>Mots de passe de robots</em> permet d’accéder à un compte utilisateur via l’API sans utiliser les identifiants de connexion principaux. Les droits utilisateur disponibles en étant connecté avec un mot de passe robot peuvent être réduits.\n\nSi vous ne voyez pas pourquoi vous voudriez faire cela, c’est que vous n’en avez pas besoin. Personne ne devrait jamais vous demander d’en générer un et de le lui donner.",
        "botpasswords-insert-failed": "Échec de l’ajout du nom de robot « $1 ». A-t-il déjà été ajouté ?",
        "botpasswords-update-failed": "Échec à la mise à jour du nom de robot « $1 ». A-t-il déjà été supprimé ?",
        "botpasswords-created-title": "Mot de passe de robots créé",
-       "botpasswords-created-body": "Le mot de passe de robots « $1 » a bien été créé.",
+       "botpasswords-created-body": "Le mot de passe pour le robot « $1 » de l'utilisateur « $2 » a été créé.",
        "botpasswords-updated-title": "Mot de passe de robots mis à jour",
-       "botpasswords-updated-body": "Le mot de passe de robots « $1 » a bien été mis à jour.",
+       "botpasswords-updated-body": "Le mot de passe pour le robot « $1 » de l'utilisateur « $2 » a été mis à jour.",
        "botpasswords-deleted-title": "Mot de passe de robots supprimé",
-       "botpasswords-deleted-body": "Le mot de passe de robots « $1 » a été supprimé.",
+       "botpasswords-deleted-body": "Le mot de passe pour le robot « $1 » de l'utilisateur « $2 » a été supprimé.",
        "botpasswords-newpassword": "Le nouveau mot de passe pour se connecter avec <strong>$1</strong> est <strong>$2</strong>. <em>Veuillez l’enregistrer pour y faire référence ultérieurement.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider n’est pas disponible.",
        "botpasswords-restriction-failed": "Les restrictions de mot de passe de robots empêchent cette connexion.",
        "rev-deleted-event": "(détails de l’entrée retirée)",
        "rev-deleted-user-contribs": "[nom d'utilisateur ou adresse IP retiré - modification masquée sur les contributions]",
        "rev-deleted-text-permission": "Cette version de la page a été '''effacée'''.\nDes détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
-       "rev-suppressed-text-permission": "Cette version de la page a été <strong>supprimée</strong>.\nLes détails se trouvent dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].",
-       "rev-deleted-text-unhide": "Cette version de la page a été '''effacée'''.\nDes détails sont disponibles dans [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} le journal des suppressions].\nVous pouvez toujours [$1 voir cette version] si vous le voulez.",
-       "rev-suppressed-text-unhide": "Cette version de la page a été '''supprimée'''.\nDes détails sont disponibles dans [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} le journal des masquages].\nVous pouvez toujours [$1 voir cette version] si vous le voulez.",
-       "rev-deleted-text-view": "Cette version de la page a été '''effacée'''.\nVous pouvez la visualiser ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
-       "rev-suppressed-text-view": "Cette version de la page a été '''supprimée'''.\nVous pouvez la visualiser ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].",
-       "rev-deleted-no-diff": "Vous ne pouvez pas voir ce diff parce qu'une des versions a été '''effacée'''.\nDes détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
-       "rev-suppressed-no-diff": "Vous ne pouvez pas voir cette différence car une des révisions a été '''supprimée'''.",
-       "rev-deleted-unhide-diff": "Une des révisions de cette différence a été '''effacée'''.\nDes détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].\nVous pouvez toujours [$1 voir cette différence] si vous le voulez.",
-       "rev-suppressed-unhide-diff": "L'une des révisions de ce diff a été '''supprimée'''.\nDes détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].\nVous pouvez toujours [$1 voir ce diff] si vous souhaitez poursuivre.",
-       "rev-deleted-diff-view": "Une des révisions de ce diff a été '''effacée'''.\nVous pouvez voir ce diff ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
-       "rev-suppressed-diff-view": "Une des révisions de ce diff a été '''supprimée'''.\nVous pouvez voir ce diff ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].",
+       "rev-suppressed-text-permission": "Cette version de la page a été <strong>masquée</strong>.\nLes détails se trouvent dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].",
+       "rev-deleted-text-unhide": "Cette version de la page a été <strong>supprimée</strong>.\nDes détails sont disponibles dans [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} le journal des suppressions].\nVous pouvez toujours [$1 voir cette version] si vous le voulez.",
+       "rev-suppressed-text-unhide": "Cette version de la page a été <strong>masquée</strong>.\nDes détails sont disponibles dans [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} le journal des masquages].\nVous pouvez toujours [$1 voir cette version] si vous le voulez.",
+       "rev-deleted-text-view": "Cette version de la page a été <strong>supprimée</strong>.\nVous pouvez la visualiser ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
+       "rev-suppressed-text-view": "Cette version de la page a été <strong>masquée</strong>.\nVous pouvez la visualiser ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].",
+       "rev-deleted-no-diff": "Vous ne pouvez pas voir ce diff parce qu'une des versions a été <strong>supprimée</strong>.\nDes détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
+       "rev-suppressed-no-diff": "Vous ne pouvez pas voir cette différence car une des révisions a été <strong>masquée</strong>.",
+       "rev-deleted-unhide-diff": "Une des révisions de cette différence a été <strong>supprimée</strong>.\nDes détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].\nVous pouvez toujours [$1 voir cette différence] si vous le voulez.",
+       "rev-suppressed-unhide-diff": "L’une des révisions de ce diff a été <strong>masquée</strong>.\nDes détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].\nVous pouvez toujours [$1 voir ce diff] si vous souhaitez poursuivre.",
+       "rev-deleted-diff-view": "Une des révisions de ce diff a été <strong>supprimée</strong>.\nVous pouvez voir ce diff ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
+       "rev-suppressed-diff-view": "Une des révisions de ce diff a été <strong>masquée</strong>.\nVous pouvez voir ce diff ; des détails sont disponibles dans le [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} journal des masquages].",
        "rev-delundel": "afficher/masquer",
        "rev-showdeleted": "afficher",
        "revisiondelete": "Supprimer ou restaurer des événements",
        "revdelete-unsuppress": "Enlever les restrictions sur les versions restaurées",
        "revdelete-log": "Motif :",
        "revdelete-submit": "Appliquer {{PLURAL:$1|à la révision sélectionnée|aux révisions sélectionnées}}",
-       "revdelete-success": "'''Visibilité des versions mise à jour avec succès.'''",
+       "revdelete-success": "Visibilité des versions mise à jour.",
        "revdelete-failure": "'''La visibilité de la version n'a pas pu être mise à jour :'''\n$1",
-       "logdelete-success": "'''Visibilité du journal paramétrée avec succès.'''",
+       "logdelete-success": "Visibilité du journal modifiée.",
        "logdelete-failure": "'''La visibilité du journal n'a pas pu être définie :'''\n$1",
        "revdel-restore": "modifier la visibilité",
        "pagehist": "Historique de la page",
        "rows": "Rangées :",
        "columns": "Colonnes :",
        "searchresultshead": "Filtrer avec cette valeur",
-       "stub-threshold": "Seuil pour le formatage des liens bouchons ($1) :",
+       "stub-threshold": "Seuil pour le formatage des liens d’ébauche ($1) :",
        "stub-threshold-sample-link": "exemple",
        "stub-threshold-disabled": "Désactivé",
        "recentchangesdays": "Nombre de jours à afficher dans les modifications récentes :",
        "userrights-changeable-col": "Les groupes que vous pouvez modifier",
        "userrights-unchangeable-col": "Les groupes que vous ne pouvez pas modifier",
        "userrights-conflict": "Conflit de modification de droits utilisateur ! Veuillez relire et confirmer vos modifications.",
-       "userrights-removed-self": "Vous avez bien supprimé vos propres droits. Du coup, vous ne pouvez plus accéder à cette page.",
+       "userrights-removed-self": "Vous avez supprimé vos propres droits. Par conséquent, vous ne pouvez plus accéder à cette page.",
        "group": "Groupe :",
        "group-user": "Utilisateurs",
        "group-autoconfirmed": "Utilisateurs autoconfirmés",
        "grant-createaccount": "Créer des comptes",
        "grant-createeditmovepage": "Créer, modifier et déplacer des pages",
        "grant-delete": "Supprimer les pages, les révisions et les entrées du journal",
-       "grant-editinterface": "Modifier l’espace de noms MédiaWiki et le CSS/JavaScript utilisateur",
+       "grant-editinterface": "Modifier l’espace de noms MediaWiki et le CSS/JavaScript utilisateur",
        "grant-editmycssjs": "Modifier votre CSS/JavaScript utilisateur",
        "grant-editmyoptions": "Modifier vos préférences utilisateur",
        "grant-editmywatchlist": "Modifier votre liste de suivi",
        "recentchangeslinked-page": "Nom de la page :",
        "recentchangeslinked-to": "Afficher les modifications des pages qui comportent un lien vers la page donnée plutôt que l'inverse",
        "recentchanges-page-added-to-category": "[[:$1]] ajouté à la catégorie",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] et {{PLURAL:$2|une page ajoutée|$2 pages ajoutées}} à la catégorie",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] et [[Special:WhatLinksHere/$1|{{PLURAL:$2|une page ajoutée|$2 pages ajoutées}}]] à la catégorie",
        "recentchanges-page-removed-from-category": "[[:$1]] supprimé de la catégorie",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] et {{PLURAL:$2|une page retirée|$2 pages retirées}} de la catégorie",
-       "autochange-username": "Modification automatique de MédiaWiki",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] et [[Special:WhatLinksHere/$1|{{PLURAL:$2|une page|$2 pages}}]] {{PLURAL:$2|retirée|retirées}} de la catégorie",
+       "autochange-username": "Modification automatique de MediaWiki",
        "upload": "Importer un fichier",
        "uploadbtn": "Importer le fichier",
        "reuploaddesc": "Annuler et retourner au formulaire d'import",
        "upload-foreign-cant-upload": "Ce wiki n’est pas configuré pour télécharger des fichiers vers le dépôt de fichiers externe demandé.",
        "upload-dialog-title": "Téléverser un fichier",
        "upload-dialog-button-cancel": "Annuler",
-       "upload-dialog-button-done": "Fait",
+       "upload-dialog-button-done": "Terminé",
        "upload-dialog-button-save": "Enregistrer",
        "upload-dialog-button-upload": "Téléverser",
        "upload-form-label-infoform-title": "Détails",
        "uploadstash-summary": "Cette page donne accès aux fichiers qui sont importés (ou en cours d’importation), mais ne sont pas encore publiés dans le wiki. Ces fichiers ne sont pas encore visibles, sauf pour l’utilisateur qui les a importés.",
        "uploadstash-clear": "Effacer les fichiers en cache",
        "uploadstash-nofiles": "Vous n’avez pas de fichiers en cache d’import.",
-       "uploadstash-badtoken": "L’exécution de cette action a échoué, peut-être parce que vos informations d’identification ont expiré. Réessayez.",
+       "uploadstash-badtoken": "L’exécution de cette action a échoué, peut-être parce que vos informations d’identification ont expiré. Veuillez réessayer.",
        "uploadstash-errclear": "La suppression des fichiers a échoué.",
        "uploadstash-refresh": "Actualiser la liste des fichiers",
+       "uploadstash-thumbnail": "afficher la vignette",
        "invalid-chunk-offset": "Offset de segment non valide",
        "img-auth-accessdenied": "Accès refusé",
        "img-auth-nopathinfo": "PATH_INFO manquant.\nVotre serveur n'est pas paramétré pour transmettre cette information.\nIl fonctionne peut-être en CGI et ne supporte pas img_auth.\nVoir : https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "apisandbox-fullscreen": "Développer le panneau",
        "apisandbox-fullscreen-tooltip": "Étendre le panneau du bac à sable pour remplir la fenêtre du navigateur.",
        "apisandbox-unfullscreen": "Afficher la page",
-       "apisandbox-unfullscreen-tooltip": "Réduire le panneau du bac à sable, pour que les liens de navigation de MédiaWiki soient disponibles.",
+       "apisandbox-unfullscreen-tooltip": "Réduire le panneau du bac à sable, pour que les liens de navigation de MediaWiki soient disponibles.",
        "apisandbox-submit": "Faire la demande",
        "apisandbox-reset": "Effacer",
        "apisandbox-retry": "Réessayer",
        "changecontentmodel-title-label": "Titre de la page",
        "changecontentmodel-model-label": "Nouveau modèle de contenu",
        "changecontentmodel-reason-label": "Motif :",
+       "changecontentmodel-submit": "Modifier",
        "changecontentmodel-success-title": "Le modèle de contenu a été modifié",
        "changecontentmodel-success-text": "Le modèle de contenu de [[:$1]] a été modifié.",
        "changecontentmodel-cannot-convert": "Le contenu sur [[:$1]] n’a pas pu être converti en un type de $2.",
        "ipb-unblock": "Débloquer un compte utilisateur ou une adresse IP",
        "ipb-blocklist": "Voir les blocages existants",
        "ipb-blocklist-contribs": "Contributions pour {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 restant",
        "unblockip": "Débloquer un utilisateur ou une adresse IP",
        "unblockiptext": "Utilisez le formulaire ci-dessous pour redonner les droits d’écriture à une adresse IP ou un nom d’utilisateur.",
        "ipusubmit": "Supprimer ce blocage",
        "unblock-hideuser": "Vous ne pouvez pas débloquer cet utilisateur, car son nom d’utilisateur a été masqué.",
        "ipb_cant_unblock": "Erreur : identifiant de blocage $1 non trouvé.\nIl est possible qu'un déblocage ait déjà été effectué.",
        "ipb_blocked_as_range": "Erreur : l'adresse IP $1 n'est pas bloquée directement et ne peut donc pas être débloquée.\nElle fait cependant partie de la plage $2 qui, elle, peut être débloquée.",
-       "ip_range_invalid": "Plage IP incorrecte.",
+       "ip_range_invalid": "Plage d’adresses IP incorrecte.",
        "ip_range_toolarge": "Les blocages de plages plus grandes que /$1 ne sont pas autorisées.",
        "proxyblocker": "Bloqueur de mandataires",
        "proxyblockreason": "Votre adresse IP a été bloquée car il s'agit d'un mandataire ouvert.\nVeuillez contacter votre fournisseur d'accès Internet ou votre support technique et l'informer de ce sérieux problème de sécurité.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|révision importée|révisions importées}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|révision importée|révisions importées}} depuis $2",
        "javascripttest": "Test de JavaScript",
-       "javascripttest-pagetext-noframework": "Cette page est réservée pour l'exécution des tests JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Structure « $1 » inconnue.",
        "javascripttest-pagetext-unknownaction": "Action « $1 » inconnue.",
-       "javascripttest-pagetext-frameworks": "Veuillez choisir l'une des structures de test suivantes : $1",
-       "javascripttest-pagetext-skins": "Choisissez un habillage avec lequel lancer les tests :",
        "javascripttest-qunit-intro": "Voir [$1 la documentation de test] sur mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Votre}} page utilisateur",
        "tooltip-pt-anonuserpage": "La page utilisateur de l'IP avec laquelle vous contribuez",
        "version-libraries-description": "Description",
        "version-libraries-authors": "Auteurs",
        "redirect": "Rediriger par ID de fichier, utilisateur, page, révision ou journal",
-       "redirect-legend": "Rediriger vers une page ou un fichier",
        "redirect-summary": "Cette page spéciale redirige vers un fichier (nom de fichier fourni), une page (ID de révision ou de page fourni), une page d’utilisateur (identifiant numérique de l’utilisateur fourni), ou une entrée de journal (ID du journal fourni). Utilisation : [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], ou [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Valider",
        "redirect-lookup": "Recherche :",
        "tags-delete-not-allowed": "Les balises définies par une extension ne peuvent pas être supprimées, à moins que l'extension ne le permette spécifiquement.",
        "tags-delete-not-found": "La balise « $1 » n’existe pas.",
        "tags-delete-too-many-uses": "La balise « $1 » est appliquée à plus de $2 {{PLURAL:$2|révision|révisions}}, ce qui signifie qu'elle ne peut pas être supprimée.",
-       "tags-delete-warnings-after-delete": "La balise « $1 » a été supprimée avec succès, mais {{PLURAL:$2|l' avertissement suivant a|avertissements suivants ont}} été rencontré{{PLURAL:$2||s}} :",
+       "tags-delete-warnings-after-delete": "La balise « $1 » a été supprimée, mais {{PLURAL:$2|l’avertissement suivant a|les avertissements suivants ont}} été rencontré{{PLURAL:$2||s}} :",
        "tags-activate-title": "Activer la balise",
        "tags-activate-question": "Vous êtes sur le point d'activer la balise « $1 ».",
        "tags-activate-reason": "Motif :",
        "tags-edit-reason": "Motif :",
        "tags-edit-revision-submit": "Appliquer les modifications à {{PLURAL:$1|cette révision|$1 révisions}}",
        "tags-edit-logentry-submit": "Appliquer les modifications à {{PLURAL:$1|cette entrée de journal|$1 entrées de journal}}",
-       "tags-edit-success": "Les modifications ont été appliquées avec succès.",
+       "tags-edit-success": "Les modifications ont été appliquées.",
        "tags-edit-failure": "Les modifications n’ont pas pu être appliquées :\n$1",
        "tags-edit-nooldid-title": "Révision cible non valide",
        "tags-edit-nooldid-text": "Vous n’avez soit pas spécifié de révision cible sur laquelle exécuter cette fonction, soit la révision spécifiée n’existe pas.",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|a protégé}} $3 $4 [protection en cascade]",
        "logentry-protect-modify": "$1 {{GENDER:$2|a modifié}} le niveau de protection de $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|a modifié}} le niveau de protection de $3 $4 [protection en cascade]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|a modifié}} l'appartenance au groupe pour $3 de $4 à $5",
+       "logentry-rights-rights": "$1 a modifié l’appartenance au groupe pour $3 de $4 à $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|a modifié}} l'appartenance au groupe pour $3",
        "logentry-rights-autopromote": "$1 {{GENDER:$2|a été promu}} automatiquement de $4 à $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|a téléchargé}} $3",
        "feedback-bugnew": "J'ai vérifié. Signaler un nouveau bogue",
        "feedback-bugornote": "Si vous êtes prêt à décrire un problème technique en détail, veuillez [$1 signaler un bogue].\nSinon, vous pouvez utiliser le formulaire simplifié ci-dessous. Votre commentaire sera ajouté à la page « [$3 $2] », avec votre nom d'utilisateur.",
        "feedback-cancel": "Annuler",
-       "feedback-close": "Fait",
+       "feedback-close": "Terminé",
        "feedback-external-bug-report-button": "Signaler un bogue technique",
        "feedback-dialog-title": "Soumettre un commentaire",
        "feedback-dialog-intro": "Vous pouvez utiliser le simple formulaire ci-dessous pour faire parvenir vos commentaires. Votre commentaire sera ajouté à la page « $1 », ainsi que votre nom d’utilisateur.",
        "api-error-unknownerror": "Erreur inconnue : « $1 ».",
        "api-error-uploaddisabled": "Le téléversement est désactivé sur ce wiki.",
        "api-error-verification-error": "Ce fichier peut être corrompu, ou son extension est incorrecte.",
+       "api-error-was-deleted": "Un fichier portant ce nom a déjà été importé puis supprimé.",
        "duration-seconds": "$1 seconde{{PLURAL:$1||s}}",
        "duration-minutes": "$1 minute{{PLURAL:$1||s}}",
        "duration-hours": "$1 heure{{PLURAL:$1||s}}",
        "special-characters-group-ipa": "API",
        "special-characters-group-symbols": "symboles",
        "special-characters-group-greek": "grec",
+       "special-characters-group-greekextended": "Grec étendu",
        "special-characters-group-cyrillic": "cyrillique",
        "special-characters-group-arabic": "arabe",
        "special-characters-group-arabicextended": "arabe étendu",
        "sessionprovider-generic": "sessions $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessions basées sur les cookies",
        "sessionprovider-nocookies": "Les cookies peuvent être désactivés. Assurez-vous que vous avez activé les cookies et recommencez.",
-       "randomrootpage": "Page racine aléatoire"
+       "randomrootpage": "Page racine aléatoire",
+       "log-action-filter-block": "Type de blocage :",
+       "log-action-filter-delete": "Type de suppression :",
+       "log-action-filter-patrol": "Type de patrouille :",
+       "log-action-filter-protect": "Type de protection :",
+       "log-action-filter-upload": "Type de téléchargement:",
+       "log-action-filter-all": "Tout",
+       "log-action-filter-block-block": "Bloc",
+       "log-action-filter-block-reblock": "Modification de bloc",
+       "log-action-filter-block-unblock": "Débloquer",
+       "log-action-filter-delete-delete": "Suppression de pages",
+       "log-action-filter-delete-restore": "Restauration de page",
+       "log-action-filter-delete-event": "Suppression du journal",
+       "log-action-filter-delete-revision": "Supression de révison",
+       "log-action-filter-patrol-patrol": "Patrouille manuelle",
+       "log-action-filter-patrol-autopatrol": "Patrouille automatique",
+       "log-action-filter-protect-protect": "Protection",
+       "log-action-filter-protect-modify": "Modification de la protection",
+       "log-action-filter-protect-unprotect": "Levée de la protection",
+       "log-action-filter-upload-upload": "Nouveau téléversement",
+       "log-action-filter-upload-overwrite": "Reitérer le téléversement"
 }
index 94046ef..62088d2 100644 (file)
@@ -16,7 +16,7 @@
        "tog-hidepatrolled": "Cachiér los changements gouardâs dedens los dèrriérs changements",
        "tog-newpageshidepatrolled": "Cachiér les pâges gouardâyes dedens la lista de les pâges novèles",
        "tog-hidecategorization": "Cachiér la catègorisacion de les pâges",
-       "tog-extendwatchlist": "Èpatar la lista de gouârda por montrar tôs los changements et pas ren que los ples novéls",
+       "tog-extendwatchlist": "Èpatar la lista de gouârda por montrar tôs los changements et pas mas que los ples novéls",
        "tog-usenewrc": "Rassemblar los changements per pâge dedens los dèrriérs changements et la lista de gouârda",
        "tog-numberheadings": "Numerotar ôtomaticament los titros de sèccion",
        "tog-showtoolbar": "Montrar la bârra d’outils de changement",
        "tog-uselivepreview": "Empleyér l’apèrçu rapido",
        "tog-forceeditsummary": "Mè balyér na semonce quand j’é pas buchiê de rèsumâ de changement",
        "tog-watchlisthideown": "Cachiér mos changements dedens la lista de gouârda",
-       "tog-watchlisthidebots": "Cachiér los changements fêts per des robots dedens la lista de gouârda",
+       "tog-watchlisthidebots": "Cachiér los changements fêts per los robots dedens la lista de gouârda",
        "tog-watchlisthideminor": "Cachiér los petiôts changements dedens la lista de gouârda",
-       "tog-watchlisthideliu": "Cachiér los changements fêts per des utilisators branchiês dedens la lista de gouârda",
+       "tog-watchlisthideliu": "Cachiér los changements fêts per los utilisators branchiês dedens la lista de gouârda",
        "tog-watchlistreloadautomatically": "Rechargiér ôtomaticament la lista de gouârda quand los chouèx de filtrâjo sont changiês (JavaScript nècèssèro)",
-       "tog-watchlisthideanons": "Cachiér los changements fêts per des utilisators anonimos dedens la lista de gouârda",
+       "tog-watchlisthideanons": "Cachiér los changements fêts per los utilisators anonimos dedens la lista de gouârda",
        "tog-watchlisthidepatrolled": "Cachiér los changements gouardâs dedens la lista de gouârda",
        "tog-watchlisthidecategorization": "Cachiér la catègorisacion de les pâges",
        "tog-ccmeonemails": "Mè mandar na copia des mèssâjos que mando ux ôtros utilisators",
@@ -52,7 +52,7 @@
        "tog-showhiddencats": "Montrar les catègories cachiêes",
        "tog-norollbackdiff": "Pas fâre vêre la dif sur na rèvocacion",
        "tog-useeditwarning": "Mè balyér na semonce quand quito na pâge de changement sen encartar los changements",
-       "tog-prefershttps": "Empleyér tot lo temps un branchement sècurisâ en étent branchiê(e)",
+       "tog-prefershttps": "Empleyér tot lo temps un branchement sècurisâ en étent branchiê",
        "underline-always": "Tot lo temps",
        "underline-never": "Jamés",
        "underline-default": "Valor per dèfôt de l’habelyâjo du navegator",
        "pagecategories": "Catègori{{PLURAL:$1|a|es}}",
        "category_header": "Pâges dedens la catègoria « $1 »",
        "subcategories": "Sot-catègories",
-       "category-media-header": "Fichiérs multimèdiâ dedens la catègoria « $1 »",
-       "category-empty": "<em>Ora cela catègoria contint gins de pâge de fichiér multimèdiâ.</em>",
+       "category-media-header": "Mèdiâ dedens la catègoria « $1 »",
+       "category-empty": "<em>Ora cela catègoria contint gins de pâge de mèdiâ.</em>",
        "hidden-categories": "{{PLURAL:$1|Catègoria cachiêe|Catègories cachiêes}}",
        "hidden-category-category": "Catègories cachiêes",
        "category-subcat-count": "Cela catègoria at {{PLURAL:$2|mas que cela sot-catègoria-que.|{{PLURAL:$1|cela sot-catègoria|celes $1 sot-catègories}}-que, sur na soma de $2.}}",
        "qbedit": "Changiér",
        "qbpageoptions": "Cela pâge",
        "qbmyoptions": "Mes pâges",
-       "faq": "Quèstions sovent posâyes",
-       "faqpage": "Project:Quèstions sovent posâyes",
+       "faq": "Quèstions sovent pôses",
+       "faqpage": "Project:Quèstions sovent pôses",
        "actions": "Accions",
        "namespaces": "Èspâços de noms",
        "variants": "Vèrsions",
        "help": "Éde",
        "search": "Rechèrche",
        "searchbutton": "Rechèrchiér",
-       "go": "Alar trovar",
+       "go": "Emmodar",
        "searcharticle": "Liére",
        "history": "Historico de la pâge",
        "history_short": "Historico",
        "pool-errorunknown": "Fôta encognua",
        "pool-servererror": "Lo sèrviço de comptâjo de la resèrva est pas disponiblo ($1).",
        "poolcounter-usage-error": "Fôta d’usâjo : $1",
-       "aboutsite": "Dessus {{SITENAME}}",
+       "aboutsite": "Sur {{SITENAME}}",
        "aboutpage": "Project:A propôs",
        "copyright": "Lo contegnu est disponiblo desot licence $1 betâ a pârt mencion contrèra.",
        "copyrightpage": "{{ns:project}}:Drêts d’ôtor",
        "helppage-top-gethelp": "Éde",
        "mainpage": "Reçua",
        "mainpage-description": "Reçua",
-       "policy-url": "Project:Règlles de dedens",
+       "policy-url": "Project:Politiques",
        "portal": "Reçua de la comunôtât",
        "portal-url": "Project:Reçua de la comunôtât",
        "privacy": "Politica de confidencialitât",
        "confirmable-confirm": "{{GENDER:$1|Vos}} éte de sûr  ?",
        "confirmable-yes": "Ouè",
        "confirmable-no": "Nan",
-       "thisisdeleted": "Vos voléd vêre ou ben refâre $1 ?",
+       "thisisdeleted": "Vos voléd vêre refâre $1 ?",
        "viewdeleted": "Vos voléd vêre $1 ?",
        "restorelink": "{{PLURAL:$1|un changement suprimâ|$1 changements suprimâs}}",
        "feedlinks": "Flux :",
-       "feed-invalid": "Tipo d’abonement du flux pas justo.",
+       "feed-invalid": "Tipo d’abonament du flux pas justo.",
        "feed-unavailable": "Los flux de sindicacion sont pas disponiblos",
        "site-rss-feed": "Flux RSS de $1",
        "site-atom-feed": "Flux Atom de $1",
        "sort-ascending": "Betar en ôrdre crèssent",
        "nstab-main": "Pâge",
        "nstab-user": "Pâge utilisator",
-       "nstab-media": "Fichiér multimèdiâ",
+       "nstab-media": "Pâge mèdiâ",
        "nstab-special": "Pâge spèciâla",
        "nstab-project": "Pâge projèt",
        "nstab-image": "Fichiér",
        "nosuchaction": "Accion encognua",
        "nosuchactiontext": "L’accion spècifiâye dens l’URL est pas justa.\nPôt-étre vos éd mâl-buchiê l’URL ou ben siuvu un lim fôx.\nPôt asse-ben étre na cofieria dedens la programeria empleyêe per {{SITENAME}}.",
        "nosuchspecialpage": "Pâge spèciâla inègzistenta",
-       "nospecialpagetext": "<strong>Vos éd demandâ na pâge spèciâla qu’ègziste pas.</strong>\n\nNa lista de les pâges spèciâles justes sè trôve dessus [[Special:SpecialPages|{{int:specialpages}}]].",
+       "nospecialpagetext": "<strong>Vos éd demandâ na pâge spèciâla pas justa.</strong>\n\nNa lista de les pâges spèciâles justes sè trôve dessus [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Fôta",
        "databaseerror": "Fôta de la bâsa de balyês",
        "databaseerror-text": "Na fôta de demanda de bâsa de balyês est arrevâye.\nCen pôt vegnir d’una cofieria dedens la programeria.",
        "databaseerror-query": "Demanda : $1",
        "databaseerror-function": "Fonccion : $1",
        "databaseerror-error": "Fôta : $1",
-       "transaction-duration-limit-exceeded": "Por èvitar na trop fôrt’ôgmentacion du dèlê de rèplicacion, cela transaccion est étâye anulâye perce que lo temps d’ècritura ($1) at dèpassâ la limita de $2 second{{PLURAL:$2|a|es}}.\nSe vos chèrchiéd a changiér un mouél de piéces en mémo temps, pletout èprovâd de fâre l’opèracion en doux-três ètapes.",
+       "transaction-duration-limit-exceeded": "Por èvitar na trop fôrt’ôgmentacion du dèlê de rèplicacion, cela transaccion est étâye anulâye, lo temps d’ècritura ($1) at dèpassâ la limita de $2 second{{PLURAL:$2|a|es}}.\nSe vos chèrchiéd a changiér un mouél de piéces en mémo temps, pletout èprovâd de fâre l’opèracion en doux-três ètapes.",
        "laggedslavemode": "<strong>Atencion :</strong> cela pâge pôt pas contegnir los fins dèrriérs changements fêts.",
        "readonly": "Bâsa de balyês cotâye",
        "enterlockreason": "Buchiéd na rêson du vèrroly et pués un’èstimacion de son temps",
        "readonlytext": "Ora la bâsa de balyês est cotâye por de novèles entrês et d’ôtros changements, de sûr por na rotina d’entretin, dês cen tot tornerat en ôrdre.\n\nL’administrator sistèmo que l’at cotâ at balyê cel’èxplicacion : $1",
-       "missing-article": "La bâsa de balyês at pas trovâ lo tèxto d’una pâge qu’el arêt diu trovar, apelâye « $1 » $2.\n\nEn g·ènèrâl cen arreve en siuvent un lim dèpassâ d’una dif d’un historico de vers na pâge suprimâye.\n\nS’o est pas lo câs, pôt étre na cofieria dedens la programeria.\nSe vos plét, signalâd-la a un [[Special:ListUsers/sysop|administrator]] sen oubliar de lui endicar l’URL du lim.",
+       "missing-article": "La bâsa de balyês at pas trovâ lo tèxto d’una pâge qu’arêt diu trovar, apelâye « $1 » $2.\n\nEn g·ènèrâl cen arreve en siuvent un lim dèpassâ d’una dif d’un historico de vers na pâge suprimâye.\n\nS’o est pas lo câs, pôt étre na cofieria dedens la programeria.\nSe vos plét, signalâd-la a un [[Special:ListUsers/sysop|administrator]] sen oubliar de lui endicar l’URL du lim.",
        "missingarticle-rev": "(numerô de vèrsion : $1)",
        "missingarticle-diff": "(dif : $1, $2)",
        "readonly_lag": "La bâsa de balyês est étâye cotâye ôtomaticament pendent que los sèrviors secondèros ratrapont lor retârd sur lo sèrvior principâl.",
        "delete-hook-aborted": "Suprèssion anulâye per un’èxtension.\nNion’èxplicacion est étâye balyêe.",
        "no-null-revision": "Y at pas moyen de fâre na novèla vèrsion voueda por la pâge « $1 »",
        "badtitle": "Crouyo titro",
-       "badtitletext": "Lo titro de la pâge demandâye est pas justo, vouedo ou ben o est un titro entèrlengoua ou entèrvouiqui mâl-liyê.\nContint de sûr yon ou ben un mouél de caractèros que pôvont pas étre empleyês dedens los titros.",
+       "badtitletext": "Lo titro de la pâge demandâye est pas justo, vouedo ou ben o est un titro entèrlengoua entèrvouiqui mâl-liyê.\nContint de sûr yon ou ben un mouél de caractèros que pôvont pas étre empleyês dedens los titros.",
        "title-invalid-empty": "Lo titro de la pâge demandâye est vouedo ou ben contint mas que lo nom d’un èspâço de noms.",
        "title-invalid-utf8": "Lo titro de la pâge demandâye contint na cobla UTF-8 pas justa.",
        "title-invalid-interwiki": "Lo titro de la pâge demandâye contint un lim entèrvouiqui que pôt pas étre empleyê dedens los titros.",
        "title-invalid-talk-namespace": "Lo titro de la pâge demandâye s’en rèfère a na pâge de discussion que pôt pas ègzistar.",
        "title-invalid-characters": "Lo titro de la pâge demandâye contint de caractèros pas justos : « $1 ».",
-       "title-invalid-relative": "Lo titro contint un chemin relatif. Los titros que rèferençont de pâges relatives (./, ../) sont pas justos, perce que seront sovent inaccèssiblos dês los navegators des utilisators.",
+       "title-invalid-relative": "Lo titro contint un chemin relatif. Los titros que rèferençont de pâges relatives (./, ../) sont pas justos, seront sovent inaccèssiblos dês los navegators des utilisators.",
        "title-invalid-magic-tilde": "Lo titro de la pâge demandâye contint na cobla de tildes magicos pas justa (<nowiki>~~~</nowiki>).",
        "title-invalid-too-long": "Lo titro de la pâge demandâye est trop long. Dêt pas dèpassar $1 octèt{{PLURAL:$1||s}} dens l’encodâjo UTF-8.",
        "title-invalid-leading-colon": "Lo titro de la pâge demandâye contint un doux-pouents pas justo u comencement.",
        "protectedpagetext": "Cela pâge est étâye protègiêe por empachiér son changement ou ben d’ôtres accions.",
        "viewsourcetext": "Vos pouede vêre et copiyér lo tèxto sôrsa de cela pâge.",
        "viewyourtext": "Vos pouede vêre et copiyér lo tèxto sôrsa de <strong>voutros changements</strong> a cela pâge.",
-       "protectedinterface": "Cela pâge-que balye de tèxto d’entèrface por la programeria sur cél vouiqui et est vêr protègiêe por èvitar los abus.\nPor apondre ou ben changiér de traduccions sur tôs los vouiquis, se vos plét empleyéd [//translatewiki.net/ translatewiki.net], lo projèt de localisacion de MediaWiki.",
+       "protectedinterface": "Cela pâge balye de tèxto d’entèrface por la programeria sur cél vouiqui et est vêr protègiêe por èvitar los abus.\nPor apondre ou ben changiér de traduccions sur tôs los vouiquis, se vos plét empleyéd [//translatewiki.net/ translatewiki.net], lo projèt de localisacion de MediaWiki.",
        "editinginterface": "<strong>Atencion :</strong> vos éte aprés changiér na pâge empleyêe por fâre lo tèxto d’entèrface de la programeria.\nLos changements sè cognetront sur l’aparence de l’entèrface utilisator por los ôtros utilisators de cél vouiqui.",
-       "translateinterface": "Por apondre ou ben changiér des traduccions sur tôs los vouiquis, se vos plét empleyéd [//translatewiki.net/ translatewiki.net], lo projèt de localisacion de MediaWiki.",
-       "cascadeprotected": "Cela pâge est protègiêe contre los changements perce qu’el est transcllua per {{PLURAL:$1|cela pâge-que qu’est étâye protègiêe|celes pâges-que que sont étâyes protègiêes}} avouéc lo chouèx « protèccion en cascâda » activâ :\n$2",
+       "translateinterface": "Por apondre changiér de traduccions sur tôs los vouiquis, se vos plét empleyéd [//translatewiki.net/ translatewiki.net], lo projèt de localisacion de MediaWiki.",
+       "cascadeprotected": "Cela pâge est protègiêe contre los changementsel est transcllua per {{PLURAL:$1|cela pâge-que qu’est étâye protègiêe|celes pâges-que que sont étâyes protègiêes}} avouéc lo chouèx « protèccion en cascâda » activâ :\n$2",
        "namespaceprotected": "Vos éd pas la pèrmission de changiér les pâges de l’èspâço de noms « <strong>$1</strong> ».",
-       "customcssprotected": "Vos éd pas la pèrmission de changiér cela pâge CSS perce que contint la configuracion a sè d’un ôtr’utilisator.",
-       "customjsprotected": "Vos éd pas la pèrmission de changiér cela pâge JavaScript perce que contint la configuracion a sè d’un ôtr’utilisator.",
+       "customcssprotected": "Vos éd pas la pèrmission de changiér cela pâge CSS, contint la configuracion a sè d’un ôtr’utilisator.",
+       "customjsprotected": "Vos éd pas la pèrmission de changiér cela pâge JavaScript, contint la configuracion a sè d’un ôtr’utilisator.",
        "mycustomcssprotected": "Vos éd pas la pèrmission de changiér cela pâge CSS.",
        "mycustomjsprotected": "Vos éd pas la pèrmission de changiér cela pâge JavaScript.",
        "myprivateinfoprotected": "Vos éd pas la pèrmission de changiér voutres enformacions a vos.",
        "mypreferencesprotected": "Vos éd pas la pèrmission de changiér voutres prèferences.",
        "ns-specialprotected": "Les pâges spèciâles pôvont pas étre changiêes.",
        "titleprotected": "Cél titro est étâ protègiê a la crèacion per [[User:$1|$1]].\nLa rêson balyêe est « <em>$2</em> ».",
-       "filereadonlyerror": "Y at pas moyen de changiér lo fichiér « $1 » perce que lo dèpôt de fichiérs « $2 » est mas qu’en lèctura.\n\nL’administrator sistèmo que l’at cotâ at balyê cel’èxplicacion : « $3 ».",
+       "filereadonlyerror": "Y at pas moyen de changiér lo fichiér « $1 », lo dèpôt de fichiérs « $2 » est mas qu’en lèctura.\n\nL’administrator sistèmo que l’at cotâ at balyê cel’èxplicacion : « $3 ».",
        "invalidtitle-knownnamespace": "Titro pas justo avouéc l’èspâço de noms « $2 » et lo tèxto « $3 »",
        "invalidtitle-unknownnamespace": "Titro pas justo avouéc lo numerô d’èspâço de noms encognu $1 et lo tèxto « $2 »",
        "exception-nologin": "Pas branchiê",
        "cannotloginnow-text": "Lo branchement est pas possiblo en empleyent $1.",
        "yourdomainname": "Voutron domêno :",
        "password-change-forbidden": "Vos pouede pas changiér los contresegnos sur cél vouiqui.",
-       "externaldberror": "Ou ben na fôta est arrevâye avouéc la bâsa de balyês d’ôtentificacion de defôr, ou ben vos éte pas ôtorisâ{{GENDER:||ye}} a betar a jorn voutron comptio de defôr.",
+       "externaldberror": "Ou ben na fôta est arrevâye avouéc la bâsa de balyês d’ôtentificacion de defôr ou ben vos éte pas ôtorisâ{{GENDER:||ye}} a betar a jorn voutron comptio de defôr.",
        "login": "Branchement",
        "nav-login-createaccount": "Sè branchiér ou ben fâre un comptio",
        "userlogin": "Sè branchiér ou ben fâre un comptio",
        "loginerror": "Fôta de branchement",
        "createacct-error": "Fôta pendent la crèacion du comptio",
        "createaccounterror": "Y at pas moyen de fâre lo comptio : $1",
-       "nocookiesnew": "Lo comptio utilisator est étâ fêt, mas vos éte pas branchiê{{GENDER:||e}}.\n{{SITENAME}} emplèye des raportiors (<em>cookies</em>) por lo branchement mas vos los éd dèsactivâs.\nSe vos plét, activâd-los et pués tornâd-vos branchiér avouéc voutron novél nom d’utilisator et voutron contresegno.",
-       "nocookieslogin": "{{SITENAME}} emplèye des raportiors (<em>cookies</em>) por lo branchement mas vos los éd dèsactivâs.\nSe vos plét, activâd-los et pués tornâd èprovar.",
-       "nocookiesfornew": "Lo comptio utilisator est pas étâ fêt, perce que nos ens pas possu confirmar son origina.\nControlâd que vos éd activâ los raportiors (<em>cookies</em>), rechargiéd la pâge et pués tornâd èprovar.",
+       "nocookiesnew": "Lo comptio utilisator est étâ fêt, mas vos éte pas branchiê{{GENDER:||e}}.\n{{SITENAME}} emplèye de raportiors (<em>cookies</em>) por lo branchement mas vos los éd dèsactivâs.\nSe vos plét, activâd-los et pués tornâd-vos branchiér avouéc voutron novél nom d’utilisator et voutron contresegno.",
+       "nocookieslogin": "{{SITENAME}} emplèye de raportiors (<em>cookies</em>) por lo branchement mas vos los éd dèsactivâs.\nSe vos plét, activâd-los et pués tornâd èprovar.",
+       "nocookiesfornew": "Lo comptio utilisator est pas étâ fêt, nos ens pas possu confirmar son origina.\nControlâd que vos éd activâ los raportiors (<em>cookies</em>), rechargiéd la pâge et pués tornâd èprovar.",
        "noname": "Vos éd pas spècifiâ un nom d’utilisator justo.",
-       "loginsuccesstitle": "Branchiê(e)",
+       "loginsuccesstitle": "Branchiê",
        "loginsuccess": "<strong>Ora vos éte branchiê{{GENDER:$1||e}} a {{SITENAME}} coment « $1 ».</strong>",
        "nosuchuser": "Y at gins d’utilisator avouéc lo nom « $1 ».\nLos noms d’utilisator sont sensiblos a la câssa.\nSe vos plét, controlâd l’ortografia ou ben [[Special:UserLogin/signup|féte un comptio novél]].",
        "nosuchusershort": "Y at gins d’utilisator avouéc lo nom « $1 ».\nSe vos plét, controlâd l’ortografia.",
        "passwordsent": "Un contresegno novél est étâ mandâ a l’adrèce èlèctronica de l’utilisator « $1 ».\nSe vos plét, tornâd-vos branchiér aprés l’avêr reçu.",
        "blocked-mailpassword": "Voutron adrèce IP est blocâye en ècritura, la fonccion de sovegnence du contresegno est vêr dèsactivâye por èvitar los abus.",
        "eauthentsent": "Un mèssâjo de confirmacion est étâ mandâ a l’adrèce èlèctronica spècifiâye.\nDevant qu’un ôtro mèssâjo seye mandâ a cél comptio, vos devréd siuvre les enstruccions du mèssâjo et pués confirmar que lo comptio est franc lo voutro.",
-       "throttled-mailpassword": "Un mèssâjo de remês’a zérô de voutron contresegno est ja étâ mandâ pendent {{PLURAL:$1|l’hora passâye|les $1 hores passâyes}}.\nPor èvitar los abus, ren que yon serat mandâ per {{PLURAL:$1|hora|entèrvalo de $1 hores}}.",
+       "throttled-mailpassword": "Un mèssâjo de remês’a zérô de voutron contresegno est ja étâ mandâ pendent {{PLURAL:$1|l’hora passâye|les $1 hores passâyes}}.\nPor èvitar los abus, mas que yon serat mandâ per {{PLURAL:$1|hora|entèrvalo de $1 hores}}.",
        "mailerror": "Fôta pendent l’èxpèdicion du mèssâjo : $1",
-       "acct_creation_throttle_hit": "Des vesitors de cél vouiqui-que qu’emplèyont voutron adrèce IP ant fêt $1 comptio{{PLURAL:$1||s}} pendent lo jorn passâ, cen qu’est lo més ôtorisâ dens ceti temps.\nDu côp los vesitors qu’emplèyont cel’adrèce IP pôvont fâre gins de comptio por lo moment.",
+       "acct_creation_throttle_hit": "Des vesitors de cél vouiqui qu’emplèyont voutron adrèce IP ant fêt $1 comptio{{PLURAL:$1||s}} pendent lo jorn passâ, cen qu’est lo més ôtorisâ dens ceti temps.\nDu côp los vesitors qu’emplèyont cel’adrèce IP pôvont fâre gins de comptio por lo moment.",
        "emailauthenticated": "Voutron adrèce èlèctronica est étâye confirmâye lo $2 a $3.",
        "emailnotauthenticated": "Voutron adrèce èlèctronica est p’oncor confirmâye.\nNion mèssâjo serat mandâ por châcuna de celes fonccionalitâts-que.",
        "noemailprefs": "Spècifiâd un’adrèce èlèctronica dens voutres prèferences por empleyér celes fonccionalitâts.",
        "emailconfirmlink": "Confirmâd voutron adrèce èlèctronica",
-       "invalidemailaddress": "Cel’adrèce èlèctronica pôt pas étre accèptâye perce que semble avêr un format pas justo.\nSe vos plét, buchiéd un’adrèce ben formatâye ou ben lèssiéd cél champ vouedo.",
+       "invalidemailaddress": "Cel’adrèce èlèctronica pôt pas étre accèptâye, semble avêr un format pas justo.\nSe vos plét, buchiéd un’adrèce ben formatâye ou ben lèssiéd cél champ vouedo.",
        "cannotchangeemail": "Les adrèces èlèctroniques des comptios pôvont pas étre changiêes sur cél vouiqui.",
        "emaildisabled": "Cél seto pôt pas mandar de mèssâjos.",
        "accountcreated": "Comptio fêt",
        "accountcreatedtext": "Lo comptio utilisator por [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|discussion]]) est étâ fêt.",
        "createaccount-title": "Crèacion d’un comptio por {{SITENAME}}",
-       "createaccount-text": "Yon at fêt un comptio por voutron adrèce èlèctronica dessus {{SITENAME}} ($4) apelâ « $2 », avouéc lo contresegno « $3 ».\nVos vos devriâd branchiér et pués changiér dês ora voutron contresegno.\n\nIgnorâd cél mèssâjo-que se cél compto est étâ fêt per fôta.",
+       "createaccount-text": "Yon at fêt un comptio por voutron adrèce èlèctronica dessus {{SITENAME}} ($4) apelâ « $2 », avouéc lo contresegno « $3 ».\nVos vos devriâd branchiér et pués changiér dês ora voutron contresegno.\n\nIgnorâd cél mèssâjo se cél comptio est étâ fêt per fôta.",
        "login-throttled": "Dês pou vos éd èprovâ un mouél de branchements.\nSe vos plét, atende-vos $1 devant que tornar èprovar.",
        "login-abort-generic": "Voutron branchement at pas reussi - Anulâ",
        "login-migrated-generic": "Voutron comptio est étâ migrâ, et pués voutron nom d’utilisator ègziste pas més sur cél vouiqui.",
        "loginlanguagelabel": "Lengoua : $1",
-       "suspicious-userlogout": "Voutra demanda de dèbranchement est étâye refusâye perce que semble qu’est étâye mandâye per un navegator câsso ou ben la mêsa en cacho d’un proxi.",
+       "suspicious-userlogout": "Voutra demanda de dèbranchement est étâye refusâye, semble qu’el est étâye mandâye per un navegator câsso ou ben la mêsa en cacho d’un sèrvior mandatèro (<em>proxy</em>).",
        "createacct-another-realname-tip": "Lo veré nom est u chouèx.\nSe vos dècidâd de lo balyér, serat empleyê por atribuar a l’utilisator ses ôvres.",
        "pt-login": "Sè branchiér",
        "pt-login-button": "Sè branchiér",
        "botpasswords-insert-failed": "Falyita de l’aponsa du nom de robot « $1 ». Est-o qu’il est ja étâ apondu ?",
        "botpasswords-update-failed": "Falyita a la mês’a jorn du nom de robot « $1 ». Est-o qu’il est ja étâ suprimâ ?",
        "botpasswords-created-title": "Contresegno de robot fêt",
-       "botpasswords-created-body": "Lo contresegno de robot « $1 » est étâ fêt.",
+       "botpasswords-created-body": "Lo contresegno de robot por lo nom de robot « $1 » a l’utilisator « $2 » est étâ fêt.",
        "botpasswords-updated-title": "Contresegno de robot betâ a jorn",
-       "botpasswords-updated-body": "Lo contresegno de robot « $1 » est étâ betâ a jorn.",
+       "botpasswords-updated-body": "Lo contresegno de robot por lo nom de robot « $1 » a l’utilisator « $2 » est étâ betâ a jorn.",
        "botpasswords-deleted-title": "Contresegno de robot suprimâ",
-       "botpasswords-deleted-body": "Lo contresegno de robot « $1 » est étâ suprimâ.",
+       "botpasswords-deleted-body": "Lo contresegno de robot por lo nom de robot « $1 » a l’utilisator « $2 » est étâ suprimâ.",
        "botpasswords-newpassword": "Lo contresegno novél por sè branchiér avouéc <strong>$1</strong> est <strong>$2</strong>. <em>Se vos plét, encartâd-lo por y fâre rèference ples târd.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider est pas disponiblo.",
        "botpasswords-restriction-failed": "Les rèstriccions de contresegno de robot empachont cél branchement.",
        "passwordreset-email": "Adrèce èlèctronica :",
        "passwordreset-emailtitle": "Dètalys du comptio dessus {{SITENAME}}",
        "passwordreset-emailtext-ip": "Yon (de sûr vos, avouéc l’adrèce IP $1) at demandâ na remês’a zérô de voutron\ncontresegno por {{SITENAME}} ($4). {{PLURAL:$3|Cél comptio utilisator-que est associyê|Celos comptios utilisators-que sont associyês}}\na cel’adrèce èlèctronica :\n\n$2\n\n{{PLURAL:$3|Cél contresegno temporèro èxpirerat|Celos contresegnos temporèros èxpireront}} dens {{PLURAL:$5|un jorn|$5 jorns}}.\nOra vos vos dête branchiér et pués chouèsir un contresegno novél. Se cela demanda vint pas de vos\nou ben se vos vos éte rapelâ de voutron contresegno originâl et que vos en voléd pas més changiér,\nvos pouede ignorar cél mèssâjo et continuar a empleyér voutron viely contresegno.",
-       "passwordreset-emailtext-user": "L’utilisator $1 dessus {{SITENAME}} at demandâ na remês’a zérô de voutron contresegno por {{SITENAME}}\n($4). {{PLURAL:$3|Cél compto utilisator-que est associyê|Celos comptos utilisators-que sont associyês}}\na cel’adrèce èlèctronica :\n\n$2\n\n{{PLURAL:$3|Cél contresegno temporèro èxpirerat|Celos contresegnos temporèros èxpireront}} dens {{PLURAL:$5|un jorn|$5 jorns}}.\nOra vos vos dête branchiér et pués chouèsir un contresegno novél. Se cela demanda vint pas de vos\nou ben se vos vos éte rapelâ de voutron contresegno originâl et que vos en voléd pas més changiér,\nvos pouede ignorar cél mèssâjo et continuar a empleyér voutron viely contresegno.",
+       "passwordreset-emailtext-user": "L’utilisator $1 dessus {{SITENAME}} at demandâ na remês’a zérô de voutron contresegno por {{SITENAME}}\n($4). {{PLURAL:$3|Cél comptio utilisator-que est associyê|Celos comptios utilisators-que sont associyês}}\na cel’adrèce èlèctronica :\n\n$2\n\n{{PLURAL:$3|Cél contresegno temporèro èxpirerat|Celos contresegnos temporèros èxpireront}} dens {{PLURAL:$5|un jorn|$5 jorns}}.\nOra vos vos dête branchiér et pués chouèsir un contresegno novél. Se cela demanda vint pas de vos\nou ben se vos vos éte rapelâ de voutron contresegno originâl et que vos en voléd pas més changiér,\nvos pouede ignorar cél mèssâjo et continuar a empleyér voutron viely contresegno.",
        "passwordreset-emailelement": "Nom d’utilisator :\n$1\n\nContresegno temporèro :\n$2",
        "passwordreset-emailsentemail": "Se cel’adrèce èlèctronica est associyêe a voutron comptio, adonc un mèssâjo de remês’a zérô de contresegno serat mandâ.",
        "passwordreset-emailsentusername": "S’y at un’adrèce èlèctronica associyêe a cél nom d’utilisator, adonc un mèssâjo de remês’a zérô de contresegno serat mandâ.",
-       "passwordreset-emailsent-capture": "Un mèssâjo de remês’a zérô de contresegno est étâ mandâ, qu’est montrâ ce-desot.",
-       "passwordreset-emailerror-capture": "Un mèssâjo de remês’a zérô de contresegno est étâ fêt, qu’est montrâ ce-desot, mas l’èxpèdicion a l’utilisat{{GENDER:$2|or|rice}} at pas reussi : $1",
-       "changeemail": "Changiér ou ben enlevar l’adrèce èlèctronica",
+       "passwordreset-emailsent-capture": "Un mèssâjo de remês’a zérô de contresegno est étâ mandâ, qu’il est montrâ ce-desot.",
+       "passwordreset-emailerror-capture": "Un mèssâjo de remês’a zérô de contresegno est étâ fêt, qu’il est montrâ ce-desot, mas l’èxpèdicion a l’utilisat{{GENDER:$2|or|rice}} at pas reussi : $1",
+       "changeemail": "Changiér enlevar l’adrèce èlèctronica",
        "changeemail-header": "Complètâd cél formulèro por changiér voutron adrèce èlèctronica. Se vos voléd enlevar l’associacion d’un’adrèce èlèctronica avouéc voutron comptio, lèssiéd la novèl’adrèce èlèctronica voueda pendent la somission du formulèro.",
        "changeemail-passwordrequired": "Vos devréd buchiér voutron contresegno por confirmar cél changement.",
        "changeemail-no-info": "Vos dête étre branchiê por arrevar tot drêt a cela pâge.",
        "image_sample": "Ègzemplo.jpg",
        "image_tip": "Fichiér apondu",
        "media_sample": "Ègzemplo.ogg",
-       "media_tip": "Lim de vers un fichiér multimèdiâ",
+       "media_tip": "Lim de vers un fichiér",
        "sig_tip": "Voutra signatura avouéc l’horodatâjo",
        "hr_tip": "Legne plana (pas nen abusar)",
        "summary": "Rèsumâ :",
        "showpreview": "Montrar un apèrçu",
        "showdiff": "Montrar los changements",
        "blankarticle": "<strong>Atencion :</strong> la pâge que vos éte aprés fâre est voueda.\nSe vos tornâd cllicar dessus « {{int:savearticle}} », la pâge serat fêta sen gins de contegnu.",
-       "anoneditwarning": "<strong>Atencion :</strong> vos éte pas branchiê. Voutron adrèce IP serat visibla devant tot lo mondo se vos féte des changements. Se vos vos <strong>[$1 branchiéd]</strong> ou ben <strong>[$2 féte un comptio]</strong>, voutros changements seront atribuâs a voutron nom d’utilisator, entre-mié ôtros avantâjos.",
+       "anoneditwarning": "<strong>Atencion :</strong> vos éte pas branchiê. Voutron adrèce IP serat visibla devant tot lo mondo se vos féte de changements. Se vos vos <strong>[$1 branchiéd]</strong> ou ben <strong>[$2 féte un comptio]</strong>, voutros changements seront atribuâs a voutron nom d’utilisator, entre-mié ôtros avantâjos.",
        "anonpreviewwarning": "<em>Vos éte pas branchiê{{GENDER:||e}}. En encartent, voutron adrèce IP serat encartâye dedens l’historico des changements de cela pâge.</em>",
        "missingsummary": "<strong>Sovegnence :</strong> vos éd balyê gins de rèsumâ de changement.\nSe vos tornâd cllicar dessus « {{int:savearticle}} », voutron changement serat encartâ sen rèsumâ.",
        "selfredirect": "<strong>Atencion :</strong> vos éte aprés redirigiér la pâge vers lyé-méma.\nVos pouede avêr spècifiâ na crouye ciba por la redirèccion ou ben pôt-étre vos changiéd na crouye pâge.\nSe vos tornâd cllicar dessus « {{int:savearticle}} », la redirèccion serat fêta tot-un.",
        "subject-preview": "Apèrçu de la chousa :",
        "previewerrortext": "Na fôta est arrevâye pendent l’èprôva d’apèrçu de voutros changements.",
        "blockedtitle": "L’utilisator est blocâ",
-       "blockedtext": "<strong>Voutron nom dâ\80\99utilisator voutron adrèce IP est Ã©tâ(ye) blocâ(ye).</strong>\n\nLo blocâjo est Ã©tâ fêt per $1.\nLa rêson balyêe est <em>$2</em>.\n\n* Comencement du blocâjo : $8\n* Ã\88xpiracion du blocâjo : $6\n* Comptio blocâ : $7\n\nVos vos pouede veriér vers $1 ou ben un Ã´trâ\80\99[[{{MediaWiki:Grouppage-sysop}}|administrator]] por nen discutar.\nVos pouede pas empleyér la fonccionalitât Â« Y mandar un mèssâjo Â» a muens quâ\80\99unâ\80\99adrèce Ã¨lèctronica justa seye spècifiâye dens voutres [[Special:Preferences|prèferences]] et que vos seyâd pas Ã©tâ blocâ de lâ\80\99empleyér.\nVoutron adrèce IP dâ\80\99ora est $3 et lâ\80\99identifient de blocâjo est $5.\nSe vos plét, entrebetâd tôs los dètalys ce-dessus dedens totes les demandes que vos faréd.",
-       "autoblockedtext": "Voutron adrèce IP est étâye blocâye ôtomaticament perce qu’el est étâye empleyêe per un ôtr’utilisator, lui-mémo blocâ per $1.\nLa rêson balyêe est :\n\n:<em>$2</em>\n\n* Comencement du blocâjo : $8\n* Èxpiracion du blocâjo : $6\n* Comptio blocâ : $7\n\nVos vos pouede veriér vers $1 ou ben yon des ôtros [[{{MediaWiki:Grouppage-sysop}}|administrators]] por nen discutar.\n\nNotâd que vos porréd pas empleyér la fonccionalitât « Y mandar un mèssâjo » a muens que vos èyâd un’adrèce èlèctronica justa encartâye dens voutres [[Special:Preferences|prèferences]] et que vos seyâd pas étâ blocâ de l’empleyér.\n\nVoutron adrèce IP d’ora est $3 et l’identifient de blocâjo est $5.\nSe vos plét, entrebetâd tôs los dètalys ce-dessus dedens totes les demandes que vos faréd.",
+       "blockedtext": "<strong>Voutron nom dâ\80\99utilisator voutron adrèce IP est Ã©tâ(ye) blocâ(ye).</strong>\n\nLo blocâjo est Ã©tâ fêt per $1.\nLa rêson balyêe est <em>$2</em>.\n\n* Comencement du blocâjo : $8\n* Ã\88xpiracion du blocâjo : $6\n* Comptio blocâ : $7\n\nVos vos pouede veriér vers $1 ou ben un Ã´trâ\80\99[[{{MediaWiki:Grouppage-sysop}}|administrator]] por nen discutar.\nVos pouede pas empleyér la fonccionalitât Â« Y mandar un mèssâjo Â» a muens quâ\80\99unâ\80\99adrèce Ã¨lèctronica justa seye spècifiâye dens voutres [[Special:Preferences|prèferences]] et que vos seyéd pas Ã©tâ blocâ de lâ\80\99empleyér.\nVoutron adrèce IP dâ\80\99ora est $3 et lâ\80\99identifient de blocâjo est $5.\nSe vos plét, rapondéd tôs los dètalys ce-dessus dedens totes les demandes que vos faréd.",
+       "autoblockedtext": "Voutron adrèce IP est étâye blocâye ôtomaticament, el est étâye empleyêe per un ôtr’utilisator, lui-mémo blocâ per $1.\nLa rêson balyêe est :\n\n:<em>$2</em>\n\n* Comencement du blocâjo : $8\n* Èxpiracion du blocâjo : $6\n* Comptio blocâ : $7\n\nVos vos pouede veriér vers $1 ou ben yon des ôtros [[{{MediaWiki:Grouppage-sysop}}|administrators]] por nen discutar.\n\nNotâd que vos porréd pas empleyér la fonccionalitât « Y mandar un mèssâjo » a muens que vos èyéd un’adrèce èlèctronica justa encartâye dens voutres [[Special:Preferences|prèferences]] et que vos seyéd pas étâ blocâ de l’empleyér.\n\nVoutron adrèce IP d’ora est $3 et l’identifient de blocâjo est $5.\nSe vos plét, rapondéd tôs los dètalys ce-dessus dedens totes les demandes que vos faréd.",
        "blockednoreason": "niona rêson balyêe",
        "whitelistedittext": "Se vos plét, vos vos dête $1 por povêr changiér les pâges.",
        "confirmedittext": "Vos dête confirmar voutron adrèce èlèctronica devant que changiér les pâges.\nSe vos plét, buchiéd et pués validâd voutron adrèce èlèctronica dens voutres [[Special:Preferences|prèferences]].",
        "nosuchsectiontitle": "Y at pas moyen de trovar la sèccion",
-       "nosuchsectiontext": "Vos éd èprovâ de changiér na sèccion qu’ègziste pas.\nPôt-étre el est étâye dèplaciêe ou ben ôtâye dês que vos éd liesu cela pâge.",
+       "nosuchsectiontext": "Vos éd èprovâ de changiér na sèccion qu’ègziste pas.\nPôt-étre el est étâye dèplaciêe ôtâye dês que vos éd liesu cela pâge.",
        "loginreqtitle": "Branchement nècèssèro",
        "loginreqlink": "branchiér",
        "loginreqpagetext": "Se vos plét, vos vos dête $1 por povêr vêre les ôtres pâges.",
        "accmailtext": "Un contresegno fêt a l’hasârd por [[User talk:$1|$1]] est étâ mandâ a $2. Pôt étre changiê dessus la pâge de <em>[[Special:ChangePassword|changement de contresegno]]</em> aprés branchement.",
        "newarticle": "(Novél)",
        "newarticletext": "Vos éd siuvu un lim de vers na pâge qu’ègziste p’oncor.\nPor fâre cela pâge, buchiéd voutron tèxto dedens la bouèta ce-desot (vêde la [$1 pâge d’éde] por més d’enformacions).\nSe vos éte arrevâ{{GENDER:||ye}} ique per fôta, cllicâd dessus lo boton <strong>Devant</strong> de voutron navegator.",
-       "anontalkpagetext": "----\n<em>O est la pâge de discussion d’un utilisator anonimo qu’at p’oncor fêt un comptio ou ben que nen emplèye pas.</em>\nPor cen, nos devens empleyér son adrèce IP numerica por o identifiar.\nUn’adrèce IP d’ense pôt étre partagiêe per un mouél d’utilisators.\nSe vos éte {{GENDER:|un utilisator|un’utilisatrice}} anonim{{GENDER:|o|a}} et pués se vos constatâd que des comentèros que vos regârdont pas vos sont étâs adrèciês, se vos plét [[Special:UserLogin/signup|féte un comptio]] ou ben [[Special:UserLogin|branchiéd-vos]] por èvitar tota confusion que vint avouéc d’ôtros utilisators anonimos.",
+       "anontalkpagetext": "----\n<em>O est la pâge de discussion d’un utilisator anonimo qu’at p’oncor fêt un comptio ou ben que nen emplèye pas.</em>\nPor cen, nos devens empleyér son adrèce IP numerica por o identifiar.\nUn’adrèce IP d’ense pôt étre partagiêe per un mouél d’utilisators.\nSe vos éte {{GENDER:|un utilisator|un’utilisatrice}} anonim{{GENDER:|o|a}} et pués se vos constatâd que de comentèros que vos regârdont pas vos sont étâs adrèciês, se vos plét [[Special:UserLogin/signup|féte un comptio]] ou ben [[Special:UserLogin|branchiéd-vos]] por èvitar tota confusion que vint avouéc d’ôtros utilisators anonimos.",
        "noarticletext": "Ora y at gins de tèxto dedens cela pâge.\nVos pouede [[Special:Search/{{PAGENAME}}|fâre na rechèrche sur cél titro]] dedens les ôtres pâges,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rechèrchiér dedens los jornâls liyês]\nou ben [{{fullurl:{{FULLPAGENAME}}|action=edit}} fâre cela pâge]</span>.",
        "noarticletext-nopermission": "Ora y at gins de tèxto dedens cela pâge.\nVos pouede [[Special:Search/{{PAGENAME}}|fâre na rechèrche sur cél titro]] dedens les ôtres pâges ou ben <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rechèrchiér dedens los jornâls liyês]</span>, mas vos éd pas la pèrmission de fâre cela pâge.",
        "missing-revision": "La vèrsion n° $1 de la pâge apelâye « {{FULLPAGENAME}} » ègziste pas.\n\nEn g·ènèrâl cen arreve en siuvent un lim dèpassâ d’un historico de vers na pâge qu’est étâye suprimâye.\nVos pouede trovar més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornâl de les suprèssions].",
-       "userpage-userdoesnotexist": "Lo comptio utilisator « $1 » est pas encartâ.\nSe vos plét, controlâd se vos voléd fâre ou ben changiér cela pâge.",
+       "userpage-userdoesnotexist": "Lo comptio utilisator « $1 » est pas encartâ.\nSe vos plét, controlâd se vos voléd fâre changiér cela pâge.",
        "userpage-userdoesnotexist-view": "Lo comptio utilisator « $1 » est pas encartâ.",
        "blocked-notice-logextract": "Ora {{GENDER:$1|cél utilisator|cel’utilisatrice}} est blocâ{{GENDER:$1||ye}}.\nLa dèrriére entrâ du jornâl des blocâjos est balyêe ce-desot coment rèference :",
        "clearyourcache": "<strong>Nota :</strong> aprés avêr encartâ, sè pôt que vos deveyéd forciér lo rechargement complèt du cacho de voutron navegator por vêre los changements.\n* <strong>Firefox / Safari :</strong> mantegnéd la toche <em>Granta Lètra</em> (<em>Shift</em>) en clliquent dessus <em>Rechargiér</em> (<em>Reload</em>) ou ben apoyéd dessus <em>Ctrl-F5</em> <em>Ctrl-R</em> (<em>⌘-R</em> sur un Mac)\n* <strong>Google Chrome :</strong> apoyéd dessus <em>Ctrl-Shift-R</em> (''⌘-Shift-R</em> sur un Mac)\n* <strong>Internet Explorer :</strong> mantegnéd la toche <em>Ctrl</em> en clliquent dessus <em>Rafrèchir</em> (<em>Refresh</em>) ou ben apoyéd dessus <em>Ctrl-F5</em>\n* <strong>Opera :</strong> vouedâd lo cacho dedens <em>Outils → Prèferences</em>",
        "usercssyoucanpreview": "<strong>Combina :</strong> empleyéd lo boton « {{int:showpreview}} » por èprovar voutra fôlye CSS novèla devant que l’encartar.",
        "userjsyoucanpreview": "<strong>Combina :</strong> empleyéd lo boton « {{int:showpreview}} » por èprovar voutra fôlye JavaScript novèla devant que l’encartar.",
        "usercsspreview": "<strong>Rapelâd-vos que vos éte ren qu’aprés prèvêre voutra fôlye CSS.\nEl est p’oncor étâye encartâye !</strong>",
-       "userjspreview": "<strong>Rapelâd-vos que vos éte ren qu’aprés prèvêre voutron code JavaScript.\nIl est p’oncor étâ encartâ !</strong>",
+       "userjspreview": "<strong>Rapelâd-vos que vos éte ren qu’aprés èprovar prèvêre voutron code JavaScript.\nIl est p’oncor étâ encartâ !</strong>",
        "sitecsspreview": "<strong>Rapelâd-vos que vos éte ren qu’aprés prèvêre cela fôlye CSS.\nEl est p’oncor étâye encartâye !</strong>",
        "sitejspreview": "<strong>Rapelâd-vos que vos éte ren qu’aprés prèvêre cél code JavaScript.\nIl est p’oncor étâ encartâ !</strong>",
-       "userinvalidcssjstitle": "<strong>Atencion :</strong> ègziste gins d’habelyâjo « $1 ».\nRapelâd-vos que les pâges a sè avouéc èxtensions .css et .js emplèyont des titros en petiôtes lètres, per ègzemplo {{ns:user}}:Foo/vector.css et pas {{ns:user}}:Foo/Vector.css.",
+       "userinvalidcssjstitle": "<strong>Atencion :</strong> ègziste gins d’habelyâjo « $1 ».\nRapelâd-vos que les pâges a sè avouéc èxtensions .css et .js emplèyont de titros en petiôtes lètres, per ègzemplo {{ns:user}}:Foo/vector.css et pas {{ns:user}}:Foo/Vector.css.",
        "updated": "(Betâ a jorn)",
        "note": "<strong>Nota :</strong>",
        "previewnote": "<strong>Rapelâd-vos qu’o est ren qu’un apèrçu.</strong>\nVoutros changements sont p’oncor étâs encartâs !",
        "previewconflict": "Cél apèrçu fât vêre lo tèxto de la zona de changement de d’amont coment aparêtrat se vos chouèsésséd de l’encartar.",
        "session_fail_preview": "Dèsolâ ! Nos povens pas encartar voutron changement a côsa d’una pèrda d’enformacions sur voutra sèssion.\n\nPôt-étre vos éte étâ dèbranchiê. <strong>Se vos plét, controlâd que vos éte adés branchiê et pués tornâd èprovar.</strong>\nSe cen tôrne pas reussir, èprovâd de vos [[Special:UserLogout|dèbranchiér]] et pués de vos tornar branchiér, et controlâd que voutron navegator accèpte los raportiors (<em>cookies</em>) de cél seto.",
        "session_fail_preview_html": "Dèsolâ ! Nos povens pas encartar voutron changement a côsa d’una pèrda d’enformacions sur voutra sèssion.\n\n<em>Perce que {{SITENAME}} at activâ l’HTML bruto, l’apèrçu est étâ cachiê por prèvegnir les ataques per JavaScript.</em>\n\n<strong>Se l’èprôva de changement est lèg·itima, se vos plét tornâd èprovar.</strong>\nSe cen tôrne pas reussir, èprovâd de vos [[Special:UserLogout|dèbranchiér]] et pués de vos tornar branchiér, et controlâd que voutron navegator accèpte los raportiors (<em>cookies</em>) de cél seto.",
-       "token_suffix_mismatch": "<strong>Voutron changement est pas étâ accèptâ perce que voutron cliant at mècllâ los caractèros de ponctuacion dedens lo jeton de changement.</strong>\nLo changement est étâ refusâ por empachiér la corrupcion du tèxto de la pâge.\nDes côps cél problèmo arreve quand vos empleyéd un sèrviço de proxi Vouèbe anonimo qu’est pas de sûr.",
+       "token_suffix_mismatch": "<strong>Voutron changement est pas étâ accèptâ, voutron cliant at mècllo los caractèros de ponctuacion dedens lo jeton de changement.</strong>\nLo changement est étâ refusâ por empachiér la corrupcion du tèxto de la pâge.\nDes côps cél problèmo arreve quand vos empleyéd un sèrviço de sèrvior mandatèro (<em>proxy</em>) Vouèbe anonimo qu’est pas de sûr.",
        "edit_form_incomplete": "<strong>Doux-três parties du formulèro de changement ant pas avengiê lo sèrvior ; controlâd que voutros changements sont entactos et pués tornâd èprovar.</strong>",
        "editing": "Changement de $1",
        "creating": "Crèacion de $1",
        "editingsection": "Changement de $1 (sèccion)",
        "editingcomment": "Changement de $1 (novèla sèccion)",
        "editconflict": "Disputa de changement : $1",
-       "explainconflict": "Un Ã´tro at changiê cela pâge aprés que vos vos seyâd betâ a la changiér.\nLa zona de changement de d’amont contint lo tèxto de la pâge coment ègziste orendrêt.\nVoutros changements aparèssont dedens la zona de changement de desot.\nVos voléd devêr fusionar voutros changements dedens lo tèxto ègzistent.\n<strong>Solament</strong> lo tèxto de la zona de changement de d’amont serat encartâ se vos cllicâd dessus « {{int:savearticle}} ».",
+       "explainconflict": "Un Ã´tro at changiê cela pâge aprés que vos vos seyéd betâ a la changiér.\nLa zona de changement de d’amont contint lo tèxto de la pâge coment ègziste orendrêt.\nVoutros changements aparèssont dedens la zona de changement de desot.\nVos voléd devêr fusionar voutros changements dedens lo tèxto ègzistent.\n<strong>Solament</strong> lo tèxto de la zona de changement de d’amont serat encartâ se vos cllicâd dessus « {{int:savearticle}} ».",
        "yourtext": "Voutron tèxto",
        "storedversion": "Vèrsion encartâye",
        "nonunicodebrowser": "<strong>Atencion : voutron navegator recognêt pas l’Unicode.</strong>\nNa solucion de rechanjo est étâye trovâye por vos pèrmetre de changiér en tota suretât na pâge : los caractèros nan-ASCII aparêtront dedens la zona de changement coment codes hègzadècimâls.",
        "editingold": "<strong>Atencion : vos éte aprés changiér na vèrsion dèpassâye de cela pâge.</strong>\nSe vos l’encartâd, tôs los changements fêts dês cela vèrsion seront pèrdus.",
        "yourdiff": "Difèrences",
        "copyrightwarning": "Se vos plét, notâd que totes les contribucions a {{SITENAME}} sont considèrâyes coment publeyêes desot los tèrmos de la $2 (vêde $1 por més de dètalys).\nSe vos voléd pas que voutros ècrits seyont changiês sen pediêt et pués redistribuâs a volontât, adonc mandâd-los pas ique.<br />\nVos nos assurâd asse-ben que vos éd cen ècrit vos-mémo ou ben que vos l’éd copiyê d’una sôrsa que vint du domêno publico ou d’un’ôtra ressôrsa libra.\n<strong>Empleyéd gins d’ôvra desot drêt d’ôtor sen pèrmission èxprèssa !</strong>",
-       "copyrightwarning2": "Se vos plét, notâd que totes les contribucions a {{SITENAME}} pôvont étre changiêes ou ben enlevâyes per d’ôtros contributors.\nSe vos voléd pas que voutros ècrits seyont changiês sen pediêt, adonc mandâd-los pas ique.<br />\nVos nos assurâd asse-ben que vos éd cen ècrit vos-mémo ou ben que vos l’éd copiyê d’una sôrsa que vint du domêno publico ou d’un’ôtra ressôrsa libra (vêde $1 por més de dètalys).\n<strong>Empleyéd gins d’ôvra desot drêt d’ôtor sen pèrmission èxprèssa !</strong>",
+       "copyrightwarning2": "Se vos plét, notâd que totes les contribucions a {{SITENAME}} pôvont étre changiêes enlevâyes per d’ôtros contributors.\nSe vos voléd pas que voutros ècrits seyont changiês sen pediêt, adonc mandâd-los pas ique.<br />\nVos nos assurâd asse-ben que vos éd cen ècrit vos-mémo ou ben que vos l’éd copiyê d’una sôrsa que vint du domêno publico ou d’un’ôtra ressôrsa libra (vêde $1 por més de dètalys).\n<strong>Empleyéd gins d’ôvra desot drêt d’ôtor sen pèrmission èxprèssa !</strong>",
        "editpage-cannot-use-custom-model": "Lo modèlo de contegnu de cela pâge pôt pas étre changiê.",
-       "longpageerror": "<strong>Fôta : lo tèxto que vos éd mandâ fât {{PLURAL:$1|un Kio|$1 Kio}}, cen que dèpâsse la limita fixâye a {{PLURAL:$2|un Kio|$2 Kio}}.</strong>\nPôt pas étre encartâ.",
+       "longpageerror": "<strong>Fôta : lo tèxto que vos éd mandâ fât {{PLURAL:$1|un Kio|$1 Kio}}, cen que dèpâsse la limita fixa a {{PLURAL:$2|un Kio|$2 Kio}}.</strong>\nPôt pas étre encartâ.",
        "readonlywarning": "<strong>Atencion : la bâsa de balyês est étâye cotâye por na rotina d’entretin, cen fât que vos porréd vêr pas encartar voutros changements orendrêt.</strong>\nVos pouede copiyér et côlar voutron tèxto dedens un fichiér tèxto et pués l’encartar por ples târd.\n\nL’administrator sistèmo que l’at cotâ at balyê cel’èxplicacion : $1",
-       "protectedpagewarning": "<strong>Atencion : cela pâge est étâye protègiêe de façon que solament los utilisators qu’ant lo statut d’administrator la pouessont changiér.</strong>\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
-       "semiprotectedpagewarning": "<strong>Nota :</strong> cela pâge est étâye protègiêe de façon que solament los utilisators encartâs la pouessont changiér.\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
-       "cascadeprotectedwarning": "<strong>Atencion :</strong> cela pâge est étâye protègiêe de façon que solament los utilisators qu’ant lo statut d’administrator la pouessont changiér perce qu’el est transcllua dedens {{PLURAL:$1|cela pâge protègiêe|celes pâges protègiêes}}-que avouéc la « protèccion en cascâda » activâye :",
-       "titleprotectedwarning": "<strong>Atencion : cela pâge est étâye protègiêe de façon que des [[Special:ListGroupRights|drêts spècificos]] sont nècèssèros por la povêr fâre.</strong>\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
+       "protectedpagewarning": "<strong>Atencion : cela pâge est étâye protègiêe por que solament los utilisators qu’ant los drêts d’administrator la pouessont changiér.</strong>\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
+       "semiprotectedpagewarning": "<strong>Nota :</strong> cela pâge est étâye protègiêe por que solament los utilisators encartâs la pouessont changiér.\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
+       "cascadeprotectedwarning": "<strong>Atencion :</strong> cela pâge est étâye protègiêe por que solament los utilisators qu’ant los drêts d’administrator la pouessont changiér, el est transcllua dedens {{PLURAL:$1|cela pâge protègiêe|celes pâges protègiêes}}-que avouéc la « protèccion en cascâda » activâye :",
+       "titleprotectedwarning": "<strong>Atencion : cela pâge est étâye protègiêe por que de [[Special:ListGroupRights|drêts spècificos]] sont nècèssèros por la povêr fâre.</strong>\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
        "templatesused": "{{PLURAL:$1|Modèlo empleyê|Modèlos empleyês}} per cela pâge :",
        "templatesusedpreview": "{{PLURAL:$1|Modèlo empleyê|Modèlos empleyês}} dedens cél apèrçu :",
        "templatesusedsection": "{{PLURAL:$1|Modèlo empleyê|Modèlos empleyês}} dedens cela sèccion :",
        "permissionserrors": "Fôta de pèrmission",
        "permissionserrorstext": "Vos éd pas la pèrmission de fâre l’accion demandâye por {{PLURAL:$1|cela rêson|celes rêsons}}-que :",
        "permissionserrorstext-withaction": "Vos éd pas la pèrmission de $2 por {{PLURAL:$1|cela rêson|celes rêsons}}-que :",
-       "contentmodelediterror": "Vos pouede pas changiér cela vèrsion perce que son modèlo de contegnu est <code>$1</code>, cen que sè difèrence du modèlo de contegnu d’ora de la pâge <code>$2</code>.",
+       "contentmodelediterror": "Vos pouede pas changiér cela vèrsion, son modèlo de contegnu est <code>$1</code>, cen que sè difèrence du modèlo de contegnu d’ora de la pâge <code>$2</code>.",
        "recreate-moveddeleted-warn": "<strong>Atencion : vos éte aprés refâre na pâge qu’est étâye suprimâye dês devant.</strong>\n\nDemandâd-vos se fôt franc continuar son changement.\nLo jornâl de les suprèssions et des dèplacements de cela pâge est balyê ce-desot por comoditât :",
        "moveddeleted-notice": "Cela pâge est étâye suprimâye.\nLo jornâl de les suprèssions et des dèplacements de cela pâge est balyê ce-desot coment rèference.",
        "moveddeleted-notice-recent": "Dèsolâ, dês pou cela pâge est étâye suprimâye (dens les 24 hores passâyes).\nLo jornâl de les suprèssions et des dèplacements de cela pâge est balyê ce-desot coment rèference.",
        "edit-hook-aborted": "Changement anulâ per un’èxtension.\nNion’èxplicacion est étâye balyêe.",
        "edit-gone-missing": "Y at pas moyen de betar a jorn la pâge.\nSemble que seye étâye suprimâye.",
        "edit-conflict": "Disputa de changement.",
-       "edit-no-change": "Voutron changement est étâ ignorâ perce que nion changement est étâ fêt u tèxto.",
+       "edit-no-change": "Voutron changement est étâ ignorâ, nion changement est étâ fêt u tèxto.",
        "postedit-confirmation-created": "La pâge est étâye fêta.",
        "postedit-confirmation-restored": "La pâge est étâye refêta.",
        "postedit-confirmation-saved": "Voutron changement est étâ encartâ.",
        "duplicate-args-category-desc": "La pâge contint d’apèls de modèlo qu’emplèyont d’arguments doblos, coment <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> ou ben <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "<strong>Atencion :</strong> cela pâge contint trop d’apèls a des fonccions parsiors que revegnont chieres.\n\nY devrêt avêr muens de $2 apèl{{PLURAL:$2||s}}, pendent qu’y en at ora $1.",
        "expensive-parserfunction-category": "Pâges avouéc trop d’apèls a des fonccions parsiors que revegnont chieres",
-       "post-expand-template-inclusion-warning": "<strong>Atencion :</strong> la talye des modèlos entrebetâs est trop grôssa.\nDoux-três modèlos seront pas entrebetâs.",
-       "post-expand-template-inclusion-category": "Pâges yô que la talye des modèlos entrebetâs est dèpassâye",
+       "post-expand-template-inclusion-warning": "<strong>Atencion :</strong> la talye des modèlos rapondus est trop grôssa.\nDoux-três modèlos seront pas rapondus.",
+       "post-expand-template-inclusion-category": "Pâges yô que la talye des modèlos rapondus est dèpassâye",
        "post-expand-template-argument-warning": "<strong>Atencion :</strong> cela pâge contint por lo muens un argument de modèlo qu’at na talye d’èxpension trop grôssa.\nCelos arguments sont pas étâs betâs.",
        "post-expand-template-argument-category": "Pâges que contegnont d’arguments de modèlo pas betâs",
        "parser-template-loop-warning": "Modèlo bocllo dècelâ : [[$1]]",
        "converter-manual-rule-error": "Fôta dècelâye dedens la règlla de convèrsion manuâla de lengoua",
        "undo-success": "Lo changement pôt étre dèfêt.\nSe vos plét, controlâd la comparèson ce-desot por vos assurar qu’o est franc cen que vos voléd fâre, et pués encartâd los changements por chavonar sa dèfêta.",
        "undo-failure": "Lo changement at pas possu étre dèfêt a côsa d’una disputa avouéc des changements entèrmèdièros.",
-       "undo-norev": "Lo changement at pas possu étre dèfêt perce qu’il est inègzistent ou ben qu’il est étâ suprimâ.",
+       "undo-norev": "Lo changement at pas possu étre dèfêt, il est inègzistent ou ben il est étâ suprimâ.",
        "undo-nochange": "Semble que lo changement seye ja étâ dèfêt.",
        "undo-summary": "Dèfêta du changement $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|discutar]])",
        "undo-summary-username-hidden": "Dèfêta du changement $1 d’un utilisator cachiê",
        "rev-suppressed-text-unhide": "Cela vèrsion de la pâge est étâye <strong>rèprimâye</strong>.\nY pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jornâl de les rèprèssions].\nVos pouede adés [$1 vêre cela vèrsion] se vos o voléd.",
        "rev-deleted-text-view": "Cela vèrsion de la pâge est étâye <strong>suprimâye</strong>.\nVos la pouede vêre ; y pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornâl de les suprèssions].",
        "rev-suppressed-text-view": "Cela vèrsion de la pâge est étâye <strong>rèprimâye</strong>.\nVos la pouede vêre ; y pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jornâl de les rèprèssions].",
-       "rev-deleted-no-diff": "Vos pouede pas vêre cela dif perce que yona de les vèrsions est étâye <strong>suprimâye</strong>.\nY pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornâl de les suprèssions].",
-       "rev-suppressed-no-diff": "Vos pouede pas vêre cela dif perce que yona de les vèrsions est étâye <strong>suprimâye</strong>.",
+       "rev-deleted-no-diff": "Vos pouede pas vêre cela dif, yona de les vèrsions est étâye <strong>suprimâye</strong>.\nY pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornâl de les suprèssions].",
+       "rev-suppressed-no-diff": "Vos pouede pas vêre cela dif, yona de les vèrsions est étâye <strong>suprimâye</strong>.",
        "rev-deleted-unhide-diff": "Yona de les vèrsions de cela dif est étâye <strong>suprimâye</strong>.\nY pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornâl de les suprèssions].\nVos pouede adés [$1 vêre cela dif] se vos o voléd.",
        "rev-suppressed-unhide-diff": "Yona de les vèrsions de cela dif est étâye <strong>rèprimâye</strong>.\nY pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jornâl de les rèprèssions].\nVos pouede adés [$1 vêre cela dif] se vos o voléd.",
        "rev-deleted-diff-view": "Yona de les vèrsions de cela dif est étâye <strong>suprimâye</strong>.\nVos pouede vêre cela dif ; y pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} jornâl de les suprèssions].",
        "rev-suppressed-diff-view": "Yona de les vèrsions de cela dif est étâye <strong>rèprimâye</strong>.\nVos pouede vêre cela dif ; y pôt avêr més de dètalys dessus lo [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} jornâl de les rèprèssions].",
        "rev-delundel": "changiér la visibilitât",
        "rev-showdeleted": "montrar",
-       "revisiondelete": "Suprimar ou ben refâre de vèrsions",
+       "revisiondelete": "Suprimar refâre de vèrsions",
        "revdelete-nooldid-title": "Vèrsion ciba pas justa",
-       "revdelete-nooldid-text": "Vos éd spècifiâ gins de vèrsion ciba por y fâre cela fonccion, ou ben la vèrsion spècifiâye ègziste pas, ou ben vos èprovâd de cachiér la vèrsion d’ora.",
+       "revdelete-nooldid-text": "Vos éd spècifiâ gins de vèrsion ciba por y fâre cela fonccion, ou ben la vèrsion spècifiâye ègziste pas ou ben vos èprovâd de cachiér la vèrsion d’ora.",
        "revdelete-no-file": "Lo fichiér spècifiâ ègziste pas.",
        "revdelete-show-file-confirm": "Vos éte de sûr de volêr vêre na vèrsion suprimâye du fichiér « <nowiki>$1</nowiki> » que dâte du $2 a $3 ?",
        "revdelete-show-file-submit": "Ouè",
        "revdelete-text-file": "Les vèrsions de fichiér suprimâyes continueront a aparêtre dedens l’historico du fichiér, mas na partia de lor contegnu serat inaccèssibla u publico.",
        "logdelete-text": "Los èvènements du jornâl suprimâs continueront a aparêtre dedens los jornâls, mas na partia de lor contegnu serat inaccèssibla u publico.",
        "revdelete-text-others": "Los ôtros administrators porront adés arrevar u contegnu cachiê et lo refâre, a muens que des rèstriccions de més seyont dèfenies.",
-       "revdelete-confirm": "Se vos plét, confirmâd qu’o est franc cen que vos voléd fâre, que vos en compregnéd les consèquences, et pués que vos o féte en acôrd avouéc les [[{{MediaWiki:Policy-url}}|règlles]].",
+       "revdelete-confirm": "Se vos plét, confirmâd qu’o est franc cen que vos voléd fâre, que vos en compregnéd les consèquences, et pués que vos o féte en acôrd avouéc les [[{{MediaWiki:Policy-url}}|politiques]].",
        "revdelete-suppress-text": "La rèprèssion dêt étre empleyêe <strong>ren que</strong> dens celos câs-que :\n* Enformacions que pôvont étre difamatouères\n* Enformacions a sè que vant pas avouéc\n*: <em>adrèce, numerô de tèlèfono, numerô d’identificacion nacionâl, et tot cen que vat avouéc</em>",
        "revdelete-legend": "Dèfenir de rèstriccions de visibilitât",
        "revdelete-hide-text": "Tèxto de la vèrsion",
        "revdelete-hide-current": "Fôta en cachient la piéce datâye du $1 a $2 : o est la vèrsion d’ora.\nPôt pas étre cachiêe.",
        "revdelete-show-no-access": "Fôta en montrent la piéce datâye du $1 a $2 : el est marcâye coment « rètrenta ».\nVos y éd pas accès.",
        "revdelete-modify-no-access": "Fôta en changient la piéce datâye du $1 a $2 : el est marcâye coment « rètrenta ».\nVos y éd pas accès.",
-       "revdelete-modify-missing": "Fôta en changient la piéce avouéc l’ID $1 : el est manquenta dedens la bâsa de balyês !",
+       "revdelete-modify-missing": "Fôta en changient la piéce avouéc l’ID $1 : el est entrovâbla dedens la bâsa de balyês !",
        "revdelete-no-change": "<strong>Atencion :</strong> la piéce datâye du $1 a $2 at ja la configuracion de visibilitât demandâye.",
        "revdelete-concurrent-change": "Fôta en changient la piéce datâye du $1 a $2 : son statut semble étre étâ changiê per un ôtro justo que vos èprovâvâd d’o changiér.\nSe vos plét, controlâd los jornâls.",
        "revdelete-only-restricted": "Fôta en cachient la piéce datâye du $1 a $2 : vos pouede pas rèprimar de piéces de la viua ux administrators sen chouèsir avouéc d’ôtros chouèx de visibilitât.",
        "revdelete-reasonotherlist": "Ôtra rêson",
        "revdelete-edit-reasonlist": "Changiér les rêsons de suprèssion",
        "revdelete-offender": "Ôtor de la vèrsion :",
-       "suppressionlog": "Jornâl de les suprèssions",
+       "suppressionlog": "Jornâl de les prèssions",
        "suppressionlogtext": "Vê-que na lista de les suprèssions et des blocâjos qu’ant de contegnu cachiê ux administrators.\nVêde la [[Special:BlockList|lista des blocâjos]] por la lista des banissements et des blocâjos que sont ora actifs.",
        "mergehistory": "Fusionar los historicos de les pâges",
        "mergehistory-header": "Cela pâge vos pèrmèt de fusionar de vèrsions de l’historico d’una pâge d’origina vers na pâge novèla.\nAssurâd-vos que cél changement consèrverat la continuitât de l’historico de la pâge.",
        "mergehistory-fail-no-change": "La fusion des historicos at fusionâ gins de vèrsion. Se vos plét, tornâd chouèsir la pâge et pués los paramètros de temps.",
        "mergehistory-fail-permission": "Drêts ensufisents por fusionar los historicos.",
        "mergehistory-fail-self-merge": "Les pâges d’origina et de dèstinacion sont pariéres.",
-       "mergehistory-fail-timestamps-overlap": "Les vèrsions d’origina cavalont ou ben siuvont les vèrsions de dèstinacion.",
-       "mergehistory-fail-toobig": "Y at pas moyen de fâre la fusion des historicos perce qu’un nombro de {{PLURAL:$1|vèrsions}} d’amont la limita de $1 devrêt étre dèplaciê.",
+       "mergehistory-fail-timestamps-overlap": "Les vèrsions d’origina cavalont siuvont les vèrsions de dèstinacion.",
+       "mergehistory-fail-toobig": "Y at pas moyen de fâre la fusion des historicosun nombro de {{PLURAL:$1|vèrsions}} d’amont la limita de $1 devrêt étre dèplaciê.",
        "mergehistory-no-source": "La pâge d’origina $1 ègziste pas.",
        "mergehistory-no-destination": "La pâge de dèstinacion $1 ègziste pas.",
        "mergehistory-invalid-source": "La pâge d’origina dêt avêr un titro justo.",
        "prefs-watchlist-token": "Jeton por la lista de gouârda :",
        "prefs-misc": "De totes sôrtes",
        "prefs-resetpass": "Changiér lo contresegno",
-       "prefs-changeemail": "Changiér ou ben enlevar l’adrèce èlèctronica",
+       "prefs-changeemail": "Changiér enlevar l’adrèce èlèctronica",
        "prefs-setemail": "Dèfenir un’adrèce èlèctronica",
        "prefs-email": "Chouèx de mèssageria èlèctronica",
        "prefs-rendering": "Aparence",
        "saveusergroups": "Encartar les tropes d’{{GENDER:$1|utilisators}}",
        "userrights-groupsmember": "Membro de :",
        "userrights-groupsmember-auto": "Membro tacito de :",
-       "userrights-groups-help": "Vos pouede changiér les tropes a lesquintes est {{GENDER:$1|cél utilisator|cel’utilisatrice}} :\n* Na câsa pouentâye vôt dére que l’utilisat{{GENDER:$1|or|rice}} sè trôve dedens cela tropa.\n* Na câsa pas pouentâye vôt dére qu’y sè trôve pas.\n* Na petiôt’ètêla (*) endique que vos pouede pas enlevar cela tropa setout que vos l’éd apondua ou ben l’una l’ôtra.",
+       "userrights-groups-help": "Vos pouede changiér les tropes que lor est {{GENDER:$1|cél utilisator|cel’utilisatrice}} :\n* Na câsa pouentâye vôt dére que l’utilisat{{GENDER:$1|or|rice}} sè trôve dedens cela tropa.\n* Na câsa pas pouentâye vôt dére qu’y sè trôve pas.\n* Na petiôt’ètêla (*) endique que vos pouede pas enlevar cela tropa setout que vos l’éd apondua ou ben l’una l’ôtra.",
        "userrights-reason": "Rêson :",
        "userrights-no-interwiki": "Vos éd pas la pèrmission de changiér de drêts d’utilisator sur d’ôtros vouiquis.",
        "userrights-nodatabase": "La bâsa de balyês « $1 » ègziste pas ou ben est pas locâla.",
        "userrights-nologin": "Vos vos dête [[Special:UserLogin|branchiér]] avouéc un comptio d’administrator por balyér de drêts d’utilisator.",
-       "userrights-notallowed": "Vos éd pas la pèrmission de balyér ou ben enlevar de drêts d’utilisator.",
+       "userrights-notallowed": "Vos éd pas la pèrmission de balyér enlevar de drêts d’utilisator.",
        "userrights-changeable-col": "Les tropes que vos pouede changiér",
        "userrights-unchangeable-col": "Les tropes que vos pouede pas changiér",
        "userrights-conflict": "Disputa de changement de drêts d’utilisator ! Se vos plét, controlâd et pués confirmâd voutros changements.",
        "group-bot": "Robots",
        "group-sysop": "Administrators",
        "group-bureaucrat": "Grata-papiérs",
-       "group-suppress": "Suprèssiors",
+       "group-suppress": "prèssiors",
        "group-all": "(tôs)",
        "group-user-member": "utilisat{{GENDER:$1|or|rice}}",
        "group-autoconfirmed-member": "utilisat{{GENDER:$1|or ôtoconfirmâ|rice ôtoconfirmâye}}",
        "group-bot-member": "{{GENDER:$1|robot}}",
        "group-sysop-member": "administrat{{GENDER:$1|or|rice}}",
        "group-bureaucrat-member": "{{GENDER:$1|grata-papiér}}",
-       "group-suppress-member": "suprèssio{{GENDER:$1|r|sa}}",
+       "group-suppress-member": "prèssio{{GENDER:$1|r|sa}}",
        "grouppage-user": "{{ns:project}}:Utilisators",
        "grouppage-autoconfirmed": "{{ns:project}}:Utilisators ôtoconfirmâs",
        "grouppage-bot": "{{ns:project}}:Robots",
        "grouppage-sysop": "{{ns:project}}:Administrators",
        "grouppage-bureaucrat": "{{ns:project}}:Grata-papiérs",
-       "grouppage-suppress": "{{ns:project}}:Suprèssiors",
+       "grouppage-suppress": "{{ns:project}}:prèssiors",
        "right-read": "Liére les pâges",
        "right-edit": "Changiér les pâges",
        "right-createpage": "Fâre de pâges (que sont pas de pâges de discussion)",
        "right-upload": "Tèlèchargiér de fichiérs",
        "right-reupload": "Ècllafar un fichiér ègzistent",
        "right-reupload-own": "Ècllafar un fichiér ègzistent tèlèchargiê per sè-mémo",
-       "right-reupload-shared": "Ècllafar localament un fichiér present sur un dèpôt de fichiérs multimèdiâ partagiê",
+       "right-reupload-shared": "Ècllafar localament un fichiér present sur un dèpôt mèdiâ partagiê",
        "right-upload_by_url": "Tèlèchargiér un fichiér dês un’URL",
        "right-purge": "Purgiér lo cacho du seto d’una pâge sen confirmacion",
        "right-autoconfirmed": "Pas étre afèctâ per les limitacions de dèbit liyêes a les adrèces IP",
        "right-block": "Blocar en ècritura d’ôtros utilisators",
        "right-blockemail": "Empachiér un utilisator de mandar de mèssâjos",
        "right-hideuser": "Blocar un utilisator en cachient son nom u publico",
-       "right-ipblock-exempt": "Èvitar los blocâjos d’IP, los blocâjos ôtomaticos et los blocâjos de plages d’IP",
+       "right-ipblock-exempt": "Èvitar los blocâjos d’IP, los blocâjos ôtomaticos et los blocâjos de plages IP",
        "right-unblockself": "Sè dèblocar sè-mémo",
        "right-protect": "Changiér los nivéls de protèccion et pués changiér les pâges protègiêes en cascâda",
        "right-editprotected": "Changiér les pâges protègiêes avouéc « {{int:protect-level-sysop}} »",
        "right-changetags": "Apondre et enlevar de façon arbitrèra de [[Special:Tags|balises]] sur des vèrsions endividuèles et des entrês de jornâl",
        "grant-generic": "Ensemblo de drêts « $1 »",
        "grant-group-page-interaction": "Entèrag·ir avouéc de pâges",
-       "grant-group-file-interaction": "Entèrag·ir avouéc de fichiérs multimèdiâ",
+       "grant-group-file-interaction": "Entèrag·ir avouéc de mèdiâs",
        "grant-group-watchlist-interaction": "Entèrag·ir avouéc voutra lista de gouârda",
        "grant-group-email": "Mandar un mèssâjo",
        "grant-group-high-volume": "Fâre un’activitât de grôs volumo",
        "grant-editpage": "Changiér de pâges ègzistentes",
        "grant-editprotected": "Changiér de pâges protègiêes",
        "grant-highvolume": "Changement de grôs volumo",
-       "grant-oversight": "Cachiér los utilisators et suprimar les vèrsions",
+       "grant-oversight": "Cachiér los utilisators et primar les vèrsions",
        "grant-patrol": "Gouardar los changements a les pâges",
        "grant-protect": "Protègiér et enlevar la protèccion de pâges",
        "grant-rollback": "Rèvocar de changements sur des pâges",
        "grant-uploadeditmovefile": "Tèlèchargiér, remplaciér et dèplaciér de fichiérs",
        "grant-uploadfile": "Tèlèchargiér de novéls fichiérs",
        "grant-basic": "Drêts de bâsa",
-       "grant-viewdeleted": "Vêre los fichiérs et les pâges suprimâ(ye)s",
+       "grant-viewdeleted": "Vêre los fichiérs et les pâges suprimâs",
        "grant-viewmywatchlist": "Vêre voutra lista de gouârda",
        "newuserlogpage": "Jornâl de les crèacions de comptios utilisator",
        "newuserlogpagetext": "O est un jornâl de les crèacions de comptios utilisator.",
        "action-mergehistory": "fusionar l’historico de cela pâge",
        "action-userrights": "changiér tôs los drêts d’utilisator",
        "action-userrights-interwiki": "changiér los drêts d’utilisator d’utilisators que sont sur d’ôtros vouiquis",
-       "action-siteadmin": "cotar ou ben dècotar la bâsa de balyês",
+       "action-siteadmin": "cotar dècotar la bâsa de balyês",
        "action-sendemail": "mandar de mèssâjos",
        "action-editmywatchlist": "changiér voutra lista de gouârda",
        "action-viewmywatchlist": "vêre voutra lista de gouârda",
        "recentchanges-label-plusminus": "La talye de la pâge at changiê de cél nombro d’octèts.",
        "recentchanges-legend-heading": "<strong>Lègenda :</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vêde avouéc la [[Special:NewPages|lista de les pâges novèles]]).",
-       "recentchanges-submit": "Listar",
+       "recentchanges-submit": "Montrar",
        "rcnotefrom": "Vê-que {{PLURAL:$5|lo changement fêt|los changements fêts}} dês lo <strong>$3 a $4</strong> (tant qu’a <strong>$1</strong> montrâs).",
        "rclistfrom": "Montrar los novéls changements dês lo $3 a $2",
        "rcshowhideminor": "$1 los petiôts changements",
        "recentchangeslinked-page": "Nom de la pâge :",
        "recentchangeslinked-to": "Montrar per contre los changements de les pâges qu’ant un lim de vers la pâge balyêe",
        "recentchanges-page-added-to-category": "[[:$1]] apondua a la catègoria",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] et {{PLURAL:$2|na pâge apondua|$2 pâges apondues}} a la catègoria",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] et [[Special:WhatLinksHere/$1|{{PLURAL:$2|na pâge apondua|$2 pâges apondues}}]] a la catègoria",
        "recentchanges-page-removed-from-category": "[[:$1]] enlevâye de la catègoria",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] et {{PLURAL:$2|na pâge enlevâye|$2 pâges enlevâyes}} de la catègoria",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] et [[Special:WhatLinksHere/$1|{{PLURAL:$2|na pâge enlevâye|$2 pâges enlevâyes}}]] de la catègoria",
        "autochange-username": "Changement ôtomatico de MediaWiki",
        "upload": "Tèlèchargiér un fichiér",
        "uploadbtn": "Tèlèchargiér lo fichiér",
        "reuploaddesc": "Anular lo tèlèchargement et pués tornar u formulèro de tèlèchargement",
        "upload-tryagain": "Mandar la dèscripcion du fichiér changiê",
-       "uploadnologin": "Pas branchiê(ye)",
+       "uploadnologin": "Pas branchiê",
        "uploadnologintext": "Se vos plét, vos vos dête $1 por povêr tèlèchargiér de fichiérs.",
-       "upload_directory_missing": "Lo rèpèrtouèro de tèlèchargement ($1) est manquent et at pas possu étre fêt per lo sèrvior Vouèbe.",
-       "upload_directory_read_only": "Lo rèpèrtouèro de tèlèchargement ($1) est pas accèssiblo en ècritura dês lo sèrvior Vouèbe.",
+       "upload_directory_missing": "Lo rèpèrtouèro de tèlèchargement ($1) est entrovâblo et at pas possu étre fêt per lo sèrvior Vouèbe.",
+       "upload_directory_read_only": "Lo rèpèrtouèro de tèlèchargement ($1) est pas enscriptiblo per lo sèrvior Vouèbe.",
        "uploaderror": "Fôta pendent lo tèlèchargement",
-       "upload-recreate-warning": "<strong>Atencion : un fichiér avouéc cél nom est étâ suprimâ ou ben dèplaciê.</strong>\n\nLo jornâl de les suprèssions et des dèplacements de cela pâge est balyê ique por comoditât :",
-       "uploadtext": "Empleyéd lo formulèro ce-desot por tèlèchargiér de fichiérs.\nPor vêre ou ben rechèrchiér de fichiérs tèlèchargiês dês devant, vêde la [[Special:FileList|lista des fichiérs tèlèchargiês]]. Los (re-)tèlèchargements sont asse-ben encartâs dessus lo [[Special:Log/upload|jornâl des tèlèchargements]], et les suprèssions dessus lo [[Special:Log/delete|jornâl de les suprèssions]].\n\nPor entrebetar un fichiér dedens na pâge, empleyéd un lim de yona de celes fôrmes-que :\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Fichiér.jpg]]</nowiki></code></strong> por empleyér la vèrsion en plêna largior du fichiér\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Fichiér.png|200px|thumb|left|tèxto dèscriptif]]</nowiki></code></strong> por empleyér na miniatura de 200 pixèls de lârjo dedens na bouèt’a gôche avouéc « tèxto dèscriptif » coment dèscripcion\n* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Fichiér.ogg]]</nowiki></code></strong> por liyér tot drêt vers lo fichiér sen lo fâre vêre",
+       "upload-recreate-warning": "<strong>Atencion : un fichiér avouéc cél nom est étâ suprimâ dèplaciê.</strong>\n\nLo jornâl de les suprèssions et des dèplacements de cela pâge est balyê ique por comoditât :",
+       "uploadtext": "Empleyéd lo formulèro ce-desot por tèlèchargiér de fichiérs.\nPor vêre rechèrchiér de fichiérs tèlèchargiês dês devant, vêde la [[Special:FileList|lista des fichiérs tèlèchargiês]]. Los (re-)tèlèchargements sont asse-ben encartâs dessus lo [[Special:Log/upload|jornâl des tèlèchargements]], et les suprèssions dessus lo [[Special:Log/delete|jornâl de les suprèssions]].\n\nPor rapondre un fichiér dedens na pâge, empleyéd un lim de yona de celes fôrmes-que :\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Fichiér.jpg]]</nowiki></code></strong> por empleyér la vèrsion en plêna largior du fichiér\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Fichiér.png|200px|thumb|left|tèxto dèscriptif]]</nowiki></code></strong> por empleyér na miniatura de 200 pixèls de lârjo dedens na bouèt’a gôche avouéc « tèxto dèscriptif » coment dèscripcion\n* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Fichiér.ogg]]</nowiki></code></strong> por liyér tot drêt vers lo fichiér sen lo fâre vêre",
        "upload-permitted": "Tipo{{PLURAL:$2||s}} de fichiérs ôtorisâ{{PLURAL:$2||s}} : $1.",
        "upload-preferred": "Tipo{{PLURAL:$2||s}} de fichiérs prèferâ{{PLURAL:$2||s}} : $1.",
        "upload-prohibited": "Tipo{{PLURAL:$2||s}} de fichiérs dèfendu{{PLURAL:$2||s}} : $1.",
        "badfilename": "Lo nom du fichiér est étâ changiê en « $1 ».",
        "filetype-mime-mismatch": "L’èxtension du fichiér « .$1 » corrèspond pas u tipo MIME dècelâ du fichiér ($2).",
        "filetype-badmime": "Los fichiérs du tipo MIME « $1 » pôvont pas étre tèlèchargiês.",
-       "filetype-bad-ie-mime": "Lo fichiér pôt pas étre tèlèchargiê perce que serêt dècelâ coment « $1 » per Internet Explorer, cen que corrèspond a un tipo de fichiér dèfendu et pués pôt-étre dangerox.",
+       "filetype-bad-ie-mime": "Lo fichiér pôt pas étre tèlèchargiê, serêt dècelâ coment « $1 » per Internet Explorer, cen que corrèspond a un tipo de fichiér dèfendu et pués pôt-étre dangerox.",
        "filetype-unwanted-type": "<strong>« .$1 »</strong> est un tipo de fichiér pas volu.\n{{PLURAL:$3|Lo tipo de fichiér prèferâ est|Los tipos de fichiérs prèferâs sont}} $2.",
        "filetype-banned-type": "<strong>« .$1 »</strong> {{PLURAL:$4|est pas un tipo de fichiér ôtorisâ|sont pas de tipos de fichiérs ôtorisâs}}.\n{{PLURAL:$3|Lo tipo de fichiér ôtorisâ est|Los tipos de fichiérs ôtorisâs sont}} $2.",
        "filetype-missing": "Lo fichiér at gins d’èxtension (coment « .jpg » per ègzemplo).",
        "largefileserver": "Cél fichiér est ples grôs que lo sèrvior est configurâ por l’ôtorisar.",
        "emptyfile": "Lo fichiér que vos éd tèlèchargiê semble étre vouedo.\nCen pôt étre diu a na fôta dedens lo nom du fichiér.\nSe vos plét, controlâd que vos voléd franc tèlèchargiér cél fichiér.",
        "windows-nonascii-filename": "Cél vouiqui recognêt pas los noms de fichiérs avouéc des caractèros spèciâls.",
-       "fileexists": "Un fichiér avouéc cél nom ègziste ja, se vos plét controlâd <strong>[[:$1]]</strong> se {{GENDER:|vos}} éte pas de sûr de lo volêr changiér.\n[[$1|thumb]]",
+       "fileexists": "Un fichiér avouéc cél nom ègziste ja, se vos plét controlâd <strong>[[:$1]]</strong> se {{GENDER:|vos}} éte pas de sûr do volêr changiér.\n[[$1|thumb]]",
        "filepageexists": "La pâge de dèscripcion por cél fichiér est ja étâye fêta ique <strong>[[:$1]]</strong>, mas nion fichiér avouéc cél nom ègziste ora.\nLo rèsumâ que vos voléd buchiér aparêtrat pas dessus la pâge de dèscripcion.\nPor o fâre, vos la devréd changiér a la man.\n[[$1|thumb]]",
        "fileexists-extension": "Un fichiér avouéc un nom d’ense ègziste ja : [[$2|thumb]]\n* Nom du fichiér a tèlèchargiér : <strong>[[:$1]]</strong>\n* Nom du fichiér ègzistent : <strong>[[:$2]]</strong>\nPôt-étre vos voléd empleyér un nom ples prôpro ?",
        "fileexists-thumbnail-yes": "Lo fichiér semble étre un’émâge en talye rèduita <em>(miniatura)</em>.\n[[$1|thumb]]\nSe vos plét, controlâd lo fichiér <strong>[[:$1]]</strong>.\nSe lo fichiér controlâ est la mém’émâge avouéc la talye originâla, y at pas fôta de tèlèchargiér na miniatura de més.",
        "uploaded-animate-svg": "La balisa « animate » est étâye trovâye que porrêt changiér lo href en empleyent l’atribut « from » <code>&lt;$1 $2=\"$3\"&gt;</code> dedens lo fichiér SVG tèlèchargiê.",
        "uploaded-setting-event-handler-svg": "La dèfinicion d’atributs de maneyor d’èvènement est dèfendua, <code>&lt;$1 $2=\"$3\"&gt;</code> est étâ trovâ dedens lo fichiér SVG tèlèchargiê.",
        "uploaded-setting-href-svg": "L’usâjo de la balisa « set » por apondre un atribut « href » a la piéce parenta est dèfendu.",
-       "uploaded-wrong-setting-svg": "L’usâjo de la balisa « set » por apondre na ciba distanta/balyês/scripte a un atribut quint que seye est dèfendu. <code>&lt;set to=\"$1\"&gt;</code> est étâ trovâ dedens lo fichiér SVG tèlèchargiê.",
-       "uploaded-setting-handler-svg": "Los SVG que dèfenéssont l’atribut « handler » avouéc distant/balyês/scripte sont dèfendus. <code>$1=\"$2\"</code> est étâ trovâ dedens lo fichiér SVG tèlèchargiê.",
+       "uploaded-wrong-setting-svg": "L’usâjo de la balisa « set » por apondre na ciba distanta / balyês / scripte a un atribut quint que seye est dèfendu. <code>&lt;set to=\"$1\"&gt;</code> est étâ trovâ dedens lo fichiér SVG tèlèchargiê.",
+       "uploaded-setting-handler-svg": "Los SVG que dèfenéssont l’atribut « handler » avouéc distant / balyês / scripte sont dèfendus. <code>$1=\"$2\"</code> est étâ trovâ dedens lo fichiér SVG tèlèchargiê.",
        "uploaded-remote-url-svg": "Los SVG que dèfenéssont un atribut de stilo quint que seye avouéc un’URL distanta sont dèfendus. <code>$1=\"$2\"</code> est étâ trovâ dedens lo fichiér SVG tèlèchargiê.",
        "uploaded-image-filter-svg": "Un filtro d’émâge avouéc URL est étâ trovâ : <code>&lt;$1 $2=\"$3\"&gt;</code> dedens lo fichiér SVG tèlèchargiê.",
        "uploadscriptednamespace": "Cél fichiér SVG contint un èspâço de noms « $1 » pas ôtorisâ.",
        "uploadinvalidxml": "Lo XML dedens lo fichiér tèlèchargiê at pas possu étre analisâ.",
        "uploadvirus": "Cél fichiér contint un virus !\nDètalys : $1",
-       "uploadjava": "O est un fichiér ZIP que contint un fichiér Java « .class ».\nLo tèlèchargement de fichiérs Java est pas ôtorisâ perce que pôvont èvitar de rèstriccions de sècuritât.",
+       "uploadjava": "O est un fichiér ZIP que contint un fichiér Java « .class ».\nLo tèlèchargement de fichiérs Java est pas ôtorisâ, pôvont èvitar de rèstriccions de sècuritât.",
        "upload-source": "Fichiér sôrsa",
        "sourcefilename": "Nom du fichiér sôrsa :",
        "sourceurl": "URL sôrsa :",
        "watchthisupload": "Siuvre cél fichiér",
        "filewasdeleted": "Un fichiér avouéc cél nom est ja étâ tèlèchargiê et pués suprimâ.\nVos devriâd controlar lo $1 devant que lo tornar tèlèchargiér.",
        "filename-thumb-name": "Cen ressemble a un titro de miniatura. Se vos plét, tèlèchargiéd gins de miniatura ja presenta sur lo mémo vouiqui. Ôtrament, se vos plét corregiéd lo nom du fichiér por que seye ples significatif et pués qu’il èye pas lo prèfixo de miniatura.",
-       "filename-bad-prefix": "Lo nom du fichiér que vos tèlèchargiéd comence per <strong>« $1 »</strong> qu’est en g·ènèrâl un nom pas dèscriptif balyê ôtomaticament per los aparèlys-fotô numericos.\nSe vos plét, chouèsésséd-nen un nom ples dèscriptif.",
+       "filename-bad-prefix": "Lo nom du fichiér que vos tèlèchargiéd comence per <strong>« $1 »</strong> qu’est en g·ènèrâl un nom pas dèscriptif balyê ôtomaticament per los aparèlys-fotô numericos.\nSe vos plét, chouèsésséd-nen un nom ples dèscriptif.",
        "filename-prefix-blacklist": " #<!-- lèssiéd ceta legne justo d’ense --> <pre>\n# La sintaxa est ceta :\n#  * Tot tèxto que siut un « # » tant qu’a la fin de la legne est un comentèro.\n#  * Tota legne pas voueda est un prèfixo tipico de nom de fichiér balyê ôtomaticament per los aparèlys-fotô numericos :\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # quârques enfatâblos\nIMG # g·ènèrico\nJD # Jenoptik\nMGP # Pentax\nPICT # de totes sôrtes\n #</pre> <!-- lèssiéd ceta legne justo d’ense -->",
        "upload-proto-error": "Protocolo fôx",
        "upload-proto-error-text": "Lo tèlèchargement a distance at fôta d’URLs que començont per <code>http://</code> ou ben <code>ftp://</code>.",
        "upload-dialog-button-upload": "Tèlèchargiér",
        "upload-form-label-infoform-title": "Dètalys",
        "upload-form-label-infoform-name": "Nom",
-       "upload-form-label-infoform-name-tooltip": "Un titro dèscriptif sen pariér por lo fichiér, que sèrvirat coment nom de fichiér. Vos pouede empleyér de lengâjo corent avouéc des èspâços. Pas entrebetar l’èxtension du fichiér.",
+       "upload-form-label-infoform-name-tooltip": "Un titro dèscriptif sen pariér por lo fichiér, que sèrvirat coment nom de fichiér. Vos pouede empleyér de lengâjo corent avouéc des èspâços. Pas rapondre l’èxtension du fichiér.",
        "upload-form-label-infoform-description": "Dèscripcion",
        "upload-form-label-infoform-description-tooltip": "Dècrire vito tot cen qu’y at de particuliér por cel’ôvra.\nPor na fotô, mencionar les chouses principâles que sont semondues, l’ocasion ou ben l’endrêt.",
        "upload-form-label-usage-title": "Usâjo",
        "backend-fail-closetemp": "Y at pas moyen de cllôre lo fichiér temporèro.",
        "backend-fail-read": "Y at pas moyen de liére lo fichiér « $1 ».",
        "backend-fail-create": "Y at pas moyen d’ècrire lo fichiér « $1 ».",
-       "backend-fail-maxsize": "Y at pas moyen d’ècrire lo fichiér « $1 » perce qu’il est ples grôs {{PLURAL:$2|qu’un octèt|que $2 octèts}}.",
+       "backend-fail-maxsize": "Y at pas moyen d’ècrire lo fichiér « $1 »il est ples grôs {{PLURAL:$2|qu’un octèt|que $2 octèts}}.",
        "backend-fail-readonly": "Ora lo sistèmo de stocâjo « $1 » est mas qu’en lèctura. La rêson balyêe est : <em>$2</em>",
        "backend-fail-synced": "Lo fichiér « $1 » est dens un ètat dèsordonâ dedens los sistèmos de stocâjo de dedens",
        "backend-fail-connect": "Y at pas moyen de sè branchiér u sistèmo de stocâjo « $1 ».",
        "backend-fail-internal": "Na fôta encognua est arrevâye dedens lo sistèmo de stocâjo « $1 ».",
        "backend-fail-contenttype": "Y at pas moyen de dètèrmenar lo tipo de contegnu du fichiér a stocar dedens « $1 ».",
        "backend-fail-batchsize": "Lo sistèmo de stocâjo at balyê na pârt de $1 {{PLURAL:$1|opèracion|opèracions}} de fichiér ; la limita est $2 {{PLURAL:$2|opèracion|opèracions}}.",
-       "backend-fail-usable": "Y at pas moyen de liére d’ècrire lo fichiér « $1 » a côsa de drêts ensufisents ou ben de rèpèrtouèros conteniors manquents.",
+       "backend-fail-usable": "Y at pas moyen de liére d’ècrire lo fichiér « $1 » a côsa de drêts ensufisents ou ben de rèpèrtouèros de conteniors entrovâblos.",
        "filejournal-fail-dbconnect": "Y at pas moyen de sè branchiér a la bâsa de balyês du jornâl por lo sistèmo de stocâjo « $1 ».",
        "filejournal-fail-dbquery": "Y at pas moyen de betar a jorn la bâsa de balyês du jornâl por lo sistèmo de stocâjo « $1 ».",
        "lockmanager-notlocked": "Y at pas moyen de dècotar « $1 » ; o est pas cotâ.",
        "uploadstash-badtoken": "L’ègzécucion de cel’accion at pas reussi. Pôt-étre perce que voutros identifients de changement ant èxpirâ. Se vos plét, tornâd èprovar.",
        "uploadstash-errclear": "La vouegiê des fichiérs at pas reussi.",
        "uploadstash-refresh": "Rafrèchir la lista des fichiérs",
+       "uploadstash-thumbnail": "vêre la miniatura",
        "invalid-chunk-offset": "Dèplacement de bocon pas justo",
        "img-auth-accessdenied": "Accès refusâ",
-       "img-auth-nopathinfo": "PATH_INFO manquent.\nVoutron sèrvior est pas configurâ por passar cel’enformacion.\nPôt-étre que fonccione en CGI et recognêt vêr pas img_auth.\nVêde https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
+       "img-auth-nopathinfo": "PATH_INFO entrovâblo.\nVoutron sèrvior est pas configurâ por passar cel’enformacion.\nPôt-étre que fonccione en CGI et recognêt vêr pas img_auth.\nVêde https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "img-auth-notindir": "Lo chemin demandâ est pas lo rèpèrtouèro de tèlèchargement configurâ.",
        "img-auth-badtitle": "Y at pas moyen de construire un titro justo dês « $1 ».",
        "img-auth-nologinnWL": "Vos éte pas branchiê et pués « $1 » est pas dedens la lista blanche.",
        "upload_source_file": "(lo fichiér que vos éd chouèsi dês voutron ordenator)",
        "listfiles-delete": "suprimar",
        "listfiles-summary": "Cela pâge spèciâla montre tôs los fichiérs tèlèchargiês.",
-       "listfiles_search_for": "Rechèrchiér un nom de fichiér multimèdiâ :",
+       "listfiles_search_for": "Rechèrchiér un nom de mèdiâ :",
        "listfiles-userdoesnotexist": "Lo comptio utilisator « $1 » est pas encartâ.",
        "imgfile": "fichiér",
        "listfiles": "Lista de fichiérs",
        "listfiles_size": "Talye",
        "listfiles_description": "Dèscripcion",
        "listfiles_count": "Vèrsions",
-       "listfiles-show-all": "Entrebetar les vielyes vèrsions de les émâges",
+       "listfiles-show-all": "Rapondre les vielyes vèrsions de les émâges",
        "listfiles-latestversion": "Vèrsion d’ora",
        "listfiles-latestversion-yes": "Ouè",
        "listfiles-latestversion-no": "Nan",
        "nolinkstoimage": "Niona pâge emplèye cél fichiér.",
        "morelinkstoimage": "Vêde [[Special:WhatLinksHere/$1|més de lims]] de vers cél fichiér.",
        "linkstoimage-redirect": "$1 (redirèccion de fichiér) $2",
-       "duplicatesoffile": "{{PLURAL:$1|Cél fichiér-que est un doblo|Celos $1 fichiérs-que sont des doblos}} de ceti ([[Special:FileDuplicateSearch/$2|més de dètalys]]) :",
+       "duplicatesoffile": "{{PLURAL:$1|Cél fichiér-que est un doblo|Celos $1 fichiérs-que sont de doblos}} de ceti ([[Special:FileDuplicateSearch/$2|més de dètalys]]) :",
        "sharedupload": "Cél fichiér vint de $1 et pôt étre empleyê per d’ôtros projèts.",
        "sharedupload-desc-there": "Cél fichiér vint de $1 et pôt étre empleyê per d’ôtros projèts.\nSe vos plét, vêde sa [$2 pâge de dèscripcion] por més d’enformacions.",
        "sharedupload-desc-here": "Cél fichiér vint de $1 et pôt étre empleyê per d’ôtros projèts.\nLa dèscripcion dessus sa [$2 pâge de dèscripcion] est montrâye ce-desot.",
        "listduplicatedfiles-summary": "O est na lista de fichiérs yô que la vèrsion la ples novèla du fichiér est na copia de la vèrsion la ples novèla d’un ôtro fichiér. Solament los fichiérs locâls sont ègzamenâs.",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] at [[$3|{{PLURAL:$2|un doblo|$2 doblos}}]].",
        "unusedtemplates": "Modèlos pas empleyês",
-       "unusedtemplatestext": "Cela pâge liste totes les pâges de l’èspâço de noms « {{ns:template}} » que sont pas entrebetâyes dedens nion’ôtra pâge.\nOubliâd pas de controlar s’y at gins d’ôtro lim de vers los modèlos devant que los suprimar.",
+       "unusedtemplatestext": "Cela pâge liste totes les pâges de l’èspâço de noms « {{ns:template}} » que sont pas rapondues dedens nion’ôtra pâge.\nOubliâd pas de controlar s’y at gins d’ôtro lim de vers los modèlos devant que los suprimar.",
        "unusedtemplateswlh": "ôtros lims",
        "randompage": "Pâge a l’hasârd",
        "randompage-nopages": "Y at gins de pâge dedens {{PLURAL:$2|cél èspâço|celos èspâços}} de noms-que : $1.",
        "pageswithprop-legend": "Pâges avouéc na propriètât de pâge",
        "pageswithprop-text": "Cela pâge liste les pâges qu’emplèyont na propriètât de pâge particuliére.",
        "pageswithprop-prop": "Nom de la propriètât :",
-       "pageswithprop-submit": "Alar trovar",
+       "pageswithprop-submit": "Emmodar",
        "pageswithprop-prophidden-long": "valor de propriètât de tèxto long cachiêe ($1)",
        "pageswithprop-prophidden-binary": "valor de propriètât binèra cachiêe ($1)",
        "doubleredirects": "Redirèccions dobles",
        "unusedimages": "Fichiérs pas empleyês",
        "wantedcategories": "Catègories demandâyes",
        "wantedpages": "Pâges demandâyes",
-       "wantedpages-summary": "Lista de les pâges inègzistentes qu’ant lo més de lims de vers lor, en èxcllusent les pâges qu’ant ren que des redirèccions pouentent vers lor. Por avêr na lista de les pâges inègzistentes qu’ant de redirèccions pouentent vers lor, vêde la [[{{#special:BrokenRedirects}}|lista de les redirèccions câsses]].",
+       "wantedpages-summary": "Lista de les pâges inègzistentes qu’ant lo més de lims de vers lor, en èxcllusent les pâges qu’ant ren que de redirèccions pouentent vers lor. Por avêr na lista de les pâges inègzistentes qu’ant de redirèccions pouentent vers lor, vêde la [[{{#special:BrokenRedirects}}|lista de les redirèccions câsses]].",
        "wantedpages-badtitle": "Titro pas justo dedens l’ensemblo de rèsultats : $1",
        "wantedfiles": "Fichiérs demandâs",
        "wantedfiletext-cat": "Celos fichiérs-que sont empleyês, mas ègzistont pas. Los fichiérs de dèpôts de defôr pôvont étre listâs mémo s’ègzistont. Tôs celos fôx positifs seront <del>barrâs</del>. Et pués les pâges qu’apondont de fichiérs qu’ègzistont pas sont listâs dedens [[:$1]].",
        "mostrevisions": "Pâges les ples changiêes",
        "prefixindex": "Totes les pâges que començont per...",
        "prefixindex-namespace": "Totes les pâges avouéc prèfixo (èspâço de noms $1)",
-       "prefixindex-submit": "Listar",
+       "prefixindex-submit": "Montrar",
        "prefixindex-strip": "Enlevar lo prèfixo dedens la lista",
        "shortpages": "Pâges côrtes",
        "longpages": "Pâges longes",
        "protectedpages-unknown-timestamp": "Encognua",
        "protectedpages-unknown-performer": "Utilisator encognu",
        "protectedtitles": "Titros protègiês",
-       "protectedtitles-summary": "Cela pâge liste los titros que sont ora protègiês contre la crèacion. Por na lista de les pâges ègzistentes protègiêes, vêde [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
+       "protectedtitles-summary": "Cela pâge liste los titros que sont ora protègiês contre la crèacion. Por na lista de les pâges ègzistentes que sont protègiêes, vêde [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Ora nion titro est protègiê avouéc celos paramètros.",
        "protectedtitles-submit": "Fâre vêre los titros",
        "listusers": "Lista des utilisators",
        "usereditcount": "$1 changement{{PLURAL:$1||s}}",
        "usercreated": "Fêt{{GENDER:$3||a}} lo $1 a $2",
        "newpages": "Pâges novèles",
-       "newpages-submit": "Listar",
+       "newpages-submit": "Montrar",
        "newpages-username": "Nom d’utilisator :",
        "ancientpages": "Pâges les ples vielyes",
        "move": "Dèplaciér",
        "pager-newer-n": "{{PLURAL:$1|ples novèla|$1 ples novèles}}",
        "pager-older-n": "{{PLURAL:$1|ples vielye|$1 ples vielyes}}",
        "suppress": "Rèprimar",
-       "querypage-disabled": "Cela pâge spèciâla est dèsactivâye por des rêsons de capacitât.",
+       "querypage-disabled": "Cela pâge spèciâla est dèsactivâye por de rêsons de capacitât.",
        "apihelp": "Éde de l’API",
        "apihelp-no-such-module": "Lo modulo « $1 » est entrovâblo.",
        "apisandbox": "Bouèta de sabla API",
        "specialloguserlabel": "Ôtor :",
        "speciallogtitlelabel": "Ciba (titro ou ben {{ns:user}}:nom d’utilisator por un utilisator) :",
        "log": "Jornâls",
-       "logeventslist-submit": "Listar",
+       "logeventslist-submit": "Montrar",
        "all-logs-page": "Tôs los jornâls publicos",
        "alllogstext": "Viua combinâye de tôs los jornâls disponiblos dessus {{SITENAME}}.\nVos pouede rètrendre la viua en chouèséssent un tipo de jornâl, lo nom d’utilisator (sensiblo a la câssa) ou ben la pâge regardâye (sensibl’a la câssa avouéc).",
-       "logempty": "Niona piéce que corrèspond sur lo jornâl.",
+       "logempty": "Niona piéce d’ense sur lo jornâl.",
        "log-title-wildcard": "Rechèrchiér entre-mié los titros que començont per cél tèxto",
        "showhideselectedlogentries": "Changiér la visibilitât de les entrês de jornâl chouèsies",
        "log-edit-tags": "Changiér les balises de les entrês de jornâl chouèsies",
        "allpagesto": "Fâre vêre les pâges tant qu’a :",
        "allarticles": "Totes les pâges",
        "allinnamespace": "Totes les pâges (dedens l’èspâço de noms $1)",
-       "allpagessubmit": "Listar",
+       "allpagessubmit": "Emmodar",
        "allpagesprefix": "Fâre vêre les pâges que començont per lo prèfixo :",
        "allpagesbadtitle": "Lo titro de la pâge balyêe est pas justo ou ben contint un prèfixo entèrlengoua entèrvouiqui resèrvâ.\nContint de sûr yon ou ben un mouél de caractèros que pôvont pas étre empleyês dedens los titros.",
        "allpages-bad-ns": "{{SITENAME}} at gins d’èspâço de noms « $1 ».",
        "cachedspecial-viewing-cached-ts": "Vos vêde na vèrsion betâye en cacho de cela pâge, que porrêt pas étre a chavon a jorn.",
        "cachedspecial-refresh-now": "Vêre la ples novèla.",
        "categories": "Catègories",
-       "categories-submit": "Listar",
-       "categoriespagetext": "{{PLURAL:$1|Cela catègoria-que contint|Celes catègories-que contegnont}} de pâges de fichiérs multimèdiâ.\nLes [[Special:UnusedCategories|catègories pas empleyêes]] sont pas montrâyes ique.\nVêde avouéc les [[Special:WantedCategories|catègories demandâyes]].",
+       "categories-submit": "Montrar",
+       "categoriespagetext": "{{PLURAL:$1|Cela catègoria-que contint|Celes catègories-que contegnont}} de pâges de mèdiâs.\nLes [[Special:UnusedCategories|catègories pas empleyêes]] sont pas montrâyes ique.\nVêde avouéc les [[Special:WantedCategories|catègories demandâyes]].",
        "categoriesfrom": "Fâre vêre les catègories dês :",
        "special-categories-sort-count": "chouèx per comptâjo",
        "special-categories-sort-abc": "chouèx alfabètico",
        "linksearch-line": "$1 est liyê dês $2",
        "linksearch-error": "Los mètacaractèros pôvont étre empleyês ren qu’u comencement du nom de domêno de l’hôto.",
        "listusersfrom": "Fâre vêre los utilisators dês :",
-       "listusers-submit": "Listar",
+       "listusers-submit": "Montrar",
        "listusers-noresult": "Nion utilisator est étâ trovâ.",
        "listusers-blocked": "(blocâ{{GENDER:$1||ye}})",
        "activeusers": "Lista des utilisators actifs",
        "listgrouprights-namespaceprotection-header": "Rèstriccions d’èspâço de noms",
        "listgrouprights-namespaceprotection-namespace": "Èspâço de noms",
        "listgrouprights-namespaceprotection-restrictedto": "Drêt(s) que pèrmèt(ont) a l’utilisator de changiér",
+       "listgrants": "Ôtorisacions",
+       "listgrants-summary": "Vê-que na lista des drêts avouéc lor accès associyê ux drêts d’utilisator. Los utilisators pôvont ôtorisar les aplicacions a empleyér lor comptio, mas avouéc des drêts limitâs d’aprés los drêts que l’utilisator at balyê a l’aplicacion. Portant un’aplicacion fassent u nom d’un utilisator pôt pas ben empleyér de drêts que l’utilisator at pas.\nY pôt avêr [[{{MediaWiki:Listgrouprights-helppage}}|més d’enformacions]] sur los drêts endividuèls.",
+       "listgrants-grant": "Ôtorisacion",
+       "listgrants-rights": "Drêts",
+       "trackingcategories": "Catègories de gouârda",
+       "trackingcategories-summary": "Cela pâge liste les catègories de gouârda que sont emplies ôtomaticament per MediaWiki. Lors noms pôvont étre changiês en changient los mèssâjos sistèmo que corrèspondont dedens l’èspâço de noms {{ns:8}}.",
+       "trackingcategories-msg": "Catègoria de gouârda",
+       "trackingcategories-name": "Nom du mèssâjo",
+       "trackingcategories-desc": "Critèros de raponsa de la catègoria",
+       "noindex-category-desc": "La pâge est pas endèxâye per los robots, contint lo mot magico <code><nowiki>__NOINDEX__</nowiki></code> et est dedens un èspâço de noms yô que cél marcâjo est ôtorisâ.",
+       "index-category-desc": "La pâge contint un <code><nowiki>__INDEX__</nowiki></code> (et est dedens un èspâço de noms yô que cél marcâjo est ôtorisâ), et pués serat vêr endèxâye per los robots pendent qu’o serêt pas étâ normalament.",
+       "post-expand-template-inclusion-category-desc": "La talye de la pâge dèpâsse <code>$wgMaxArticleSize</code> aprés l’èxpension de tôs los modèlos, cen fât que doux-três modèlos ant vêr pas étâ èpatâs.",
+       "post-expand-template-argument-category-desc": "La pâge dèpâsse <code>$wgMaxArticleSize</code> aprés l’èxpension d’un argument de modèlo (quârque-ren entre-mié colâdes triples, coment <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "La pâge emplèye trop de fonccions parsiors que revegnont chieres (coment <code>#ifexist</code>). Vêde [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "La pâge contint un lim de fichiér câsso (un lim por apondre un fichiér pendent que ceti ègziste pas).",
+       "hidden-category-category-desc": "La catègoria contint <code><nowiki>__HIDDENCAT__</nowiki></code> dedens son contegnu, cen qu’empache per dèfôt sa viua dens la bouèta des lims de catègoria sur les pâges.",
+       "trackingcategories-nodesc": "Niona dèscripcion disponibla.",
+       "trackingcategories-disabled": "La catègoria est dèsactivâye",
        "mailnologin": "Nion’adrèce d’èxpèdior",
-       "mailnologintext": "Vos dête étre [[Special:UserLogin|branchiê]] et avêr spècifiâ un’adrèce èlèctronica justa dens voutres [[Special:Preferences|prèferences]] por povêr mandar des mèssâjos a d’ôtros utilisators.",
-       "emailuser": "Lui mandar un mèssâjo",
-       "emailuser-title-target": "Mandar un mèssâjo a cet’utilisat{{GENDER:$1|or|rice}}",
+       "mailnologintext": "Vos dête étre [[Special:UserLogin|branchiê]] et pués avêr un’adrèce èlèctronica justa dens voutres [[Special:Preferences|prèferences]] por povêr mandar de mèssâjos a d’ôtros utilisators.",
+       "emailuser": "Y mandar un mèssâjo",
+       "emailuser-title-target": "Mandar un mèssâjo a {{GENDER:$1|cél utilisator|cel’utilisatrice}}",
        "emailuser-title-notarget": "Mandar un mèssâjo a l’utilisator",
-       "emailpagetext": "Vos pouede empleyér lo formulèro ce-desot por mandar un mèssâjo a cet’utilisat{{GENDER:$1|or|rice}}.\nL’adrèce èlèctronica que vos éd buchiêe dens voutres [[Special:Preferences|prèferences]] aparêtrat dedens lo champ « Èxpèdior » de voutron mèssâjo ; d’ense, lo dèstinatèro vos porrat rèpondre tot drêt.",
+       "emailpagetext": "Vos pouede empleyér lo formulèro ce-desot por mandar un mèssâjo a {{GENDER:$1|cél utilisator|cel’utilisatrice}}.\nL’adrèce èlèctronica que vos éd buchiêe dens voutres [[Special:Preferences|prèferences]] aparêtrat dedens lo champ « Èxpèdior » de voutron mèssâjo, cen fât que lo dèstinatèro vos porrat rèpondre tot drêt.",
        "defemailsubject": "Mèssâjo de {{SITENAME}} de l’utilisator « $1 »",
        "usermaildisabled": "L’èxpèdicion de mèssâjos entre utilisators est dèsactivâye",
-       "usermaildisabledtext": "Vos pouede pas mandar de mèssâjos a d’ôtros utilisators sur ceti vouiqui",
+       "usermaildisabledtext": "Vos pouede pas mandar de mèssâjos a d’ôtros utilisators sur cél vouiqui",
        "noemailtitle": "Nion’adrèce èlèctronica",
-       "noemailtext": "Cet’utilisator at pas spècifiâ un’adrèce èlèctronica justa.",
+       "noemailtext": "Cél utilisator at pas spècifiâ un’adrèce èlèctronica justa.",
        "nowikiemailtext": "Cél utilisator at chouèsi de pas recêvre de mèssâjos de la pârt d’ôtros utilisators.",
        "emailnotarget": "Nom d’utilisator du dèstinatèro pas ègzistent pas justo.",
        "emailtarget": "Buchiéd lo nom d’utilisator du dèstinatèro",
        "emailccsubject": "Copia de voutron mèssâjo a $1 : $2",
        "emailsent": "Mèssâjo mandâ",
        "emailsenttext": "Voutron mèssâjo est étâ mandâ per mèssageria èlèctronica.",
-       "emailuserfooter": "Ceti mèssâjo est étâ mandâ per « $1 » a « $2 » per la fonccion « Lui mandar un mèssâjo » de {{SITENAME}}.",
+       "emailuserfooter": "Cél mèssâjo est étâ {{GENDER:$1|mandâ}} per « $1 » a « {{GENDER:$2|$2}} » per la fonccion « {{int:emailuser}} » de {{SITENAME}}.",
        "usermessage-summary": "At lèssiê un mèssâjo sistèmo.",
        "usermessage-editor": "Mèssagiér du sistèmo",
        "usermessage-template": "MediaWiki:MèssâjoUtilisator",
-       "watchlist": "Lista de siuvu",
-       "mywatchlist": "Lista de siuvu",
+       "watchlist": "Lista de gouârda",
+       "mywatchlist": "Lista de gouârda",
        "watchlistfor2": "Por $1 $2",
-       "nowatchlist": "Vos éd gins de piéce dedens voutra lista de siuvu.",
-       "watchlistanontext": "Se vos plét, vos vos dête $1 por povêr vêre ou ben changiér les piéces de voutra lista de siuvu.",
+       "nowatchlist": "Vos éd gins de piéce dedens voutra lista de gouârda.",
+       "watchlistanontext": "Se vos plét, branchiéd-vos por vêre changiér les piéces de voutra lista de gouârda.",
        "watchnologin": "Pas branchiê",
-       "addwatch": "Apondre a la lista de siuvu",
-       "addedwatchtext": "La pâge « [[:$1]] » est étâye apondua a voutra [[Special:Watchlist|lista de siuvu]].\nLos changements que vegnont de ceta pâge et de la sina pâge de discussion y seront listâs.",
-       "removewatch": "Enlevar de la lista de siuvu",
-       "removedwatchtext": "La pâge « [[:$1]] » est étâye enlevâye de voutra [[Special:Watchlist|lista de siuvu]].",
+       "addwatch": "Apondre a la lista de gouârda",
+       "addedwatchtext": "« [[:$1]] » et sa pâge de discussion sont étâyes apondues a voutra [[Special:Watchlist|lista de gouârda]].",
+       "addedwatchtext-short": "La pâge « $1 » est étâye apondua a voutra lista de gouârda.",
+       "removewatch": "Enlevar de la lista de gouârda",
+       "removedwatchtext": "« [[:$1]] » et sa pâge de discussion sont étâyes enlevâyes de voutra [[Special:Watchlist|lista de gouârda]].",
+       "removedwatchtext-short": "La pâge « $1 » est étâye enlevâye de voutra lista de gouârda.",
        "watch": "Siuvre",
-       "watchthispage": "Siuvre ceta pâge",
+       "watchthispage": "Siuvre cela pâge",
        "unwatch": "Pas més siuvre",
        "unwatchthispage": "Pas més siuvre",
        "notanarticle": "O est pas na pâge de contegnu",
        "notvisiblerev": "La dèrriére vèrsion per un ôtr’utilisator est étâye suprimâye",
-       "watchlist-details": "Y at $1 pâge{{PLURAL:$1||s}} dedens voutra lista de siuvu, sen comptar les pâges de discussion.",
+       "watchlist-details": "Y at $1 pâge{{PLURAL:$1||s}} dedens voutra lista de gouârda, sen comptar a pârt les pâges de discussion.",
        "wlheader-enotif": "La notificacion per mèssageria èlèctronica est activâye.",
-       "wlheader-showupdated": "Les pâges que sont étâyes changiêes dês voutra dèrriére visita sont montrâyes en '''grâs'''.",
-       "wlnote": "Vê-que {{PLURAL:$1|lo dèrriér changement fêt|los '''$1''' dèrriérs changements fêts}} pendent {{PLURAL:$2|l’hora passâye|les '''$2''' hores passâyes}}, dês $3 a $4.",
-       "wlshowlast": "Montrar les $1 hores passâyes, los $2 jorns passâs ou ben",
-       "watchlist-options": "Chouèx de la lista de siuvu",
-       "watching": "Siuvu...",
-       "unwatching": "Fin du siuvu...",
-       "watcherrortext": "Na fôta est arrevâye pendent lo changement de la configuracion de voutra lista de siuvu por « $1 ».",
-       "enotif_reset": "Marcar totes les pâges coment visitâyes",
+       "wlheader-showupdated": "Les pâges que sont étâyes changiêes dês voutra dèrriére vesita sont montrâyes en <strong>grôs</strong>.",
+       "wlnote": "Vê-que {{PLURAL:$1|lo dèrriér changement fêt|los <strong>$1</strong> dèrriérs changements fêts}} pendent {{PLURAL:$2|l’hora passâye|les <strong>$2</strong> hores passâyes}}, tant qu’u $3 a $4.",
+       "wlshowlast": "Montrar les $1 hores passâyes, los $2 jorns passâs",
+       "watchlist-hide": "Cachiér",
+       "watchlist-submit": "Montrar",
+       "wlshowtime": "Temps a fâre vêre :",
+       "wlshowhideminor": "petiôts changements",
+       "wlshowhidebots": "robots",
+       "wlshowhideliu": "utilisators encartâs",
+       "wlshowhideanons": "utilisators anonimos",
+       "wlshowhidepatr": "changements gouardâs",
+       "wlshowhidemine": "mos changements",
+       "wlshowhidecategorization": "catègorisacion de les pâges",
+       "watchlist-options": "Chouèx de la lista de gouârda",
+       "watching": "Comencement de la gouârda...",
+       "unwatching": "Fin de la gouârda...",
+       "watcherrortext": "Na fôta est arrevâye pendent lo changement de la configuracion de voutra lista de gouârda por « $1 ».",
+       "enotif_reset": "Marcar totes les pâges coment vesitâyes",
        "enotif_impersonal_salutation": "Utilisator de {{SITENAME}}",
-       "enotif_subject_deleted": "La pâge $1 dessus {{SITENAME}} est étâye suprimâye per {{GENDER:$2|$2}}",
-       "enotif_subject_created": "La pâge $1 dessus {{SITENAME}} est étâye fêta per {{GENDER:$2|$2}}",
-       "enotif_subject_moved": "La pâge $1 dessus {{SITENAME}} est étâye dèplaciêe per {{GENDER:$2|$2}}",
-       "enotif_subject_restored": "La pâge $1 dessus {{SITENAME}} est étâye refêta per {{GENDER:$2|$2}}",
-       "enotif_subject_changed": "La pâge $1 dessus {{SITENAME}} est étâye changiêe per {{GENDER:$2|$2}}",
-       "enotif_body_intro_deleted": "La pâge $1 dessus {{SITENAME}} est étâye suprimâye lo $PAGEEDITDATE per {{GENDER:$2|$2}}, vêde $3.",
-       "enotif_body_intro_created": "La pâge $1 dessus {{SITENAME}} est étâye fêta lo $PAGEEDITDATE per {{GENDER:$2|$2}}, vêde $3 por la vèrsion d’ora.",
-       "enotif_body_intro_moved": "La pâge $1 dessus {{SITENAME}} est étâye dèplaciêe lo $PAGEEDITDATE per {{GENDER:$2|$2}}, vêde $3 por la vèrsion d’ora.",
-       "enotif_body_intro_restored": "La pâge $1 dessus {{SITENAME}} est étâye refêta lo $PAGEEDITDATE per {{GENDER:$2|$2}}, vêde $3 por la vèrsion d’ora.",
-       "enotif_body_intro_changed": "La pâge $1 dessus {{SITENAME}} est étâye changiêe lo $PAGEEDITDATE per {{GENDER:$2|$2}}, vêde $3 por la vèrsion d’ora.",
-       "enotif_lastvisited": "Vêde $1 por tôs los changements dês voutra dèrriére visita.",
+       "enotif_subject_deleted": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|suprimâye}} per $2",
+       "enotif_subject_created": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|fêta}} per $2",
+       "enotif_subject_moved": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|dèplaciêe}} per $2",
+       "enotif_subject_restored": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|refêta}} per $2",
+       "enotif_subject_changed": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|changiêe}} per $2",
+       "enotif_body_intro_deleted": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|suprimâye}} lo $PAGEEDITDATE per $2, vêde $3.",
+       "enotif_body_intro_created": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|fêta}} lo $PAGEEDITDATE per $2, vêde $3 por la vèrsion d’ora.",
+       "enotif_body_intro_moved": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|dèplaciêe}} lo $PAGEEDITDATE per $2, vêde $3 por la vèrsion d’ora.",
+       "enotif_body_intro_restored": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|refêta}} lo $PAGEEDITDATE per $2, vêde $3 por la vèrsion d’ora.",
+       "enotif_body_intro_changed": "La pâge $1 dessus {{SITENAME}} est étâye {{GENDER:$2|changiêe}} lo $PAGEEDITDATE per $2, vêde $3 por la vèrsion d’ora.",
+       "enotif_lastvisited": "Vêde $1 por tôs los changements dês voutra dèrriére vesita.",
        "enotif_lastdiff": "Vêde $1 por vêre cél changement.",
        "enotif_anon_editor": "utilisator anonimo $1",
-       "enotif_body": "Chier(a) $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nRèsumâ du contributor : $PAGESUMMARY $PAGEMINOREDIT\n\nVeriéd-vos vers lo contributor :\nmèl. : $PAGEEDITOR_EMAIL\nvouiqui : $PAGEEDITOR_WIKI\n\nY arat gins d’ôtra notificacion en câs de changements a vegnir, du muens que vos visiteyâd cela pâge. Vos pouede asse-ben rebetar a zérô los segnalements de notificacion por totes les pâges de voutra lista de siuvu.\n\nVoutron sistèmo de notificacion de {{SITENAME}}\n\n--\nPor changiér la configuracion de notificacion per mèssageria èlèctronica, visitâd\n{{canonicalurl:{{#special:Preferences}}}}\n\nPor changiér la configuracion de voutra lista de siuvu, visitâd\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPor suprimar la pâge de voutra lista de siuvu, visitâd\n$UNWATCHURL\n\nAvis et assistance de ples :\n$HELPPAGE",
+       "enotif_body": "Chier{{GENDER:$WATCHINGUSERNAME||a}} $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nRèsumâ du contributor : $PAGESUMMARY $PAGEMINOREDIT\n\nVeriéd-vos vers lo contributor :\nmèl. : $PAGEEDITOR_EMAIL\nvouiqui : $PAGEEDITOR_WIKI\n\nY arat gins d’ôtra notificacion en câs de changements a vegnir, a muens que vos vesiteyéd cela pâge a pêna branchiê. Vos pouede asse-ben rebetar a zérô los marcâjos de notificacion por totes les pâges de voutra lista de gouârda.\n\nVoutron sistèmo de notificacion de {{SITENAME}}\n\n--\nPor changiér la configuracion de notificacion per mèssageria èlèctronica, vesitâd\n{{canonicalurl:{{#special:Preferences}}}}\n\nPor changiér la configuracion de voutra lista de gouârda, vesitâd\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPor suprimar la pâge de voutra lista de gouârda, vesitâd\n$UNWATCHURL\n\nAvis et éde de més :\n$HELPPAGE",
        "created": "fêta",
        "changed": "changiê",
        "deletepage": "Suprimar la pâge",
        "confirm": "Confirmar",
        "excontent": "lo contegnu ére : « $1 »",
-       "excontentauthor": "lo contegnu ére : « $1 » (et lo solèt contributor ére « [[Special:Contributions/$2|$2]] »)",
+       "excontentauthor": "lo contegnu ére : « $1 », et lo solèt contributor « [[Special:Contributions/$2|$2]] » ([[User talk:$2|discutar]])",
        "exbeforeblank": "lo contegnu devant blanchiment ére : « $1 »",
        "delete-confirm": "Suprimar « $1 »",
        "delete-legend": "Suprimar",
-       "historywarning": "'''Atencion :''' la pâge que vos éte prèst a suprimar at un historico avouéc a pou prés $1 vèrsion{{PLURAL:$1||s}} :",
-       "confirmdeletetext": "Vos éte prèst a suprimar na pâge et pués tot lo sin historico.\nSe vos plét, confirmâd qu’o est franc cen que vos voléd fâre, que vos en compregnéd les consèquences et pués que vos o féte en acôrd avouéc les [[{{MediaWiki:Policy-url}}|règlles de dedens]].",
+       "historywarning": "<strong>Atencion :</strong> la pâge que vos éte prèst a suprimar at un historico avouéc $1 vèrsion{{PLURAL:$1||s}} :",
+       "historyaction-submit": "Montrar",
+       "confirmdeletetext": "Vos éte prèst a suprimar na pâge et pués tot son historico.\nSe vos plét, confirmâd qu’o est franc cen que vos voléd fâre, que vos en compregnéd les consèquences et pués que vos o féte en acôrd avouéc les [[{{MediaWiki:Policy-url}}|politiques]].",
        "actioncomplete": "Accion fêta",
        "actionfailed": "L’accion at pas reussi",
        "deletedtext": "« $1 » est étâye suprimâye.\nVêde lo $2 por na lista de les novèles suprèssions.",
-       "dellogpage": "Jornal de les suprèssions",
+       "dellogpage": "Jornâl de les suprèssions",
        "dellogpagetext": "Vê-que na lista de les suprèssions les ples novèles.",
-       "deletionlog": "jornal de les suprèssions",
-       "reverted": "Vèrsion devant rètablia",
+       "deletionlog": "jornâl de les suprèssions",
+       "reverted": "Rèvocâ a la vèrsion devant",
        "deletecomment": "Rêson :",
-       "deleteotherreason": "Ôtra rêson / rêson de ples :",
+       "deleteotherreason": "Ôtra rêson ou ben rêson de més :",
        "deletereasonotherlist": "Ôtra rêson",
-       "deletereason-dropdown": "*Rêsons corentes de suprèssion\n** Demanda de l’ôtor\n** Violacion du drêt d’ôtor\n** Vandalismo",
+       "deletereason-dropdown": "* Rêsons corentes de suprèssion\n** Mèssâjo cofo\n** Vandalismo\n** Violacion du drêt d’ôtor\n** Demanda de l’ôtor\n** Redirèccion câssa",
        "delete-edit-reasonlist": "Changiér les rêsons de suprèssion",
-       "delete-toobig": "Ceta pâge at un grôs historico de changements avouéc més de $1 vèrsion{{PLURAL:$1||s}}.\nLa suprèssion de pâges d’ense est étâye rètrenta por prèvegnir des pèrturbacions emprèvues de {{SITENAME}}.",
-       "delete-warning-toobig": "Ceta pâge at un grôs historico de changements avouéc més de $1 vèrsion{{PLURAL:$1||s}}.\nLa suprimar pôt troblar la mârche de la bâsa de balyês de {{SITENAME}} ;\na fâre avouéc prudence.",
+       "delete-toobig": "Cela pâge at un grôs historico de changements avouéc més de $1 vèrsion{{PLURAL:$1||s}}.\nLa suprèssion de pâges d’ense est étâye rètrenta por prèvegnir de pèrturbacions emprèviues de {{SITENAME}}.",
+       "delete-warning-toobig": "Cela pâge at un grôs historico de changements avouéc més de $1 vèrsion{{PLURAL:$1||s}}.\nLa suprimar pôt troblar la mârche de la bâsa de balyês de {{SITENAME}} ;\na fâre avouéc prudence.",
+       "deleteprotected": "Vos pouede pas suprimar cela pâge, el est étâye protègiêe.",
+       "deleting-backlinks-warning": "<strong>Atencion :</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|D’ôtres pâges]] ant un lim de vers ou ben transcllusont la pâge que vos voléd suprimar.",
        "rollback": "Rèvocar los changements",
        "rollbacklink": "rèvocar",
        "rollbacklinkcount": "rèvocar $1 changement{{PLURAL:$1||s}}",
        "rollbacklinkcount-morethan": "rèvocar més de $1 changement{{PLURAL:$1||s}}",
        "rollbackfailed": "La rèvocacion at pas reussi",
-       "cantrollback": "Y at pas moyen de rèvocar lo changement ;\nlo dèrriér contributor est lo solèt ôtor de ceta pâge.",
-       "alreadyrolled": "Y at pas moyen de rèvocar lo dèrriér changement de la pâge « [[:$1]] » fêt per [[User:$2|$2]] ([[User talk:$2|discutar]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) ;\nun ôtro at ja changiê ou ben rèvocâ la pâge.\n\nLo dèrriér changement de la pâge est étâ fêt per [[User:$3|$3]] ([[User talk:$3|discutar]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
+       "cantrollback": "Y at pas moyen de rèvocar lo changement ;\nlo dèrriér contributor est lo solèt ôtor de cela pâge.",
+       "alreadyrolled": "Y at pas moyen de rèvocar lo dèrriér changement de la pâge « [[:$1]] » fêt per [[User:$2|$2]] ([[User talk:$2|discutar]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) ;\nun ôtro at ja changiê rèvocâ la pâge.\n\nLo dèrriér changement de la pâge est étâ fêt per [[User:$3|$3]] ([[User talk:$3|discutar]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Lo rèsumâ de changement ére : <em>$1</em>.",
        "revertpage": "Rèvocacion des changements de [[Special:Contributions/$2|$2]] ([[User talk:$2|discutar]]) de vers la dèrriére vèrsion de [[User:$1|$1]]",
-       "revertpage-nouser": "Rèvocacion des changements de (nom d’utilisator enlevâ) de vers la dèrriére vèrsion de [[User:$1|$1]]",
+       "revertpage-nouser": "Rèvocacion des changements per un utilisator cachiê de vers la dèrriére vèrsion de {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Rèvocacion des changements de $1 ;\nrèstoracion de la dèrriére vèrsion de $2.",
-       "sessionfailure-title": "Falyita de sèance",
-       "sessionfailure": "Voutra sèance de branchement semble avêr des problèmos ;\ncel’accion est étâye anulâye en prèvencion d’un piratâjo de sèance.\nSe vos plét, clicâd dessus « Devant », rechargiéd la pâge de yô que vos vegnéd et pués tornâd èprovar.",
-       "protectlogpage": "Jornal de les protèccions",
+       "sessionfailure-title": "Falyita de sèssion",
+       "sessionfailure": "Voutra sèssion de branchement semble avêr de problèmos ;\ncel’accion est étâye anulâye en prèvencion d’un piratâjo de sèssion.\nSe vos plét, cllicâd dessus « Devant », rechargiéd la pâge de yô que vos vegnéd et pués tornâd èprovar.",
+       "changecontentmodel": "Changiér lo modèlo de contegnu d’una pâge",
+       "changecontentmodel-legend": "Changiér lo modèlo de contegnu",
+       "changecontentmodel-title-label": "Titro de la pâge",
+       "changecontentmodel-model-label": "Novél modèlo de contegnu",
+       "changecontentmodel-reason-label": "Rêson :",
+       "changecontentmodel-submit": "Changiér",
+       "changecontentmodel-success-title": "Lo modèlo de contegnu est étâ changiê",
+       "changecontentmodel-success-text": "Lo tipo de contegnu de [[:$1]] est étâ changiê.",
+       "changecontentmodel-cannot-convert": "Lo contegnu dessus [[:$1]] at pas possu étre convèrti en un tipo de $2.",
+       "changecontentmodel-nodirectediting": "Lo modèlo de contegnu $1 recognêt pas lo changement drêt",
+       "log-name-contentmodel": "Jornâl des changements de modèlo de contegnu",
+       "log-description-contentmodel": "Èvènements sur los modèlos de contegnu d’una pâge",
+       "logentry-contentmodel-new": "$1 at {{GENDER:$2|fêt}} la pâge $3 en empleyent un modèlo de contegnu « $5 » ôtro que celi per dèfôt",
+       "logentry-contentmodel-change": "$1 at {{GENDER:$2|changiê}} lo modèlo de contegnu de la pâge $3 de « $4 » en « $5 »",
+       "logentry-contentmodel-change-revertlink": "rèvocar",
+       "logentry-contentmodel-change-revert": "rèvocar",
+       "protectlogpage": "Jornâl de les protèccions",
        "protectlogtext": "Vê-que na lista des changements de les protèccions de pâges.\nVêde la [[Special:ProtectedPages|lista de les pâges protègiêes]] por la lista de les protèccions que sont ora actives.",
        "protectedarticle": "at protègiê « [[$1]] »",
        "modifiedarticleprotection": "at changiê lo nivél de protèccion de « [[$1]] »",
        "protect-title-notallowed": "Vêre lo nivél de protèccion de « $1 »",
        "prot_1movedto2": "at dèplaciê [[$1]] vers [[$2]]",
        "protect-badnamespace-title": "Èspâço de noms pas protèjâblo",
-       "protect-badnamespace-text": "Les pâges dedens cet’èspâço de noms pôvont pas étre protègiêes.",
+       "protect-badnamespace-text": "Les pâges dedens cél èspâço de noms pôvont pas étre protègiêes.",
        "protect-norestrictiontypes-text": "Cela pâge pôt pas étre protègiêe, y at gins de tipo de rèstriccion disponiblo.",
        "protect-norestrictiontypes-title": "Pâge pas protèjâbla",
        "protect-legend": "Confirmar la protèccion",
        "protectcomment": "Rêson :",
        "protectexpiry": "Dâta d’èxpiracion :",
-       "protect_expiry_invalid": "La dâta d’èxpiracion est pas justa.",
-       "protect_expiry_old": "La dâta d’èxpiracion est ja passâye.",
-       "protect-unchain-permissions": "Dèvèrrolyér adés més de chouèx de protèccion",
-       "protect-text": "Ique vos pouede vêre et changiér lo nivél de protèccion de la pâge '''$1'''.",
-       "protect-locked-blocked": "Vos pouede pas changiér los nivéls de protèccion tant que vos éte blocâ{{GENDER:||ye|(ye)}}.\nVê-que la configuracion d’ora de la pâge '''$1''' :",
-       "protect-locked-dblock": "Los nivéls de protèccion pôvont pas étre changiês, la bâsa de balyês est vèrrolyêe.\nVê-que la configuracion d’ora de la pâge '''$1''' :",
-       "protect-locked-access": "Voutron compto at pas los drêts nècèssèros por changiér los nivéls de protèccion de pâges.\nVê-que la configuracion d’ora de la pâge '''$1''' :",
-       "protect-cascadeon": "Ora cela pâge-que est protègiêe, el est entrebetâye dedens {{PLURAL:$1|ceta pâge qu’est étâye protègiêe|cetes pâges que sont étâyes protègiêes}} avouéc lo chouèx « protèccion en cascâda » activâ.\nVos pouede changiér lo nivél de protèccion de cela pâge sen que cen afècte la protèccion en cascâda.",
+       "protect_expiry_invalid": "Lo temps d’èxpiracion est pas justo.",
+       "protect_expiry_old": "Lo temps d’èxpiracion est ja passâ.",
+       "protect-unchain-permissions": "Dècotar adés més de chouèx de protèccion",
+       "protect-text": "Ique vos pouede vêre et changiér lo nivél de protèccion de la pâge <strong>$1</strong>.",
+       "protect-locked-blocked": "Vos pouede pas changiér los nivéls de protèccion tant que vos éte blocâ{{GENDER:||ye}}.\nVê-que la configuracion d’ora de la pâge <strong>$1</strong> :",
+       "protect-locked-dblock": "Los nivéls de protèccion pôvont pas étre changiês, la bâsa de balyês est cotâye.\nVê-que la configuracion d’ora de la pâge <strong>$1</strong> :",
+       "protect-locked-access": "Voutron comptio at pas los drêts nècèssèros por changiér los nivéls de protèccion de pâges.\nVê-que la configuracion d’ora de la pâge <strong>$1</strong> :",
+       "protect-cascadeon": "Ora cela pâge est protègiêe, el est transcllua dedens {{PLURAL:$1|cela pâge-que qu’est étâye protègiêe|celes pâges-que que sont étâyes protègiêes}} avouéc lo chouèx « protèccion en cascâda » activâ.\nLos changements du nivél de protèccion de cela pâge afècteront pas la protèccion en cascâda.",
        "protect-default": "Ôtorisar tôs los utilisators",
-       "protect-fallback": "Ôtorisar ren que los utilisators avouéc lo drêt « $1 »",
-       "protect-level-autoconfirmed": "Ôtorisar ren que los utilisators ôtoconfirmâs",
-       "protect-level-sysop": "Ôtorisar ren que los administrators",
+       "protect-fallback": "Ôtorisar mas que los utilisators avouéc lo drêt « $1 »",
+       "protect-level-autoconfirmed": "Ôtorisar mas que los utilisators ôtoconfirmâs",
+       "protect-level-sysop": "Ôtorisar mas que los administrators",
        "protect-summary-cascade": "protèccion en cascâda",
-       "protect-expiring": "èxpire lo $2 a $3 (UTC)",
+       "protect-expiring": "èxpire lo $1 (UTC)",
        "protect-expiring-local": "èxpire lo $1",
        "protect-expiry-indefinite": "sen fin",
-       "protect-cascade": "Protègiér les pâges entrebetâyes dedens ceta (protèccion en cascâda)",
-       "protect-cantedit": "Vos pouede pas changiér los nivéls de protèccion de ceta pâge, vos éd pas la pèrmission de la changiér.",
-       "protect-othertime": "Ôtra dâta d’èxpiracion :",
-       "protect-othertime-op": "ôtra dâta d’èxpiracion",
-       "protect-existing-expiry": "Dâta d’èxpiracion ègzistenta : $2 a $3",
-       "protect-otherreason": "Ôtra rêson / rêson de ples :",
+       "protect-cascade": "Protègiér les pâges rapondues dedens ceta (protèccion en cascâda)",
+       "protect-cantedit": "Vos pouede pas changiér los nivéls de protèccion de cela pâge, vos éd pas la pèrmission de la changiér.",
+       "protect-othertime": "Ôtro temps :",
+       "protect-othertime-op": "ôtro temps",
+       "protect-existing-expiry": "Temps d’èxpiracion ègzistent : $2 a $3",
+       "protect-existing-expiry-infinity": "Temps d’èxpiracion ègzistent : sen fin",
+       "protect-otherreason": "Ôtra rêson ou ben rêson de més :",
        "protect-otherreason-op": "Ôtra rêson",
-       "protect-dropdown": "*Rêsons corentes de protèccion\n** Vandalismo èxcèssif\n** Spame èxcèssif\n** Guèrres de changements contre-productives\n** Pâge a trafic fôrt",
+       "protect-dropdown": "*Rêsons corentes de protèccion\n** Vandalismo afrox\n** Mèssâjos cofos afrox\n** Disputes de changement vouedes\n** Pâge a trafic fôrt",
        "protect-edit-reasonlist": "Changiér les rêsons de protèccion",
        "protect-expiry-options": "1 hora:1 hour,1 jorn:1 day,1 semana:1 week,2 semanes:2 weeks,1 mês:1 month,3 mês:3 months,6 mês:6 months,1 an:1 year,sen fin:infinite",
        "restriction-type": "Pèrmission :",
        "restriction-level-autoconfirmed": "mié-protèccion",
        "restriction-level-all": "tôs los nivéls",
        "undelete": "Vêre les pâges suprimâyes",
-       "undeletepage": "Vêre et refâre des pâges suprimâyes",
-       "undeletepagetitle": "'''Ceta lista contint des vèrsions suprimâyes de [[:$1|$1]].'''",
+       "undeletepage": "Vêre et refâre de pâges suprimâyes",
+       "undeletepagetitle": "<strong>Cela lista-que contint de vèrsions suprimâyes de [[:$1|$1]].</strong>",
        "viewdeletedpage": "Vêre les pâges suprimâyes",
-       "undeletepagetext": "{{PLURAL:$1|Ceta pâge est étâye suprimâye et pués sè trôve|Cetes pâges sont étâyes suprimâyes et pués sè trôvont}} adés dedens les arch·ives, de yô que pô{{PLURAL:$1||von}}t étre refêt{{PLURAL:$1|a|es}}.\nLes arch·ives pôvont étre èfaciêes règuliérement.",
+       "undeletepagetext": "{{PLURAL:$1|Cela pâge-que est étâye suprimâye et pués sè trôve|Celes pâges-que sont étâyes suprimâyes et pués sè trôvont}} adés dedens les arch·ives, de yô que pô{{PLURAL:$1||von}}t étre refêt{{PLURAL:$1|a|es}}.\nLes arch·ives pôvont étre neteyêes règuliérement.",
        "undelete-fieldset-title": "Refâre les vèrsions",
-       "undeleteextrahelp": "Por refâre l’historico complèt de la pâge, lèssiéd totes les câses pas pouentâyes et pués clicâd dessus '''''{{int:undeletebtn}}'''''.\nPor fâre na rèstoracion a mêtiêt, pouentâd les câses que corrèspondont a les vèrsions a refâre et pués clicâd dessus '''''{{int:undeletebtn}}'''''.",
-       "undeleterevisions": "$1 {{PLURAL:$1|vèrsion arch·ivâye|vèrsions arch·ivâyes}}",
+       "undeleteextrahelp": "Por refâre l’historico complèt de la pâge, lèssiéd totes les câses pas pouentâyes et pués cllicâd dessus <strong><em>{{int:undeletebtn}}</em></strong>.\nPor fâre na rèstoracion a mêtiêt, pouentâd les câses que corrèspondont a les vèrsions a refâre et pués cllicâd dessus <strong><em>{{int:undeletebtn}}</em></strong>.",
+       "undeleterevisions": "$1 {{PLURAL:$1|vèrsion suprimâye|vèrsions suprimâyes}}",
        "undeletehistory": "Se vos reféte la pâge, totes les vèrsions seront rebetâyes dedens l’historico.\nS’una pâge novèla avouéc lo mémo nom est étâye fêta dês la suprèssion, les vèrsions refêtes aparêtront dedens l’historico devant.",
-       "undeleterevdel": "La rèstoracion serat pas fêta s’a la fin la vèrsion la ples novèla de la pâge du fichiér réste a mêtiêt suprimâye.\nDens celos câs, vos dête pas pouentar ou ben cachiér la vèrsion suprimâye la ples novèla.",
-       "undeletehistorynoadmin": "Ceta pâge est étâye suprimâye.\nLa rêson de la suprèssion est montrâye dens lo rèsumâ ce-desot, avouéc los dètalys des utilisators que l’ant changiê devant la sina suprèssion.\nLo contegnu èfèctif de celes vèrsions suprimâyes est accèssiblo ren qu’ux administrators.",
+       "undeleterevdel": "La rèstoracion serat pas fêta se finalament la vèrsion la ples novèla de la pâge du fichiér réste a mêtiêt suprimâye.\nDens celos câs, vos dête pas pouentar cachiér la vèrsion suprimâye la ples novèla.",
+       "undeletehistorynoadmin": "Cela pâge est étâye suprimâye.\nLa rêson de la suprèssion est montrâye dens lo rèsumâ ce-desot, avouéc los dètalys des utilisators que l’ant changiê devant sa suprèssion.\nLo contegnu èfèctif de celes vèrsions suprimâyes est accèssiblo ren qu’ux administrators.",
        "undelete-revision": "Vèrsion suprimâye de $1 (du $4 a $5) per $3 :",
-       "undeleterevision-missing": "Vèrsion pas justa ou ben manquenta.\nPôt-étre vos éd un crouyo lim ou ben la vèrsion at possu étre refêta ou enlevâye de les arch·ives.",
+       "undeleterevision-missing": "Vèrsion pas justa ou ben entrovâbla.\nPôt-étre vos éd un crouyo lim ou ben la vèrsion at possu étre refêta enlevâye de les arch·ives.",
        "undelete-nodiff": "Niona vèrsion devant trovâye.",
        "undeletebtn": "Refâre",
        "undeletelink": "vêre / refâre",
        "undeletedrevisions-files": "$1 vèrsion{{PLURAL:$1||s}} et $2 fichiér{{PLURAL:$2||s}} refêts",
        "undeletedfiles": "$1 {{PLURAL:$1|fichiér refêt|fichiérs refêts}}",
        "cannotundelete": "Falyita de la rèstoracion :\n$1",
-       "undeletedpage": "'''$1 est étâye refêta'''\n\nVêde lo [[Special:Log/delete|jornal de les suprèssions]] por avêr na lista de les novèles suprèssions et rèstoracions.",
-       "undelete-header": "Vêde lo [[Special:Log/delete|jornal de les suprèssions]] por avêr les pâges suprimâyes dês pou.",
-       "undelete-search-title": "Rechèrchiér des pâges suprimâs",
-       "undelete-search-box": "Rechèrchiér des pâges suprimâs",
+       "undeletedpage": "<strong>$1 est étâye refêta</strong>\n\nVêde lo [[Special:Log/delete|jornâl de les suprèssions]] por avêr na lista de les novèles suprèssions et rèstoracions.",
+       "undelete-header": "Vêde lo [[Special:Log/delete|jornâl de les suprèssions]] por avêr les pâges suprimâyes dês pou.",
+       "undelete-search-title": "Rechèrchiér de pâges suprimâyes",
+       "undelete-search-box": "Rechèrchiér de pâges suprimâyes",
        "undelete-search-prefix": "Montrar les pâges que començont per :",
        "undelete-search-submit": "Rechèrchiér",
-       "undelete-no-results": "Niona pâge d’ense at étâ trovâ dens les arch·ives de suprèssion.",
-       "undelete-filename-mismatch": "Empossiblo de refâre la vèrsion du fichiér datâ du $1 : lo nom de fichiér corrèspond pas.",
-       "undelete-bad-store-key": "Empossiblo de refâre la vèrsion du fichiér datâ du $1 : lo fichiér ére absent devant la suprèssion.",
-       "undelete-cleanup-error": "Èrror pendent la suprèssion du fichiér de les arch·ives inutilisâ « $1 ».",
-       "undelete-missing-filearchive": "Empossiblo de refâre lo fichiér de les arch·ives avouéc lo numerô $1 perce qu’il est pas dens la bâsa de balyês.\nIl at pôt-étre ja étâ refêt.",
-       "undelete-error": "Èrror pendent la rèstoracion de la pâge",
-       "undelete-error-short": "Èrror pendent la rèstoracion du fichiér : $1",
-       "undelete-error-long": "Des èrrors ont étâ rencontrâs pendent la rèstoracion du fichiér :\n\n$1",
-       "undelete-show-file-confirm": "Éte-vos de sûr de volêr vêre una vèrsion suprimâ du fichiér « <nowiki>$1</nowiki> » que dâte du $2 a $3 ?",
+       "undelete-no-results": "Niona pâge d’ense est étâye trovâye dedens les arch·ives de suprèssion.",
+       "undelete-filename-mismatch": "Y at pas moyen de refâre la vèrsion du fichiér datâye du $1 : lo nom de fichiér corrèspond pas.",
+       "undelete-bad-store-key": "Y at pas moyen de refâre la vèrsion du fichiér datâye du $1 : lo fichiér ére entrovâblo devant la suprèssion.",
+       "undelete-cleanup-error": "Fôta pendent la suprèssion du fichiér de les arch·ives pas empleyê « $1 ».",
+       "undelete-missing-filearchive": "Y at pas moyen de refâre lo fichiér de les arch·ives avouéc l’ID $1, il est pas dedens la bâsa de balyês.\nPôt-étre il est ja étâ refêt.",
+       "undelete-error": "Fôta pendent la rèstoracion de la pâge",
+       "undelete-error-short": "Fôta pendent la rèstoracion du fichiér : $1",
+       "undelete-error-long": "Des fôtes sont arrevâyes pendent la rèstoracion du fichiér :\n\n$1",
+       "undelete-show-file-confirm": "Vos éte de sûr de volêr vêre na vèrsion suprimâye du fichiér « <nowiki>$1</nowiki> » que dâte du $2 a $3 ?",
        "undelete-show-file-submit": "Ouè",
        "namespace": "Èspâço de noms :",
        "invert": "Envèrsar lo chouèx",
-       "tooltip-invert": "Pouentâd ceta câsa por cachiér los changements de les pâges dens l’èspâço de noms chouèsi (et l’èspâço de noms associyê avouéc se pouentâ)",
+       "tooltip-invert": "Pouentâd cela câsa por cachiér los changements de les pâges dedens l’èspâço de noms chouèsi (et l’èspâço de noms associyê avouéc se pouentâ)",
+       "tooltip-whatlinkshere-invert": "Pouentâd cela câsa por cachiér los lims de les pâges dedens l’èspâço de noms chouèsi.",
        "namespace_association": "Èspâço de noms associyê",
-       "tooltip-namespace_association": "Pouentâd ceta câsa por encllure avouéc l’èspâço de noms de discussion associyê a l’èspâço de noms chouèsi",
+       "tooltip-namespace_association": "Pouentâd cela câsa por rapondre avouéc l’èspâço de noms de discussion de chousa associyê a l’èspâço de noms chouèsi",
        "blanknamespace": "(Principâl)",
        "contributions": "Contribucions de l’utilisat{{GENDER:$1|or|rice}}",
-       "contributions-title": "Lista de les contribucions a l’usanciér $1",
+       "contributions-title": "Contribucions de l’utilisat{{GENDER:$1|or|rice}} $1",
        "mycontris": "Contribucions",
+       "anoncontribs": "Contribucions",
        "contribsub2": "Por {{GENDER:$3|$1}} ($2)",
-       "nocontribs": "Y at gins de changement que corrèspond a cetos critèros.",
+       "contributions-userdoesnotexist": "Lo comptio utilisator « $1 » est pas encartâ.",
+       "nocontribs": "Y at gins de changement que corrèspond a celos critèros.",
        "uctop": "(d’ora)",
        "month": "Dês lo mês (et devant) :",
        "year": "Dês l’an (et devant) :",
        "sp-contributions-newbies": "Montrar ren que les contribucions des novéls utilisators",
-       "sp-contributions-newbies-sub": "Permié los comptos novéls",
-       "sp-contributions-newbies-title": "Contribucions d’usanciérs permié los comptos novéls",
-       "sp-contributions-blocklog": "jornal des blocâjos",
-       "sp-contributions-deleted": "contribucions suprimâs",
+       "sp-contributions-newbies-sub": "Entre-mié los comptios novéls",
+       "sp-contributions-newbies-title": "Contribucions d’utilisators entre-mié los comptios novéls",
+       "sp-contributions-blocklog": "jornâl des blocâjos",
+       "sp-contributions-suppresslog": "contribucions d’utilisators rèprimâyes",
+       "sp-contributions-deleted": "contribucions d’utilisators suprimâyes",
        "sp-contributions-uploads": "tèlèchargements",
-       "sp-contributions-logs": "jornals",
+       "sp-contributions-logs": "jornâls",
        "sp-contributions-talk": "discutar",
-       "sp-contributions-userrights": "administrar los drêts d’usanciér",
-       "sp-contributions-blocked-notice": "Ceti usanciér est ora blocâ.\nLa dèrriére entrâ du jornal des blocâjos est disponibla ce-desot :",
-       "sp-contributions-blocked-notice-anon": "Ceta adrèce IP est ora blocâ.\nLa dèrriére entrâ du jornal des blocâjos est disponibla ce-desot :",
+       "sp-contributions-userrights": "maneyér los drêts d’utilisator",
+       "sp-contributions-blocked-notice": "Ora cél utilisator est blocâ.\nLa dèrriére entrâ du jornâl des blocâjos est balyêe ce-desot coment rèference :",
+       "sp-contributions-blocked-notice-anon": "Ora cel’adrèce IP est blocâye.\nLa dèrriére entrâ du jornâl des blocâjos est balyêe ce-desot coment rèference :",
        "sp-contributions-search": "Rechèrchiér les contribucions",
-       "sp-contributions-username": "Adrèce IP ou ben nom d’usanciér :",
-       "sp-contributions-toponly": "Montrar ren que les novèles vèrsions",
+       "sp-contributions-username": "Adrèce IP ou ben nom d’utilisator :",
+       "sp-contributions-toponly": "Montrar ren que los changements que sont les dèrriéres vèrsions",
+       "sp-contributions-newonly": "Montrar ren que los changements que sont de crèacions de pâge",
        "sp-contributions-submit": "Rechèrchiér",
        "whatlinkshere": "Pâges liyêes",
        "whatlinkshere-title": "Pâges que pouentont vers « $1 »",
        "whatlinkshere-page": "Pâge :",
-       "linkshere": "Les pâges ce-desot contegnont un lim de vers '''[[:$1]]''' :",
-       "nolinkshere": "Niona pâge contint de lim de vers '''[[:$1]]'''.",
-       "nolinkshere-ns": "Niona pâge contint de lim de vers '''[[:$1]]''' dens l’èspâço de noms chouèsi.",
+       "linkshere": "Celes pâges-que contegnont un lim de vers <strong>[[:$1]]</strong> :",
+       "nolinkshere": "Niona pâge contint de lim de vers <strong>[[:$1]]</strong>.",
+       "nolinkshere-ns": "Niona pâge contint de lim de vers <strong>[[:$1]]</strong> dedens l’èspâço de noms chouèsi.",
        "isredirect": "pâge de redirèccion",
-       "istemplate": "encllusion",
+       "istemplate": "transcllusion",
        "isimage": "lim de vers lo fichiér",
        "whatlinkshere-prev": "{{PLURAL:$1|devant|$1 devant}}",
        "whatlinkshere-next": "{{PLURAL:$1|aprés|$1 aprés}}",
        "whatlinkshere-links": "← lims",
        "whatlinkshere-hideredirs": "$1 les redirèccions",
-       "whatlinkshere-hidetrans": "$1 les encllusions",
+       "whatlinkshere-hidetrans": "$1 les transcllusions",
        "whatlinkshere-hidelinks": "$1 los lims",
-       "whatlinkshere-hideimages": "$1 los fichiérs liyês",
+       "whatlinkshere-hideimages": "$1 los lims de vers lo fichiér",
        "whatlinkshere-filters": "Filtros",
-       "autoblockid": "Blocâjo ôtomatico #$1",
-       "block": "Blocar l’usanciér",
-       "unblock": "Dèblocar l’usanciér",
-       "blockip": "Blocar l’usanciér",
-       "blockip-legend": "Blocar l’usanciér",
-       "blockiptext": "Utilisâd lo formulèro ce-desot por blocar l’accès en ècritura dês una adrèce IP spècefica ou ben un nom d’usanciér.\nUna tâla mesera devrêt étre prêsa ren que por empachiér lo vandalismo et en acôrd avouéc les [[{{MediaWiki:Policy-url}}|règlles de dedens]].\nBalyéd ce-desot una rêson justa (per ègzemplo en citent les pâges qu’ont étâ vandalisâs).",
-       "ipaddressorusername": "Adrèce IP ou ben nom d’usanciér :",
+       "whatlinkshere-submit": "Emmodar",
+       "autoblockid": "Blocâjo ôtomatico n° $1",
+       "block": "Blocar l’utilisator",
+       "unblock": "Dèblocar l’utilisator",
+       "blockip": "Blocar l’utilisat{{GENDER:$1|or|rice}}",
+       "blockip-legend": "Blocar l’utilisator",
+       "blockiptext": "Empleyéd lo formulèro ce-desot por blocar l’accès en ècritura dês un’adrèce IP spècifica un nom d’utilisator spècifico.\nNa mesera d’ense devrêt étre prêsa ren que por empachiér lo vandalismo et pués en acôrd avouéc les [[{{MediaWiki:Policy-url}}|politiques]].\nBalyéd ce-desot na rêson prècisa (per ègzemplo en citent les pâges que sont étâyes vandalisâyes).\nVos pouede blocar de plages IP en empleyent la sintaxa [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR] ; la ples granta plage ôtorisâye est /$1 por IPv4 et /$2 por IPv6.",
+       "ipaddressorusername": "Adrèce IP ou ben nom d’utilisator :",
        "ipbexpiry": "Temps devant èxpiracion :",
        "ipbreason": "Rêson :",
-       "ipbreason-dropdown": "*Rêsons corentes de blocâjo\n** Entrebetâ d’enformacions fôsses\n** Suprèssion de contegnu de les pâges\n** Entrebetâ de lims de defôr publicitèros (spame)\n** Entrebetâ de contegnu sen gins de significacion et d’ècovelyes dedens les pâges\n** Tentativa d’entimidacion ou ben de torment\n** Abus d’usâjo d’un mouél de comptos\n** Nom d’utilisator pas accèptâblo",
-       "ipb-hardblock": "Empache los changements des usanciérs encartâs qu’utilisont cela adrèce IP",
-       "ipbcreateaccount": "Empachiér la crèacion de compto",
-       "ipbemailban": "Empachiér l’usanciér de mandar des mèssâjos",
-       "ipbenableautoblock": "Blocar ôtomaticament la dèrriére adrèce IP utilisâ per l’usanciér et pués totes ses adrèces IP a vegnir que porrêt èprovar",
-       "ipbsubmit": "Blocar ceti usanciér",
+       "ipbreason-dropdown": "*Rêsons corentes de blocâjo\n** Entrebetâ d’enformacions fôsses\n** Suprèssion de contegnu de les pâges\n** Raponsa de lims de defôr cofos (recllâma)\n** Entrebetâ de contegnu sen gins de significacion et d’ècovelyes dedens les pâges\n** Èprôva d’entimidacion de pèrsècucion\n** Abus d’usâjo d’un mouél de comptios\n** Nom d’utilisator pas accèptâblo",
+       "ipb-hardblock": "Empachiér los utilisators branchiês de changiér en empleyent cel’adrèce IP",
+       "ipbcreateaccount": "Empachiér la crèacion de comptio",
+       "ipbemailban": "Empachiér l’utilisator de mandar de mèssâjos",
+       "ipbenableautoblock": "Blocar ôtomaticament la dèrriére adrèce IP empleyêe per l’utilisator et pués totes ses adrèces IP a vegnir que porrêt èprovar",
+       "ipbsubmit": "Blocar cél utilisator",
        "ipbother": "Ôtro temps :",
        "ipboptions": "2 hores:2 hours,1 jorn:1 day,3 jorns:3 days,1 semana:1 week,2 semanes:2 weeks,1 mês:1 month,3 mês:3 months,6 mês:6 months,1 an:1 year,sen fin:infinite",
-       "ipbhidename": "Cachiér lo nom d’usanciér des changements et de les listes",
-       "ipbwatchuser": "Siuvre les pâges usanciér et de discussion a ceti usanciér",
-       "ipb-disableusertalk": "Empache cél usanciér de changiér sa prôpra pâge de discussion pendent lo temps de son blocâjo",
-       "ipb-change-block": "Tornar blocar ceti usanciér avouéc celos paramètres",
+       "ipbhidename": "Cachiér lo nom d’utilisator des changements et de les listes",
+       "ipbwatchuser": "Siuvre les pâges utilisator et de discussion a cél utilisator",
+       "ipb-disableusertalk": "Empachiér cél utilisator de changiér la sina pâge de discussion pendent lo blocâjo",
+       "ipb-change-block": "Tornar blocar l’utilisator avouéc cela configuracion",
        "ipb-confirm": "Confirmar lo blocâjo",
-       "badipaddress": "L’adrèce IP est fôssa.",
+       "badipaddress": "L’adrèce IP est pas justa.",
        "blockipsuccesssub": "Blocâjo reussi",
-       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] at étâ blocâ.<br />\nVêde la [[Special:BlockList|lista des blocâjos]] por revêre los blocâjos.",
-       "ipb-blockingself": "Vos éte prèst a vos blocar vos-mémo !  Éte-vos de sûr de lo volêr fâre ?",
-       "ipb-confirmhideuser": "Vos éte prèst a blocar un usanciér avouéc « cachiér l’usanciér » activâ.  Cen suprime lo nom a l’usanciér dens totes les listes et les entrâs du jornal.  Éte-vos de sûr de lo volêr fâre ?",
+       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] est {{GENDER:$1|étâ blocâ|étâye blocâye}}.<br />\nVêde la [[Special:BlockList|lista des blocâjos]] por revêre los blocâjos.",
+       "ipb-blockingself": "Vos éte prèst a vos blocar vos-mémo ! Vos éte de sûr d’o volêr fâre ?",
+       "ipb-confirmhideuser": "Vos éte prèst a blocar un utilisator avouéc « cachiér l’utilisator » activâ. Cen rèprime lo nom a l’utilisator dedens totes les listes et les entrês du jornâl. Vos éte de sûr d’o volêr fâre ?",
+       "ipb-confirmaction": "Se vos éte de sûr d’o volêr franc fâre, se vos plét pouentâd lo champ « {{int:ipb-confirm}} » d’avâl.",
        "ipb-edit-dropdown": "Changiér les rêsons de blocâjo",
        "ipb-unblock-addr": "Dèblocar $1",
-       "ipb-unblock": "Dèblocar un usanciér ou ben una adrèce IP",
-       "ipb-blocklist": "Vêde los blocâjos ègzistents",
-       "ipb-blocklist-contribs": "Contribucions por $1",
-       "unblockip": "Dèblocar l’usanciér",
-       "unblockiptext": "Utilisâd lo formulèro ce-desot por rètablir l’accès en ècritura dês una adrèce IP spècefica ou ben un nom d’usanciér.",
-       "ipusubmit": "Enlevar ceti blocâjo",
-       "unblocked": "[[User:$1|$1]] at étâ dèblocâ",
-       "unblocked-range": "$1 at étâ dèblocâ",
-       "unblocked-id": "Lo blocâjo $1 at étâ enlevâ",
-       "blocklist": "Usanciérs blocâs",
-       "ipblocklist": "Usanciérs blocâs",
-       "ipblocklist-legend": "Chèrchiér un usanciér blocâ",
-       "blocklist-userblocks": "Cachiér los blocâjos de comptos",
+       "ipb-unblock": "Dèblocar un nom d’utilisator un’adrèce IP",
+       "ipb-blocklist": "Vêre los blocâjos ègzistents",
+       "ipb-blocklist-contribs": "Contribucions por {{GENDER:$1|$1}}",
+       "unblockip": "Dèblocar un utilisator",
+       "unblockiptext": "Empleyéd lo formulèro ce-desot por rètablir l’accès en ècritura dês un’adrèce IP blocâye un nom d’utilisator blocâ los côps devant.",
+       "ipusubmit": "Enlevar cél blocâjo",
+       "unblocked": "[[User:$1|$1]] est {{GENDER:$1|étâ dèblocâ|étâye dèblocâye}}.",
+       "unblocked-range": "$1 est étâ dèblocâ.",
+       "unblocked-id": "Lo blocâjo $1 est étâ enlevâ.",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] est étâ dèblocâ.",
+       "blocklist": "Utilisators blocâs",
+       "ipblocklist": "Utilisators blocâs",
+       "ipblocklist-legend": "Trovar un utilisator blocâ",
+       "blocklist-userblocks": "Cachiér los blocâjos de comptios",
        "blocklist-tempblocks": "Cachiér los blocâjos temporèros",
-       "blocklist-addressblocks": "Cachiér los blocâjos d’adrèces IP solètes",
-       "blocklist-rangeblocks": "Cachiér los blocos de portâ",
+       "blocklist-addressblocks": "Cachiér los blocâjos de mas qu’un’adrèce IP",
+       "blocklist-rangeblocks": "Cachiér los blocâjos de plages IP",
        "blocklist-timestamp": "Dâta et hora",
        "blocklist-target": "Ciba",
-       "blocklist-expiry": "Dâta d’èxpiracion",
+       "blocklist-expiry": "Èxpiracion",
        "blocklist-by": "Administrator qu’at fêt lo blocâjo",
-       "blocklist-params": "Paramètres de blocâjo",
+       "blocklist-params": "Paramètros de blocâjo",
        "blocklist-reason": "Rêson",
        "ipblocklist-submit": "Rechèrchiér",
        "ipblocklist-localblock": "Blocâjo locâl",
        "ipblocklist-otherblocks": "{{PLURAL:$1|Ôtro blocâjo|Ôtros blocâjos}}",
        "infiniteblock": "sen fin",
        "expiringblock": "èxpire lo $1 a $2",
-       "anononlyblock": "solament los usanciérs pas encartâs",
+       "anononlyblock": "mas que los utilisators anonimos",
        "noautoblockblock": "blocâjo ôtomatico dèsactivâ",
-       "createaccountblock": "crèacion de compto dèfendua",
-       "emailblock": "mèssageria èlèctronica blocâ",
-       "blocklist-nousertalk": "pôt pas changiér sa prôpra pâge de discussion",
-       "ipblocklist-empty": "Ora, la lista a les adrèces IP blocâs est voueda.",
-       "ipblocklist-no-results": "L’adrèce IP ou ben l’usanciér demandâ est pas blocâ.",
+       "createaccountblock": "crèacion de comptio dèsactivâye",
+       "emailblock": "mèssageria èlèctronica dèsactivâye",
+       "blocklist-nousertalk": "pôt pas changiér la sina pâge de discussion",
+       "ipblocklist-empty": "La lista des blocâjos est voueda.",
+       "ipblocklist-no-results": "L’adrèce IP demandâye lo nom d’utilisator demandâ est pas blocâ(ye).",
        "blocklink": "blocar",
        "unblocklink": "dèblocar",
        "change-blocklink": "changiér lo blocâjo",
        "contribslink": "contribucions",
        "emaillink": "mandar un mèssâjo",
-       "autoblocker": "Vos avéd étâ blocâ ôtomaticament perce que voutra adrèce IP at étâ utilisâ dèrriérement per « [[User:$1|$1]] ».\nLa rêson balyê por lo blocâjo a $1 est : « $2 ».",
-       "blocklogpage": "Jornal des blocâjos",
-       "blocklog-showlog": "Ceti usanciér at étâ blocâ dês devant.\nLo jornal des blocâjos est disponiblo ce-desot :",
-       "blocklog-showsuppresslog": "Ceti usanciér at étâ blocâ et pués cachiê dês devant.\nLo jornal de les suprèssions est disponiblo ce-desot :",
-       "blocklogentry": "at blocâ [[$1]] ; èxpiracion : $2 $3",
-       "reblock-logentry": "at changiê los paramètres du blocâjo a [[$1]] avouéc una èxpiracion u $2 $3",
-       "blocklogtext": "O est lo jornal de les accions de blocâjo et dèblocâjo d’utilisators.\nLes adrèces IP blocâyes ôtomaticament sont pas listâyes.\nVêde la [[Special:BlockList|lista des blocâjos]] por la lista des banissements et des blocâjos que sont ora actifs.",
+       "autoblocker": "Vos éte étâ blocâ ôtomaticament, voutron adrèce IP est étâye empleyêe dês pou per « [[User:$1|$1]] ».\nLa rêson balyêe por lo blocâjo de $1 est « $2 ».",
+       "blocklogpage": "Jornâl des blocâjos",
+       "blocklog-showlog": "Cél utilisator est étâ blocâ los côps devant.\nLo jornâl des blocâjos est balyê ce-desot coment rèference :",
+       "blocklog-showsuppresslog": "Cél utilisator est étâ blocâ et pués cachiê los côps devant.\nLo jornâl de les rèprèssions est balyê ce-desot coment rèference :",
+       "blocklogentry": "at blocâ [[$1]] avouéc un temps d’èxpiracion de $2 $3",
+       "reblock-logentry": "at changiê la configuracion du blocâjo de [[$1]] avouéc un temps d’èxpiracion de $2 $3",
+       "blocklogtext": "O est lo jornâl de les accions de blocâjo et dèblocâjo d’utilisators.\nLes adrèces IP blocâyes ôtomaticament sont pas listâyes.\nVêde la [[Special:BlockList|lista des blocâjos]] por la lista des banissements et des blocâjos que sont ora actifs.",
        "unblocklogentry": "at dèblocâ $1",
-       "block-log-flags-anononly": "solament los usanciérs pas encartâs",
-       "block-log-flags-nocreate": "crèacion de compto dèfendua",
-       "block-log-flags-noautoblock": "ôtoblocâjo a les adrèces IP dèsactivâ",
-       "block-log-flags-noemail": "èxpèdicion de mèssâjo dèfendua",
-       "block-log-flags-nousertalk": "pôt pas changiér sa prôpra pâge de discussion",
-       "block-log-flags-angry-autoblock": "ôtoblocâjo mèlyorâ activâ",
-       "block-log-flags-hiddenname": "nom d’usanciér cachiê",
-       "range_block_disabled": "Lo povêr d’administrator de fâre des blocâjos de plages d’adrèces IP est dèsactivâ.",
-       "ipb_expiry_invalid": "Temps d’èxpiracion fôx.",
-       "ipb_expiry_temp": "Los blocâjos de noms d’usanciér cachiês dêvont étre sen fin.",
-       "ipb_hide_invalid": "Empossiblo de suprimar ceti compto ; semble avêr trop de changements.",
+       "block-log-flags-anononly": "mas que los utilisators anonimos",
+       "block-log-flags-nocreate": "crèacion de comptio dèsactivâye",
+       "block-log-flags-noautoblock": "blocâjo ôtomatico dèsactivâ",
+       "block-log-flags-noemail": "mèssageria èlèctronica dèsactivâye",
+       "block-log-flags-nousertalk": "pôt pas changiér la sina pâge de discussion",
+       "block-log-flags-angry-autoblock": "blocâjo ôtomatico bônâ activâ",
+       "block-log-flags-hiddenname": "nom d’utilisator cachiê",
+       "range_block_disabled": "Lo moyen d’administrator de fâre de blocâjos de plages IP est dèsactivâ.",
+       "ipb_expiry_invalid": "Temps d’èxpiracion pas justo.",
+       "ipb_expiry_old": "Lo temps d’èxpiracion est ja passâ.",
+       "ipb_expiry_temp": "Los blocâjos de noms d’utilisator cachiês dêvont étre sen fin.",
+       "ipb_hide_invalid": "Y at pas moyen de rèprimar cél comptio ; semble avêr més {{PLURAL:$1|d’un changement|de $1 changements}}.",
        "ipb_already_blocked": "« $1 » est ja blocâ",
-       "ipb-needreblock": "$1 est ja blocâ.\nVoléd-vos changiér los paramètres ?",
+       "ipb-needreblock": "$1 est ja blocâ.\nVos voléd changiér la configuracion ?",
        "ipb-otherblocks-header": "{{PLURAL:$1|Ôtro blocâjo|Ôtros blocâjos}}",
-       "unblock-hideuser": "Vos pouede pas dèblocar cél usanciér, perce que son nom d’usanciér at étâ cachiê.",
-       "ipb_cant_unblock": "Èrror : numerô de blocâjo $1 pas trovâ.\nO est possiblo qu’un dèblocâjo èye ja étâ fêt.",
-       "ipb_blocked_as_range": "Èrror : l’adrèce IP $1 est pas blocâ tot drêt et pôt vêr pas étre dèblocâ.\nPortant, el est avouéc la plage $2 que pôt étre dèblocâ.",
-       "ip_range_invalid": "Plage d’adrèces IP fôssa.",
-       "ip_range_toolarge": "Los blocâjos de plages d’adrèces IP ples grantes que /$1 sont pas ôtorisâs.",
-       "proxyblocker": "Bloquior de sèrvors mandatèros (''proxies'')",
-       "proxyblockreason": "Voutra adrèce IP at étâ blocâ perce qu’o est un sèrvor mandatèro (''proxy'') uvèrt.\nVos volyéd veriér vers voutron fornissor d’accès u Malyâjo ou ben voutra assistance tècnica et l’enformar de cél problèmo de sècuritât sèriox.",
-       "sorbsreason": "Voutra adrèce IP est listâ coment sèrvor mandatèro (''proxy'') uvèrt dens lo DNSBL utilisâ per {{SITENAME}}.",
-       "sorbs_create_account_reason": "Voutra adrèce IP est listâ coment sèrvor mandatèro (''proxy'') uvèrt dens lo DNSBL utilisâ per {{SITENAME}}.\nVos pouede pas fâre un compto.",
-       "cant-see-hidden-user": "L’usanciér que vos tâchiéd de blocar at ja étâ blocâ et cachiê.\nPas èyent lo drêt hideuser, vos pouede pas vêre ou ben changiér lo blocâjo a l’usanciér.",
-       "ipbblocked": "Vos pouede pas blocar ou ben dèblocar d’ôtros usanciérs, perce que vos éte vos-mémo blocâ",
-       "ipbnounblockself": "Vos éte pas ôtorisâ a vos dèblocar vos-mémo",
-       "lockdb": "Vèrrolyér la bâsa de balyês",
-       "unlockdb": "Dèvèrrolyér la bâsa de balyês",
-       "lockdbtext": "Lo vèrrolyâjo de la bâsa de balyês empachierat tôs los usanciérs de changiér des pâges, d’encartar lors prèferences, de changiér lor lista de survelyence et pués de fâre totes les ôtres opèracions qu’ont fôta des changements dens la bâsa de balyês.\nVolyéd confirmar qu’o est franc cen que vos voléd fâre et que vos dèvèrrolyeréd la bâsa setout que voutra opèracion de mantegnence serat chavonâ.",
-       "unlockdbtext": "Lo dèvèrrolyâjo de la bâsa de balyês tornerat pèrmetre a tôs los usanciérs de changiér des pâges, d’encartar lors prèferences, de changiér lor lista de survelyence et pués de fâre totes les ôtres opèracions qu’ont fôta des changements dens la bâsa de balyês.\nVolyéd confirmar qu’o est franc cen que vos voléd fâre.",
-       "lockconfirm": "Ouè, confirmo que souhèto vèrrolyér la bâsa de balyês.",
-       "unlockconfirm": "Ouè, confirmo que souhèto dèvèrrolyér la bâsa de balyês.",
-       "lockbtn": "Vèrrolyér la bâsa de balyês",
-       "unlockbtn": "Dèvèrrolyér la bâsa de balyês",
+       "unblock-hideuser": "Vos pouede pas dèblocar cél utilisator, son nom d’utilisator est étâ cachiê.",
+       "ipb_cant_unblock": "Fôta : identifient de blocâjo $1 pas trovâ. O est possiblo qu’un dèblocâjo èye ja étâ fêt.",
+       "ipb_blocked_as_range": "Fôta : l’adrèce IP $1 est pas blocâye tot drêt et pués pôt vêr pas étre dèblocâye.\nPortant el est avouéc la plage IP $2 que pôt étre dèblocâye.",
+       "ip_range_invalid": "Plage IP pas justa.",
+       "ip_range_toolarge": "Los blocâjos de plages IP ples grantes que /$1 sont pas ôtorisâs.",
+       "proxyblocker": "Bloquior de sèrviors mandatèros (<em>proxies</em>)",
+       "proxyblockreason": "Voutron adrèce IP est étâye blocâye, o est un sèrvior mandatèro (<em>proxy</em>) uvèrt.\nSe vos plét, veriéd-vos vers voutron fornissor d’accès u Malyâjo voutron supôrt tècnico et pués enformâd-los de cél problèmo de sècuritât sèriox.",
+       "sorbsreason": "Voutron adrèce IP est listâye coment sèrvior mandatèro (<em>proxy</em>) uvèrt dedens lo DNSBL empleyê per {{SITENAME}}.",
+       "sorbs_create_account_reason": "Voutron adrèce IP est listâye coment sèrvior mandatèro (<em>proxy</em>) uvèrt dedens lo DNSBL empleyê per {{SITENAME}}.\nVos pouede pas fâre un comptio.",
+       "xffblockreason": "Un’adrèce IP dedens l’en-téta X-Forwarded-For, ou ben la voutra ou ben cela d’un sèrvior mandatèro (<em>proxy</em>) que vos empleyéd, est étâye blocâye. La rêson originâla du blocâjo ére : $1",
+       "cant-see-hidden-user": "L’utilisator que vos èprovâd de blocar est ja étâ blocâ et cachiê.\nSen lo drêt « hideuser », vos pouede pas vêre changiér lo blocâjo de l’utilisator.",
+       "ipbblocked": "Vos pouede pas blocar dèblocar d’ôtros utilisators, vos éte vos-mém{{GENDER:|o|a}} blocâ{{GENDER:||ye}}.",
+       "ipbnounblockself": "Vos éte pas ôtorisâ{{GENDER:||ye}} a vos dèblocar vos-mém{{GENDER:|o|a}}.",
+       "lockdb": "Cotar la bâsa de balyês",
+       "unlockdb": "Dècotar la bâsa de balyês",
+       "lockdbtext": "Lo vèrroly de la bâsa de balyês empachierat tôs los utilisators de changiér de pâges, d’encartar lors prèferences, de changiér lor lista de gouârda et pués de fâre totes les ôtres opèracions qu’ant fôta de changements dedens la bâsa de balyês.\nSe vos plét, confirmâd qu’o est franc cen que vos voléd fâre et que vos la dècoteréd setout que voutra rotina d’entretin serat chavona.",
+       "unlockdbtext": "La fin du vèrroly de la bâsa de balyês tornerat pèrmetre a tôs los utilisators de changiér de pâges, d’encartar lors prèferences, de changiér lor lista de gouârda et pués de fâre totes les ôtres opèracions qu’ant fôta de changements dedens la bâsa de balyês.\nSe vos plét, confirmâd qu’o est franc cen que vos voléd fâre.",
+       "lockconfirm": "Ouè, confirmo que vuel cotar la bâsa de balyês.",
+       "unlockconfirm": "Ouè, confirmo que vuel dècotar la bâsa de balyês.",
+       "lockbtn": "Cotar la bâsa de balyês",
+       "unlockbtn": "Dècotar la bâsa de balyês",
        "locknoconfirm": "Vos éd pas pouentâ la câsa de confirmacion.",
-       "lockdbsuccesssub": "Vèrrolyâjo de la bâsa de balyês reussi",
-       "unlockdbsuccesssub": "Vèrrolyâjo de la bâsa de balyês enlevâ",
-       "lockdbsuccesstext": "La bâsa de donâs est étâye vèrrolyêye.<br />\nOubliâd pas de [[Special:UnlockDB|la dèvèrrolyér]] quand vos aréd chavonâ voutra opèracion de mantegnence.",
-       "unlockdbsuccesstext": "La bâsa de balyês at étâ dèvèrrolyê.",
-       "lockfilenotwritable": "Lo fichiér de vèrrolyâjo de la bâsa de balyês est pas enscriptiblo.\nPor vèrrolyér ou ben dèvèrrolyér la bâsa de balyês, dêt étre accèssiblo en ècritura dês lo sèrvor vouèbe.",
-       "databasenotlocked": "La bâsa de balyês est pas vèrrolyê.",
-       "lockedbyandtime": "(per $1 lo $2 a $3)",
-       "move-page": "Renomar $1",
-       "move-page-legend": "Renomar una pâge",
-       "movepagetext": "Utilisâd lo formulèro ce-desot por renomar una pâge, en dèplacient tot son historico vers lo novél nom.\nLo viely titro vindrat una pâge de redirèccion de vers lo titro novél.\nVos pouede betar a jorn ôtomaticament les redirèccions d’ora que pouentont vers lo titro originâl.\nSe vos chouèsésséd de pas lo fâre, assurâd-vos de controlar tota [[Special:DoubleRedirects|redirèccion dobla]] ou ben [[Special:BrokenRedirects|câssa]].\nVos avéd la rèsponsabilitât de vos assurar que los lims continuont de pouentar vers lor dèstinacion suposâ.\n\nNotâd que la pâge serat '''pas''' dèplaciê s’y at ja una pâge avouéc lo titro novél, a muens que cela dèrriére seye voueda ou ben seye ren qu’una redirèccion et que son historico des changements seye vouedo.\nCen vôt dére que vos pouede renomar una pâge vers sa posicion d’origina se vos éd fêt una èrror, mas que vos pouede pas ècllafar una pâge ja ègzistenta.\n\n'''ATENCION !'''\nCen pôt provocar un changement fôrt et emprèvu por una pâge sovent vua ;\nassurâd-vos de nen avêr comprês les consèquences devant que continuar.",
-       "movepagetext-noredirectfixer": "Utilisâd lo formulèro ce-desot por renomar una pâge, en dèplacient tot son historico vers lo novél nom.\nLo viely titro vindrat una pâge de redirèccion de vers lo titro novél.\nControlâd bien les [[Special:DoubleRedirects|redirèccions dobles]] ou ben [[Special:BrokenRedirects|câsses]].\nVos avéd la rèsponsabilitât de vos assurar que los lims continuont de pouentar vers lor dèstinacion suposâ.\n\nNotâd que la pâge serat '''pas''' dèplaciê s’y at ja una pâge avouéc lo titro novél, a muens que cela dèrriére seye voueda ou ben seye ren qu’una redirèccion et que son historico des changements seye vouedo.\nCen vôt dére que vos pouede renomar una pâge vers sa posicion d’origina se vos éd fêt una èrror, mas que vos pouede pas ècllafar una pâge ja ègzistenta.\n\n'''ATENCION !'''\nCen pôt provocar un changement fôrt et emprèvu por una pâge sovent vua ;\nassurâd-vos de nen avêr comprês les consèquences devant que continuar.",
-       "movepagetalktext": "La pâge de discussion associyê, se presente, serat renomâ ôtomaticament avouéc '''a muens que :'''\n* una pâge de discussion pas voueda ègziste ja avouéc lo novél nom, ou ben\n* vos pouentâd pas la câsa ce-desot.\n\nDens celos câs, vos devréd renomar ou ben fusionar la pâge a la man se vos lo voléd.",
-       "moveuserpage-warning": "'''Atencion :''' vos éte prèst a renomar una pâge usanciér. Volyéd notar que solament la pâge serat renomâ et que l’usanciér serat '''pas''' renomâ.",
-       "movenologintext": "Por povêr renomar una pâge, vos dête étre [[Special:UserLogin|branchiê]] coment usanciér encartâ.",
-       "movenotallowed": "Vos avéd pas la pèrmission de renomar les pâges.",
-       "movenotallowedfile": "Vos avéd pas la pèrmission de renomar los fichiérs.",
-       "cant-move-user-page": "Vos avéd pas la pèrmission de renomar les pâges principâles d’usanciérs (en defôr de lors sot-pâges).",
-       "cant-move-to-user-page": "Vos avéd pas la pèrmission de renomar una pâge vers una pâge usanciér (a l’èxcèpcion d’una sot-pâge).",
-       "newtitle": "De vers lo titro novél :",
+       "lockdbsuccesssub": "Vèrroly de la bâsa de balyês reussi",
+       "unlockdbsuccesssub": "Vèrroly de la bâsa de balyês enlevâ",
+       "lockdbsuccesstext": "La bâsa de balyês est étâye cotâye.<br />\nOubliâd pas de la [[Special:UnlockDB|dècotar]] quand vos aréd chavono voutra rotina d’entretin.",
+       "unlockdbsuccesstext": "La bâsa de balyês est étâye dècotâye.",
+       "lockfilenotwritable": "Lo fichiér de vèrroly de la bâsa de balyês est pas enscriptiblo.\nPor cotar dècotar la bâsa de balyês, dêt étre enscriptiblo per lo sèrvior Vouèbe.",
+       "databasenotlocked": "La bâsa de balyês est pas cotâye.",
+       "lockedbyandtime": "(per {{GENDER:$1|$1}} lo $2 a $3)",
+       "move-page": "Dèplaciér $1",
+       "move-page-legend": "Dèplaciér na pâge",
+       "movepagetext": "Empleyéd lo formulèro ce-desot por renomar na pâge, en dèplacient tot son historico vers lo novél nom.\nLo viely titro vindrat na pâge de redirèccion de vers lo titro novél.\nVos pouede betar a jorn ôtomaticament les redirèccions d’ora que pouentont vers lo titro originâl.\nSe vos chouèsésséd de pas o fâre, assurâd-vos de controlar tota [[Special:DoubleRedirects|redirèccion dobla]] [[Special:BrokenRedirects|câssa]].\nVos éd la rèsponsabilitât de vos assurar que los lims continuont de pouentar vers lor dèstinacion suposâye.\n\nNotâd que la pâge serat <strong>pas</strong> dèplaciêe s’y at ja na pâge avouéc lo titro novél, a muens que cela dèrriére seye na simpla redirèccion avouéc un historico de changements vouedo.\nCen vôt dére que vos pouede renomar na pâge vers sa posicion d’origina se vos éd fêt na fôta, mas que vos pouede pas ècllafar na pâge ja ègzistenta.\n\n<strong>Nota :</strong>\nCen pôt côsar un changement radicâl et emprèviu por na pâge sovent viua ;\nse vos plét assurâd-vos de nen avêr comprês les consèquences devant que continuar.",
+       "movepagetext-noredirectfixer": "Empleyéd lo formulèro ce-desot por renomar na pâge, en dèplacient tot son historico vers lo novél nom.\nLo viely titro vindrat na pâge de redirèccion de vers lo titro novél.\nAssurâd-vos de controlar tota [[Special:DoubleRedirects|redirèccion dobla]] [[Special:BrokenRedirects|câssa]].\nVos éd la rèsponsabilitât de vos assurar que los lims continuont de pouentar vers lor dèstinacion suposâye.\n\nNotâd que la pâge serat <strong>pas</strong> dèplaciêe s’y at ja na pâge avouéc lo titro novél, a muens que cela dèrriére seye na simpla redirèccion avouéc un historico de changements vouedo.\nCen vôt dére que vos pouede renomar na pâge vers sa posicion d’origina se vos éd fêt na fôta, mas que vos pouede pas ècllafar na pâge ja ègzistenta.\n\n<strong>Nota :</strong>\nCen pôt côsar un changement radicâl et emprèviu por na pâge sovent viua ;\nse vos plét assurâd-vos de nen avêr comprês les consèquences devant que continuar.",
+       "movepagetalktext": "Se vos pouentâd cela câsa, la pâge de discussion associyêe serat asse-ben dèplaciêe ôtomaticament, a muens qu’una pâge de discussion pas voueda ègzisteye ja desot lo novél nom.\n\nDens cél câs, vos devréd dèplaciér fusionar la pâge a la man se vos o voléd.",
+       "moveuserpage-warning": "<strong>Atencion :</strong> vos éte prèst a dèplaciér na pâge utilisator. Se vos plét, notâd que solament la pâge serat dèplaciêe et que l’utilisator serat <em>pas</em> renomâ.",
+       "movecategorypage-warning": "<strong>Atencion :</strong> vos éte prèst a dèplaciér na pâge de catègoria. Se vos plét, notâd que solament la pâge serat dèplaciêe et que <em>pas yona</em> de les pâges de la vielye catègoria serat betâye dedens la novèla.",
+       "movenologintext": "Vos dête étre un utilisator encartâ et pués étre [[Special:UserLogin|branchiê]] por povêr dèplaciér na pâge.",
+       "movenotallowed": "Vos éd pas la pèrmission de dèplaciér de pâges.",
+       "movenotallowedfile": "Vos éd pas la pèrmission de dèplaciér de fichiérs.",
+       "cant-move-user-page": "Vos éd pas la pèrmission de dèplaciér de pâges utilisator (en defôr de sot-pâges).",
+       "cant-move-to-user-page": "Vos éd pas la pèrmission de dèplaciér na pâge vers na pâge utilisator (mas pas vers na sot-pâge utilisator).",
+       "cant-move-category-page": "Vos éd pas la pèrmission de dèplaciér de pâges de catègoria.",
+       "cant-move-to-category-page": "Vos éd pas la pèrmission de dèplaciér na pâge vers na pâge de catègoria.",
+       "newtitle": "Titro novél :",
        "move-watch": "Siuvre les pâges sôrsa et ciba",
-       "movepagebtn": "Renomar la pâge",
+       "movepagebtn": "Dèplaciér la pâge",
        "pagemovedsub": "Changement de nom reussi",
-       "movepage-moved": "'''« $1 » at étâ renomâ en « $2 »'''",
-       "movepage-moved-redirect": "Una redirèccion dês lo viely nom at étâ fêta.",
-       "movepage-moved-noredirect": "La crèacion d’una redirèccion dês lo viely nom at étâ anulâ.",
-       "articleexists": "Ègziste ja una pâge que pôrte cél titro, ou ben lo titro que vos éd chouèsi est fôx.\nNen volyéd chouèsir un ôtro.",
-       "cantmove-titleprotected": "Vos pouede pas dèplaciér una pâge vers cél emplacement perce que lo titro novél at étâ protègiê a la crèacion.",
-       "movetalk": "Renomar avouéc la pâge de discussion associyê",
-       "move-subpages": "Renomar les sot-pâges (tant qu’a $1 pâges)",
-       "move-talk-subpages": "Renomar les sot-pâges de la pâge de discussion (tant qu’a $1 pâges)",
-       "movepage-page-exists": "La pâge $1 ègziste ja et pôt pas étre ècrasâ ôtomaticament.",
-       "movepage-page-moved": "La pâge $1 at étâ renomâ en $2.",
-       "movepage-page-unmoved": "La pâge $1 at pas possu étre renomâ en $2.",
-       "movepage-max-pages": "Lo més de $1 {{PLURAL:$1|pâge at étâ renomâ|pâges ont étâ renomâs}} et niona ôtra pâge serat renomâ ôtomaticament.",
-       "movelogpage": "Jornal des changements de nom",
-       "movelogpagetext": "Vê-que la lista de totes les pâges renomâs ou dèplaciês.",
+       "movepage-moved": "<strong>« $1 » est étâ dèplaciê vers « $2 »</strong>",
+       "movepage-moved-redirect": "Na redirèccion est étâye fêta.",
+       "movepage-moved-noredirect": "La crèacion d’una redirèccion est étâye rèprimâye.",
+       "articleexists": "Ègziste ja na pâge avouéc cél nom, ou ben lo nom que vos éd chouèsi est pas justo.\nSe vos plét, chouèsésséd-nen un ôtro.",
+       "cantmove-titleprotected": "Vos pouede pas dèplaciér na pâge vers cél endrêt, lo titro novél est étâ protègiê a la crèacion.",
+       "movetalk": "Dèplaciér avouéc la pâge de discussion associyêe",
+       "move-subpages": "Dèplaciér les sot-pâges (tant qu’a $1)",
+       "move-talk-subpages": "Dèplaciér les sot-pâges de la pâge de discussion (tant qu’a $1)",
+       "movepage-page-exists": "La pâge $1 ègziste ja et pués pôt pas étre ècllafâye ôtomaticament.",
+       "movepage-page-moved": "La pâge $1 est étâye dèplaciêe vers $2.",
+       "movepage-page-unmoved": "La pâge $1 at pas possu étre dèplaciêe vers $2.",
+       "movepage-max-pages": "Lo més de $1 pâge{{PLURAL:$1||s}} est étâ dèplaciê et pués pas yona de més serat dèplaciêe ôtomaticament.",
+       "movelogpage": "Jornâl des changements de nom",
+       "movelogpagetext": "Vê-que na lista de totes les pâges dèplaciêes.",
        "movesubpage": "Sot-pâge{{PLURAL:$1||s}}",
-       "movesubpagetext": "Cela pâge at $1 {{PLURAL:$1|sot-pâge montrâ|sot-pâges montrâs}} ce-desot.",
-       "movenosubpage": "Ceta pâge at gins de sot-pâge.",
+       "movesubpagetext": "Cela pâge at $1 {{PLURAL:$1|sot-pâge montrâye|sot-pâges montrâyes}} ce-desot.",
+       "movenosubpage": "Cela pâge at gins de sot-pâge.",
        "movereason": "Rêson :",
-       "revertmove": "rètablir",
-       "delete_and_move_text": "== Suprèssion nècèssèra ==\nLa pâge de dèstinacion « [[:$1]] » ègziste ja.\nLa voléd-vos suprimar por pèrmetre lo changement de nom ?",
-       "delete_and_move_confirm": "Ouè, j’accèpto de suprimar la pâge de dèstinacion por pèrmetre lo changement de nom.",
-       "delete_and_move_reason": "Pâge suprimâ por pèrmetre lo changement de nom dês « [[$1]] »",
-       "selfmove": "Los titros d’origina et de dèstinacion sont los mémos ;\nempossiblo de renomar una pâge sur lyé-méma.",
-       "immobile-source-namespace": "Vos pouede pas renomar les pâges dens l’èspâço de noms « $1 »",
-       "immobile-target-namespace": "Vos pouede pas renomar des pâges vers l’èspâço de noms « $1 »",
-       "immobile-target-namespace-iw": "Los lims entèrvouiquis sont pas una ciba valida por los changements de nom.",
-       "immobile-source-page": "Cela pâge est pas renomâbla.",
-       "immobile-target-page": "Empossiblo de renomar la pâge vers cél titro.",
-       "imagenocrossnamespace": "Empossiblo de renomar un fichiér vers un èspâço de noms ôtro que « {{ns:file}} ».",
-       "nonfile-cannot-move-to-file": "Empossiblo de renomar quârque-ren d’ôtro qu’un fichiér vers l’èspâço de noms « {{ns:file}} ».",
-       "imagetypemismatch": "La novèla èxtension de cél fichiér corrèspond pas a son tipo.",
-       "imageinvalidfilename": "Lo nom du fichiér ciba est fôx",
-       "fix-double-redirects": "Betar a jorn les redirèccions que pouentont vers lo titro originâl",
-       "move-leave-redirect": "Lèssiér una redirèccion de vers lo titro novél",
-       "protectedpagemovewarning": "'''ATENCION :''' ceta pâge at étâ protègiê de façon que solament los usanciérs qu’ont lo statut d’administrator la pouessont renomar.\nLa dèrriére entrâ du jornal est montrâ ce-desot coment refèrence :",
-       "semiprotectedpagemovewarning": "'''Nota :''' ceta pâge at étâ protègiê de façon que solament los usanciérs encartâs la pouessont renomar.\nLa dèrriére entrâ du jornal est montrâ ce-desot coment refèrence :",
-       "move-over-sharedrepo": "== Lo fichiér ègziste ==\n[[:$1]] ègziste ja sur un dèpôt partagiê. Renomar cél fichiér rendrat lo fichiér sur lo dèpôt partagiê pas accèssiblo.",
-       "file-exists-sharedrepo": "Lo nom chouèsi est ja utilisâ per un fichiér sur un dèpôt partagiê.\nNen volyéd chouèsir un ôtro.",
-       "export": "Èxportar des pâges",
-       "exporttext": "Vos pouede èxportar en XML lo tèxto et l’historico d’una pâge ou ben d’un ensemblo de pâges ;\nlo rèsultat pôt adonc étre importâ dens un ôtro vouiqui qu’utilise la programeria MediaWiki avouéc la [[Special:Import|pâge d’importacion]].\n\nPor èxportar des pâges, buchiéd lors titros dens la bouèta de tèxto ce-desot, yon titro per legne, et pués chouèsésséd se vos voléd ou pas la vèrsion d’ora avouéc totes les vielyes vèrsions, avouéc les legnes de l’historico de la pâge, ou ben simplament la pâge d’ora avouéc des enformacions sur lo dèrriér changement.\n\nDens cél dèrriér câs, vos pouede asse-ben utilisar un lim, coment [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] por la pâge « [[{{MediaWiki:Mainpage}}]] ».",
+       "revertmove": "rèvocar",
+       "delete_and_move_text": "La pâge de dèstinacion « [[:$1]] » ègziste ja.\nVos la voléd suprimar por pèrmetre lo changement de nom ?",
+       "delete_and_move_confirm": "Ouè, suprimar la pâge",
+       "delete_and_move_reason": "Suprimâye por pèrmetre lo changement de nom dês « [[$1]] »",
+       "selfmove": "Los titros d’origina et de dèstinacion sont los mémos ;\ny at pas moyen de dèplaciér na pâge vers lyé-méma.",
+       "immobile-source-namespace": "Vos pouede pas dèplaciér les pâges dedens l’èspâço de noms « $1 ».",
+       "immobile-target-namespace": "Vos pouede pas dèplaciér de pâges vers l’èspâço de noms « $1 ».",
+       "immobile-target-namespace-iw": "Los lims entèrvouiquis sont pas na ciba justa por los changements de nom.",
+       "immobile-source-page": "Cela pâge est pas dèplaçâbla.",
+       "immobile-target-page": "Y at pas moyen de dèplaciér vers cél titro de dèstinacion.",
+       "bad-target-model": "La dèstinacion volua emplèye un ôtro modèlo de contegnu. Y at pas moyen de convèrtir de $1 vers $2.",
+       "imagenocrossnamespace": "Y at pas moyen de dèplaciér un fichiér vers un èspâço de noms ôtro que « {{ns:file}} ».",
+       "nonfile-cannot-move-to-file": "Y at pas moyen de dèplaciér quârque-ren d’ôtro qu’un fichiér vers l’èspâço de noms « {{ns:file}} ».",
+       "imagetypemismatch": "La novèla èxtension du fichiér corrèspond pas a son tipo.",
+       "imageinvalidfilename": "Lo nom du fichiér ciba est pas justo.",
+       "fix-double-redirects": "Betar a jorn totes les redirèccions que pouentont vers lo titro originâl",
+       "move-leave-redirect": "Lèssiér na redirèccion",
+       "protectedpagemovewarning": "<strong>Atencion :</strong> cela pâge est étâye protègiêe por que solament los utilisators qu’ant los drêts d’administrator la pouessont dèplaciér.\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
+       "semiprotectedpagemovewarning": "<strong>Nota :</strong> cela pâge est étâye protègiêe por que solament los utilisators encartâs la pouessont dèplaciér.\nLa dèrriére entrâ du jornâl est balyêe ce-desot coment rèference :",
+       "move-over-sharedrepo": "[[:$1]] ègziste ja sur un dèpôt partagiê. Dèplaciér un fichiér vers cél titro ècllaferat lo fichiér partagiê.",
+       "file-exists-sharedrepo": "Lo nom de fichiér chouèsi est ja empleyê sur un dèpôt partagiê.\nSe vos plét, chouèsésséd-nen un ôtro.",
+       "export": "Èxportar de pâges",
+       "exporttext": "Vos pouede èxportar en XML lo tèxto et l’historico d’una pâge d’un ensemblo de pâges.\nAdonc lo rèsultat pôt étre importâ dens un ôtro vouiqui qu’emplèye la programeria MediaWiki avouéc la [[Special:Import|pâge d’importacion]].\n\nPor èxportar de pâges, buchiéd lors titros dedens la bouèta de tèxto ce-desot, un titro per legne, et pués chouèsésséd se vos voléd la vèrsion d’ora avouéc totes les vielyes vèrsions, avouéc les legnes de l’historico de la pâge, ou ben simplament la pâge d’ora avouéc des enformacions sur lo dèrriér changement.\n\nDens cél dèrriér câs, vos pouede asse-ben empleyér un lim, coment [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] por la pâge « [[{{MediaWiki:Mainpage}}]] ».",
        "exportall": "Èxportar totes les pâges",
-       "exportcuronly": "Èxportar ren que la vèrsion d’ora, sen l’historico complèt",
-       "exportnohistory": "----\n'''Nota :''' l’èxportacion de l’historico complèt de les pâges avouéc ceti formulèro at étâ dèsactivâ por des rêsons de capacitât.",
-       "exportlistauthors": "Encllure una lista complèta ux contributors por châque pâge",
+       "exportcuronly": "Rapondre mas que la vèrsion d’ora, sen l’historico complèt",
+       "exportnohistory": "----\n<strong>Nota :</strong> l’èxportacion de l’historico complèt de les pâges avouéc cél formulèro est étâye dèsactivâye por des rêsons de capacitât.",
+       "exportlistauthors": "Rapondre na lista complèta des contributors por châque pâge",
        "export-submit": "Èxportar",
-       "export-addcattext": "Apondre les pâges de la catègorie :",
+       "export-addcattext": "Apondre de pâges de la catègoria :",
        "export-addcat": "Apondre",
-       "export-addnstext": "Apondre des pâges dens l’èspâço de noms :",
+       "export-addnstext": "Apondre de pâges de l’èspâço de noms :",
        "export-addns": "Apondre",
-       "export-download": "Encartar dens un fichiér",
-       "export-templates": "Encllure los modèlos",
-       "export-pagelinks": "Encllure les pâges liyês a una provondior de :",
+       "export-download": "Encartar dedens un fichiér",
+       "export-templates": "Rapondre los modèlos",
+       "export-pagelinks": "Rapondre les pâges liyêes a na provondior de :",
+       "export-manual": "Apondre de pâges a la man :",
        "allmessages": "Mèssâjos sistèmo",
-       "allmessagesname": "Nom du mèssâjo",
-       "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.\nVolyéd visitar la [https://www.mediawiki.org/wiki/Special:MyLanguage/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â.",
+       "allmessagesname": "Nom",
+       "allmessagesdefault": "Tèxto du mèssâjo per dèfôt",
+       "allmessagescurrent": "Tèxto du mèssâjo d’ora",
+       "allmessagestext": "O est na lista des mèssâjos sistèmo disponiblos dedens l’èspâço de noms MediaWiki.\nSe vos plét, vesitâd la [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation localisacion de MediaWiki] et pués [//translatewiki.net translatewiki.net] se vos voléd contribuar a la localisacion g·ènèrâla de MediaWiki.",
+       "allmessagesnotsupportedDB": "Cela pâge est pas empleyâbla, <strong>$wgUseDatabaseMessages</strong> est étâ dèsactivâ.",
        "allmessages-filter-legend": "Filtro",
-       "allmessages-filter": "Filtrar per ètat de changement :",
+       "allmessages-filter": "Filtrar per ètat de pèrsonalisacion :",
        "allmessages-filter-unmodified": "Pas changiê",
        "allmessages-filter-all": "Tôs",
        "allmessages-filter-modified": "Changiê",
        "allmessages-prefix": "Filtrar per prèfixo :",
        "allmessages-language": "Lengoua :",
-       "allmessages-filter-submit": "Aplicar",
+       "allmessages-filter-submit": "Emmodar",
+       "allmessages-filter-translate": "Traduire",
        "thumbnail-more": "Agrantir",
-       "filemissing": "Fichiér manquent",
-       "thumbnail_error": "Èrror pendent la crèacion de la figura : $1",
-       "djvu_page_error": "Pâge DjVu en defôr de les limites",
-       "djvu_no_xml": "Empossiblo de rècupèrar lo XML por lo fichiér DjVu",
-       "thumbnail-temp-create": "Empossiblo de fâre lo fichiér de figura temporèra",
-       "thumbnail-dest-create": "Empossiblo d’encartar la figura sur la dèstinacion",
-       "thumbnail_invalid_params": "Paramètres de la figura fôx",
-       "thumbnail_dest_directory": "Empossiblo de fâre lo rèpèrtouèro de dèstinacion",
+       "filemissing": "Fichiér entrovâblo",
+       "thumbnail_error": "Fôta pendent la crèacion de la miniatura : $1",
+       "thumbnail_error_remote": "Mèssâjo de fôta de $1 :\n$2",
+       "djvu_page_error": "Pâge DjVu en defôr de portâ",
+       "djvu_no_xml": "Y at pas moyen de rècupèrar lo XML por lo fichiér DjVu",
+       "thumbnail-temp-create": "Y at pas moyen de fâre lo fichiér de miniatura temporèro",
+       "thumbnail-dest-create": "Y at pas moyen d’encartar la miniatura sur la dèstinacion",
+       "thumbnail_invalid_params": "Paramètros de la miniatura pas justos",
+       "thumbnail_toobigimagearea": "Fichiér avouéc des dimensions d’amont $1",
+       "thumbnail_dest_directory": "Y at pas moyen de fâre lo rèpèrtouèro de dèstinacion",
        "thumbnail_image-type": "Tipo d’émâge pas recognu",
        "thumbnail_gd-library": "Configuracion encomplèta de la bibliotèca GD : fonccion $1 entrovâbla",
-       "thumbnail_image-missing": "Ceti fichiér est entrovâblo : $1",
-       "import": "Importar des pâges",
-       "importinterwiki": "Importacion entèrvouiqui",
-       "import-interwiki-text": "Chouèsésséd un vouiqui et un titro de pâge a importar.\nLes dâtes de les vèrsions et los noms ux contributors seront presèrvâs.\nTotes les accions d’importacion entèrvouiqui sont consignês dens lo [[Special:Log/import|jornal de les importacions]].",
-       "import-interwiki-history": "Copiyér totes les vèrsions de l’historico de ceta pâge",
-       "import-interwiki-templates": "Encllure tôs los modèlos",
+       "thumbnail_image-missing": "Lo fichiér semble étre entrovâblo : $1",
+       "thumbnail_image-failure-limit": "Dês pou y at avu un mouél d’èprôves pas reussies ($1 ou ben més) por rèstituar cela miniatura. Se vos plét, tornâd èprovar ples târd.",
+       "import": "Importar de pâges",
+       "importinterwiki": "Importar dês un ôtro vouiqui",
+       "import-interwiki-text": "Chouèsésséd un vouiqui et pués un titro de pâge a importar.\nLes dâtes de les vèrsions et los noms des contributors seront presèrvâs.\nTotes les importacions dês d’ôtros vouiquis sont encartâyes dessus lo [[Special:Log/import|jornâl de les importacions]].",
+       "import-interwiki-sourcewiki": "Vouiqui d’origina :",
+       "import-interwiki-sourcepage": "Pâge d’origina :",
+       "import-interwiki-history": "Copiyér totes les vèrsions de l’historico de cela pâge",
+       "import-interwiki-templates": "Rapondre tôs los modèlos",
        "import-interwiki-submit": "Importar",
+       "import-mapping-default": "Importar ux endrêts per dèfôt",
+       "import-mapping-namespace": "Importar vers un èspâço de noms :",
+       "import-mapping-subpage": "Importar coment sot-pâges de cela pâge-que :",
        "import-upload-filename": "Nom du fichiér :",
        "import-comment": "Comentèro :",
-       "importtext": "Volyéd èxportar lo fichiér dês lo vouiqui d’origina en utilisent son [[Special:Export|outil d’èxportacion]].\nSôvâd-lo sur voutron ordenator et pués tèlèchargiéd-lo ique.",
+       "importtext": "Se vos plét, èxportâd lo fichiér dês lo vouiqui d’origina en empleyent son [[Special:Export|outil d’èxportacion]].\nEncartâd-lo sur voutron ordenator et pués tèlèchargiéd-lo ique.",
        "importstart": "Importacion de les pâges...",
        "import-revision-count": "$1 vèrsion{{PLURAL:$1||s}}",
-       "importnopages": "Gins de pâge a importar.",
-       "imported-log-entries": "$1 entrâ{{PLURAL:$1||s}} du jornal importâ{{PLURAL:$1||s}}.",
+       "importnopages": "Niona pâge a importar.",
+       "imported-log-entries": "$1 entr{{PLURAL:$1|â|ês}} du jornâl importâye{{PLURAL:$1||s}}.",
        "importfailed": "Falyita de l’importacion : <nowiki>$1</nowiki>",
        "importunknownsource": "Tipo de la sôrsa a importar encognu",
-       "importcantopen": "Empossiblo d’uvrir lo fichiér a importar",
+       "importcantopen": "Y at pas moyen d’uvrir lo fichiér a importar",
        "importbadinterwiki": "Crouyo lim entèrvouiqui",
-       "importsuccess": "L’importacion at reussia !",
-       "importnosources": "Niona sôrsa d’importacion entèrvouiqui at étâ dèfenia et los tèlèchargements drêts d’historicos sont dèsactivâs.",
-       "importnofile": "Nion fichiér a importar at étâ tèlèchargiê.",
-       "importuploaderrorsize": "Lo tèlèchargement du fichiér a importar at pas reussi.\nSa talye est ples granta que cela ôtorisâ.",
-       "importuploaderrorpartial": "Lo tèlèchargement du fichiér a importar at pas reussi.\nSon contegnu at étâ tèlèchargiê ren qu’a mêtiêt.",
-       "importuploaderrortemp": "Lo tèlèchargement du fichiér a importar at pas reussi.\nUn dossiér temporèro est manquent.",
+       "importsuccess": "L’importacion at reussi !",
+       "importnosources": "Nion vouiqui d’origina est étâ dèfeni et pués los tèlèchargements drêts d’historicos sont dèsactivâs.",
+       "importnofile": "Nion fichiér a importar est étâ tèlèchargiê.",
+       "importuploaderrorsize": "Lo tèlèchargement du fichiér a importar at pas reussi.\nSa talye est ples granta que cela ôtorisâye.",
+       "importuploaderrorpartial": "Lo tèlèchargement du fichiér a importar at pas reussi.\nSon contegnu est étâ tèlèchargiê ren qu’a mêtiêt.",
+       "importuploaderrortemp": "Lo tèlèchargement du fichiér a importar at pas reussi.\nUn dossiér temporèro est entrovâblo.",
        "import-parse-failure": "Falyita pendent l’analise du XML a importar",
-       "import-noarticle": "Gins de pâge a importar !",
-       "import-nonewrevisions": "Totes les vèrsions ont étâ importâs dês devant.",
+       "import-noarticle": "Niona pâge a importar !",
+       "import-nonewrevisions": "Niona vèrsion importâye (totes érant ja presentes ou ben ignorâyes a côsa de fôtes).",
        "xml-error-string": "$1 a la legne $2, colona $3 (octèt $4) : $5",
        "import-upload": "Tèlèchargement de balyês XML",
-       "import-token-mismatch": "Pèrta de les balyês de sèance.\nVolyéd tornar èprovar.",
-       "import-invalid-interwiki": "Empossiblo d’importar dês lo vouiqui spècefiâ.",
-       "import-error-edit": "La pâge « $1 » est pas importâ perce que vos éte pas ôtorisâ a la changiér.",
-       "import-error-create": "La pâge « $1 » est pas importâ perce que vos éte pas ôtorisâ a la fâre.",
+       "import-token-mismatch": "Pèrda de les balyês de sèssion.\n\nPôt-étre vos éte étâ dèbranchiê. <strong>Se vos plét, controlâd que vos éte adés branchiê et pués tornâd èprovar.</strong>\nSe cen tôrne pas reussir, èprovâd de vos [[Special:UserLogout|dèbranchiér]] et pués de vos tornar branchiér, et controlâd que voutron navegator accèpte los raportiors (<em>cookies</em>) de cél seto.",
+       "import-invalid-interwiki": "Y at pas moyen d’importar dês lo vouiqui spècifiâ.",
+       "import-error-edit": "La pâge « $1 » est pas étâye importâye, vos éte pas ôtorisâ a la changiér.",
+       "import-error-create": "La pâge « $1 » est pas étâye importâye, vos éte pas ôtorisâ a la fâre.",
+       "import-error-interwiki": "La pâge « $1 » est pas étâye importâye, son nom est resèrvâ por un lim de defôr (entèrvouiqui).",
+       "import-error-special": "La pâge « $1 » est pas étâye importâye, el est a un èspâço de noms spèciâl qu’ôtorise gins de pâge.",
+       "import-error-invalid": "La pâge « $1 » est pas étâye importâye, lo nom que lyé serêt étâye importâye desot est pas justo sur cél vouiqui.",
+       "import-error-unserialize": "La vèrsion $2 de la pâge « $1 » pôt pas étre dèssèrialisâye. La vèrsion ére raportâye coment empleyent lo modèlo de contegnu $3 sèrialisâ en $4.",
+       "import-error-bad-location": "La vèrsion $2 qu’emplèye lo modèlo de contegnu $3 at pas possu étre stocâye dessus « $1 » sur cél vouiqui-que, cél modèlo est pas recognu sur cela pâge.",
        "import-options-wrong": "{{PLURAL:$2|Crouyo chouèx|Crouyos chouèx}} : <nowiki>$1</nowiki>",
-       "importlogpage": "Jornal de les importacions",
+       "import-rootpage-invalid": "La pâge racena balyêe est un titro pas justo.",
+       "import-rootpage-nosubpage": "L’èspâço de noms « $1 » de la pâge racena ôtorise pas les sot-pâges.",
+       "importlogpage": "Jornâl de les importacions",
        "importlogpagetext": "Importacions administratives de pâges avouéc lor historico de changements dês d’ôtros vouiquis.",
-       "import-logentry-upload-detail": "$1 vèrsion{{PLURAL:$1||s}}",
-       "import-logentry-interwiki-detail": "$1 vèrsion{{PLURAL:$1||s}} dês $2",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|vèrsion importâye|vèrsions importâyes}}",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|vèrsion importâye|vèrsions importâyes}} dês $2",
        "javascripttest": "Èprôva de JavaScript",
+       "javascripttest-pagetext-unknownaction": "Accion « $1 » encognua.",
        "javascripttest-qunit-intro": "Vêde la [$1 documentacion de les èprôves] dessus mediawiki.org.",
-       "tooltip-pt-userpage": "Voutra pâge usanciér",
-       "tooltip-pt-anonuserpage": "La pâge usanciér de l’adrèce IP avouéc laquinta vos contribuâd",
-       "tooltip-pt-mytalk": "Voutra pâge de discussion",
-       "tooltip-pt-anontalk": "La pâge de discussion por les contribucions dês cela adrèce IP",
-       "tooltip-pt-preferences": "Voutres prèferences",
-       "tooltip-pt-watchlist": "La lista de les pâges que vos siude los changements",
-       "tooltip-pt-mycontris": "La lista de voutres contribucions",
-       "tooltip-pt-login": "Vos éte encoragiê a vos branchiér ; portant o est pas oblegatouèro.",
+       "tooltip-pt-userpage": "{{GENDER:|Voutra}} pâge utilisator",
+       "tooltip-pt-anonuserpage": "La pâge utilisator por l’adrèce IP que vos empleyéd",
+       "tooltip-pt-mytalk": "{{GENDER:|Voutra}} pâge de discussion",
+       "tooltip-pt-anontalk": "Discussion sur los changements fêts dês cel’adrèce IP",
+       "tooltip-pt-preferences": "{{GENDER:|Voutres}} prèferences",
+       "tooltip-pt-watchlist": "Na lista de les pâges que vos gouardâd los changements",
+       "tooltip-pt-mycontris": "Na lista de {{GENDER:|voutres}} contribucions",
+       "tooltip-pt-anoncontribs": "Na lista des changements fêts dês cel’adrèce IP",
+       "tooltip-pt-login": "Vos éte encoragiê a vos branchiér ; portant o est pas oblegatouèro",
        "tooltip-pt-logout": "Sè dèbranchiér",
-       "tooltip-pt-createaccount": "Vos éte encoragiê a fâre un comptio et pués a vos branchiér ; portant o est pas oblegatouèro.",
-       "tooltip-ca-talk": "Discussion dessus cela pâge de contegnu",
+       "tooltip-pt-createaccount": "Vos éte encoragiê a fâre un comptio et pués a vos branchiér ; portant o est pas oblegatouèro",
+       "tooltip-ca-talk": "Discussion sur lo contegnu de la pâge",
        "tooltip-ca-edit": "Changiér cela pâge",
-       "tooltip-ca-addsection": "Comenciér una novèla sèccion",
-       "tooltip-ca-viewsource": "Ceta pâge est protègiêye.\nPortant vos en pouede vêre lo sin tèxto sôrsa",
+       "tooltip-ca-addsection": "Comenciér na novèla sèccion",
+       "tooltip-ca-viewsource": "Cela pâge est protègiêe.\nPortant vos en pouede vêre son tèxto sôrsa",
        "tooltip-ca-history": "Vèrsions passâyes de cela pâge",
-       "tooltip-ca-protect": "Protègiér ceta pâge",
-       "tooltip-ca-unprotect": "Changiér la protèccion de ceta pâge",
-       "tooltip-ca-delete": "Suprimar ceta pâge",
-       "tooltip-ca-undelete": "Refâre los changements fêts sur ceta pâge devant sa suprèssion",
-       "tooltip-ca-move": "Renomar ceta pâge",
+       "tooltip-ca-protect": "Protègiér cela pâge",
+       "tooltip-ca-unprotect": "Changiér la protèccion de cela pâge",
+       "tooltip-ca-delete": "Suprimar cela pâge",
+       "tooltip-ca-undelete": "Refâre los changements fêts sur cela pâge devant sa suprèssion",
+       "tooltip-ca-move": "Dèplaciér cela pâge",
        "tooltip-ca-watch": "Apondre cela pâge a voutra lista de gouârda",
-       "tooltip-ca-unwatch": "Enlevar ceta pâge de voutra lista de survelyence",
+       "tooltip-ca-unwatch": "Enlevar cela pâge de voutra lista de gouârda",
        "tooltip-search": "Rechèrchiér dedens {{SITENAME}}",
-       "tooltip-search-go": "Alar de vers na pâge que pôrte justo cél nom s’ègziste.",
-       "tooltip-search-fulltext": "Rechèrchiér les pâges que presentont cél tèxto.",
+       "tooltip-search-go": "Emmodar vers na pâge que pôrte justo cél nom s’ègziste",
+       "tooltip-search-fulltext": "Rechèrchiér les pâges que presentont cél tèxto",
        "tooltip-p-logo": "Vesitar la pâge principâla",
        "tooltip-n-mainpage": "Vesitar la pâge principâla",
        "tooltip-n-mainpage-description": "Vesitar la pâge principâla",
-       "tooltip-n-portal": "Dessus lo projèt, cen que vos pouede fâre, yô que trovar les chouses.",
-       "tooltip-n-currentevents": "Trovar les enformacions de fond dessus les dèrriéres novèles",
+       "tooltip-n-portal": "Sur lo projèt, cen que vos pouede fâre, yô que trovar de chouses",
+       "tooltip-n-currentevents": "Trovar les enformacions de fond sur les novèles d’ora",
        "tooltip-n-recentchanges": "Na lista des dèrriérs changements sur lo vouiqui",
-       "tooltip-n-randompage": "Fâre vêre na pâge a l’hasârd",
-       "tooltip-n-help": "L’endrêt por nen savêr més.",
-       "tooltip-t-whatlinkshere": "Na lista de les pâges liyêes a ceta",
+       "tooltip-n-randompage": "Chargiér na pâge a l’hasârd",
+       "tooltip-n-help": "L’endrêt por nen savêr més",
+       "tooltip-t-whatlinkshere": "Na lista de totes les pâges du vouiqui liyêes a ceta",
        "tooltip-t-recentchangeslinked": "Dèrriérs changements de les pâges liyêes a ceta",
-       "tooltip-feed-rss": "Flux RSS por ceta pâge",
-       "tooltip-feed-atom": "Flux Atom por ceta pâge",
-       "tooltip-t-contributions": "Vêre la lista de les contribucions de cet’utilisator",
-       "tooltip-t-emailuser": "Mandar un mèssâjo a ceti usanciér",
-       "tooltip-t-upload": "Tèlèchargiér des fichiérs",
+       "tooltip-feed-rss": "Flux RSS por cela pâge",
+       "tooltip-feed-atom": "Flux Atom por cela pâge",
+       "tooltip-t-contributions": "Na lista de les contribucions de {{GENDER:$1|cél utilisator|cel’utilisatrice}}",
+       "tooltip-t-emailuser": "Mandar un mèssâjo a {{GENDER:$1|cél utilisator|cel’utilisatrice}}",
+       "tooltip-t-info": "Més d’enformacions sur cela pâge",
+       "tooltip-t-upload": "Tèlèchargiér de fichiérs",
        "tooltip-t-specialpages": "Na lista de totes les pâges spèciâles",
        "tooltip-t-print": "Vèrsion emprimâbla de cela pâge",
        "tooltip-t-permalink": "Lim fixo de vers cela vèrsion de la pâge",
        "tooltip-ca-nstab-main": "Vêre la pâge de contegnu",
        "tooltip-ca-nstab-user": "Vêre la pâge utilisator",
-       "tooltip-ca-nstab-media": "Vêre la pâge du fichiér mèdia",
-       "tooltip-ca-nstab-special": "O est na pâge spèciâla que pôt pas étre changiêe.",
+       "tooltip-ca-nstab-media": "Vêre la pâge mèdiâ",
+       "tooltip-ca-nstab-special": "O est na pâge spèciâla que pôt pas étre changiêe",
        "tooltip-ca-nstab-project": "Vêre la pâge projèt",
        "tooltip-ca-nstab-image": "Vêre la pâge du fichiér",
        "tooltip-ca-nstab-mediawiki": "Vêre lo mèssâjo sistèmo",
        "tooltip-ca-nstab-template": "Vêre lo modèlo",
        "tooltip-ca-nstab-help": "Vêre la pâge d’éde",
-       "tooltip-ca-nstab-category": "Vêre la pâge de la catègorie",
+       "tooltip-ca-nstab-category": "Vêre la pâge de la catègoria",
        "tooltip-minoredit": "Marcar mos changements coment petiôts",
-       "tooltip-save": "Sôvar voutros changements",
-       "tooltip-preview": "Volyéd prèvisualisar voutros changements devant que los sôvar !",
-       "tooltip-diff": "Pèrmèt de montrar los changements que vos éd fêts",
-       "tooltip-compareselectedversions": "Fâre ressortir les difèrences entre doves vèrsions de ceta pâge",
-       "tooltip-watch": "Apondre ceta pâge a voutra lista de survelyence",
+       "tooltip-save": "Encartar voutros changements",
+       "tooltip-preview": "Prèvêde voutros changements. Se vos plét, empleyéd-lo devant qu’encartar.",
+       "tooltip-diff": "Montrar los changements que vos éd aportâs u tèxto",
+       "tooltip-compareselectedversions": "Fâre ressortir les difèrences entre les doves vèrsions chouèsies de cela pâge",
+       "tooltip-watch": "Apondre cela pâge a voutra lista de gouârda",
        "tooltip-watchlistedit-normal-submit": "Enlevar los titros",
-       "tooltip-watchlistedit-raw-submit": "Betar a jorn la lista de survelyence",
-       "tooltip-recreate": "Refâre la pâge mémo se ceta at étâ suprimâ",
+       "tooltip-watchlistedit-raw-submit": "Betar a jorn la lista de gouârda",
+       "tooltip-recreate": "Refâre la pâge quand ben que ceta est étâye suprimâye",
        "tooltip-upload": "Emmodar lo tèlèchargement",
-       "tooltip-rollback": "« Rèvocar » anule tot d’un côp lo ou ben los changement(s) de cela pâge per lo dèrriér contributor.",
-       "tooltip-undo": "« Dèfâre » rèvoque ceti changement et ôvre la fenétra d’èdicion en fôrma de prèvisualisacion.\nPèrmèt de rètablir la vèrsion devant et pués d’apondre una rêson dens la bouèta de rèsumâ.",
+       "tooltip-rollback": "« Rèvocar » anule tot d’un côp lo(s) changement(s) de cela pâge per lo dèrriér contributor",
+       "tooltip-undo": "« Dèfâre » anule cél changement et pués ôvre la fenétra de changement en fôrma d’apèrçu. Pèrmèt d’apondre na rêson dens lo rèsumâ.",
        "tooltip-preferences-save": "Encartar les prèferences",
        "tooltip-summary": "Buchiéd un côrt rèsumâ",
        "common.css": "/* Lo code CSS betâ ique serat aplicâ a tôs los habelyâjos. */",
        "group-bot.js": "/* Tot code JavaScript betâ ique serat chargiê ren que por los bots. */",
        "group-sysop.js": "/* Tot code JavaScript betâ ique serat chargiê ren que por los administrators. */",
        "group-bureaucrat.js": "/* Tot code JavaScript betâ ique serat chargiê ren que por los grata-papiérs. */",
-       "anonymous": "{{PLURAL:$1|Usanciér pas encartâ|Usanciérs pas encartâs}} dessus {{SITENAME}}",
-       "siteuser": "l’usanciér{{GENDER:$2||e}} $1 de {{SITENAME}}",
-       "anonuser": "l’usanciér pas encartâ $1 de {{SITENAME}}",
-       "lastmodifiedatby": "Ceta pâge at étâ changiê por lo dèrriér côp lo $1 a $2 per $3.",
+       "anonymous": "{{PLURAL:$1|Utilisator anonimo|Utilisators anonimos}} dessus {{SITENAME}}",
+       "siteuser": "l’utilisat{{GENDER:$2|or|rice}} $1 de {{SITENAME}}",
+       "anonuser": "l’utilisator anonimo $1 de {{SITENAME}}",
+       "lastmodifiedatby": "Cela pâge est étâye changiêe por lo dèrriér côp lo $1 a $2 per $3.",
        "othercontribs": "Basâ sur l’ôvra a $1.",
        "others": "ôtros",
-       "siteusers": "{{PLURAL:$2|l’usanciér|los usanciérs}} $1 de {{SITENAME}}",
-       "anonusers": "{{PLURAL:$2|l’usanciér pas encartâ|los usanciérs pas encartâs}} $1 de {{SITENAME}}",
-       "creditspage": "Crèdits de la pâge",
-       "nocredits": "Y at gins d’enformacion d’atribucion disponibla por ceta pâge.",
-       "spamprotectiontitle": "Pâge protègiê ôtomaticament a côsa de spame",
-       "spamprotectiontext": "La pâge que vos éd tâchiê de sôvar at étâ blocâ per lo filtro anti-spame.\nO est probâblament diu a un lim de vers un seto de defôr qu’aparêt sur la lista nêre.",
-       "spamprotectionmatch": "La chêna de caractèros « '''$1''' » at dècllenchiê lo dècelior de spame.",
-       "spambot_username": "Neteyâjo de spame per MediaWiki",
+       "siteusers": "{{PLURAL:$2|{{GENDER:$1|l’utilisator|l’utilisatrice}}|{{Gender:$1|los utilisators|les utilisatrices}}}} $1 de {{SITENAME}}",
+       "anonusers": "{{PLURAL:$2|l’utilisator anonimo|los utilisators anonimos}} $1 de {{SITENAME}}",
+       "creditspage": "Atribucions de la pâge",
+       "nocredits": "Y at gins d’enformacion d’atribucion disponibla por cela pâge.",
+       "spamprotectiontitle": "Filtro de protèccion contre los mèssâjos cofos",
+       "spamprotectiontext": "Lo tèxto que vos éd volu encartar est étâ blocâ per lo filtro contre los mèssâjos cofos.\nO est probâblament diu a un lim de vers un seto de defôr qu’aparêt sur la lista nêre.",
+       "spamprotectionmatch": "Cél tèxto-que est cen qu’at dècllenchiê noutron filtro contre los mèssâjos cofos : $1",
+       "spambot_username": "Neteyâjo de mèssâjos cofos per MediaWiki",
        "spam_reverting": "Rètablissement de la dèrriére vèrsion que contint gins de lim de vers $1",
-       "spam_blanking": "Totes les vèrsions que contegnont des lims de vers $1 sont blanchies",
-       "spam_deleting": "Totes les vèrsions que contegnont des lims de vers $1 sont suprimâs",
-       "simpleantispam-label": "Contrôlo anti-spame.\nEnscrîde '''REN''' ique !",
+       "spam_blanking": "Totes les vèrsions que contegnont de lims de vers $1 sont blanchies",
+       "spam_deleting": "Totes les vèrsions que contegnont de lims de vers $1 sont suprimâyes",
+       "simpleantispam-label": "Contrôlo contre los mèssâjos cofos.\nEmpléd <strong>ren</strong> ique !",
        "pageinfo-title": "Enformacions por « $1 »",
+       "pageinfo-not-current": "Dèsolâ, y at pas moyen de balyér cel’enformacion por les vielyes vèrsions.",
        "pageinfo-header-basic": "Enformacions de bâsa",
        "pageinfo-header-edits": "Historico des changements",
        "pageinfo-header-restrictions": "Protèccion de la pâge",
        "pageinfo-header-properties": "Propriètâts de la pâge",
        "pageinfo-display-title": "Titro montrâ",
-       "pageinfo-default-sort": "Cllâf de tri per dèfôt",
+       "pageinfo-default-sort": "Cllâf de chouèx per dèfôt",
        "pageinfo-length": "Talye de la pâge (en octèts)",
-       "pageinfo-article-id": "Numerô de la pâge",
+       "pageinfo-article-id": "Identifient de la pâge",
        "pageinfo-language": "Lengoua du contegnu de la pâge",
-       "pageinfo-robot-policy": "Statut de motor de rechèrche",
-       "pageinfo-robot-index": "Endèxâblo",
-       "pageinfo-robot-noindex": "Pas endèxâblo",
-       "pageinfo-watchers": "Nombro de contributors qu’ont la pâge dedens lor lista de survelyence",
-       "pageinfo-redirects-name": "Redirèccions de vers ceta pâge",
-       "pageinfo-subpages-name": "Sot-pâges de ceta pâge",
+       "pageinfo-content-model": "Modèlo de contegnu de la pâge",
+       "pageinfo-robot-policy": "Endèxacion per robots",
+       "pageinfo-robot-index": "Ôtorisâye",
+       "pageinfo-robot-noindex": "Dèfendua",
+       "pageinfo-watchers": "Nombro d’obsèrvators de la pâge",
+       "pageinfo-visiting-watchers": "Nombro d’obsèrvators de la pâge qu’ant vesitâ los dèrriérs changements",
+       "pageinfo-few-watchers": "Muens de $1 obsèrvator{{PLURAL:$1||s}}",
+       "pageinfo-few-visiting-watchers": "Y pôt ou ben pas avêr un obsèrvator que vesite los dèrriérs changements",
+       "pageinfo-redirects-name": "Nombro de redirèccions de vers cela pâge",
+       "pageinfo-subpages-name": "Nombro de sot-pâges de cela pâge",
        "pageinfo-subpages-value": "$1 ($2 redirèccion{{PLURAL:$2||s}} ; $3 nan-redirèccion{{PLURAL:$3||s}})",
        "pageinfo-firstuser": "Crèator de la pâge",
        "pageinfo-firsttime": "Dâta de crèacion de la pâge",
        "pageinfo-lasttime": "Dâta du dèrriér changement",
        "pageinfo-edits": "Soma totâla de changements",
        "pageinfo-authors": "Soma totâla d’ôtors difèrents",
-       "pageinfo-recent-edits": "Nombro de novéls changements (dedens los $1 passâs)",
+       "pageinfo-recent-edits": "Nombro de novéls changements (dens los $1 passâs)",
        "pageinfo-recent-authors": "Nombro de novéls ôtors difèrents",
        "pageinfo-magic-words": "{{PLURAL:$1|Mot magico|Mots magicos}} ($1)",
-       "pageinfo-hidden-categories": "{{PLURAL:$1|Catègorie cachiêye|Catègories cachiêyes}} ($1)",
-       "pageinfo-templates": "{{PLURAL:$1|Modèlo encllu|Modèlos encllus}} ($1)",
-       "pageinfo-toolboxlink": "Enformacions dessus la pâge",
+       "pageinfo-hidden-categories": "{{PLURAL:$1|Catègoria cachiêe|Catègories cachiêes}} ($1)",
+       "pageinfo-templates": "{{PLURAL:$1|Modèlo transcllu|Modèlos transcllus}} ($1)",
+       "pageinfo-transclusions": "Pâge{{PLURAL:$1||s}} yô qu’el est transcllua ($1)",
+       "pageinfo-toolboxlink": "Enformacions sur la pâge",
        "pageinfo-redirectsto": "Redirige vers",
        "pageinfo-redirectsto-info": "enfô",
        "pageinfo-contentpage": "Comptâ coment pâge de contegnu",
        "pageinfo-contentpage-yes": "Ouè",
+       "pageinfo-protect-cascading": "Les protèccions sont en cascâda dês ique",
        "pageinfo-protect-cascading-yes": "Ouè",
-       "markaspatrolleddiff": "Marcar coment survelyê",
-       "markaspatrolledtext": "Marcar ceta pâge coment survelyê",
-       "markedaspatrolled": "Marcâye coment survelyêye",
-       "markedaspatrolledtext": "La vèrsion chouèsia de [[:$1]] est étâye marcâye coment survelyêye.",
-       "rcpatroldisabled": "La fonccion de survelyence des dèrriérs changements est pas activâ.",
-       "rcpatroldisabledtext": "La fonccionalitât de survelyence des dèrriérs changements est pas activâ.",
-       "markedaspatrollederror": "Pôt pas étre marcâye coment survelyêye",
-       "markedaspatrollederrortext": "Vos dête chouèsir una vèrsion por la povêr marcar coment survelyê.",
-       "markedaspatrollederror-noautopatrol": "Vos avéd pas lo drêt de marcar voutros prôpros changements coment survelyês.",
-       "patrol-log-page": "Jornal de les vèrsions survelyês",
-       "patrol-log-header": "Vê-que un jornal de les vèrsions survelyês.",
-       "log-show-hide-patrol": "$1 lo jornal de les vèrsions survelyês",
-       "deletedrevision": "La vielye vèrsion $1 at étâ suprimâ.",
-       "filedeleteerror-short": "Èrror pendent la suprèssion du fichiér : $1",
-       "filedeleteerror-long": "Des èrrors ont étâ rencontrâs pendent la suprèssion du fichiér :\n\n$1",
-       "filedelete-missing": "Lo fichiér « $1 » pôt pas étre suprimâ perce qu’ègziste pas.",
-       "filedelete-old-unregistered": "La vèrsion du fichiér spècefiâ « $1 » est pas dens la bâsa de balyês.",
-       "filedelete-current-unregistered": "Lo fichiér spècefiâ « $1 » est pas dens la bâsa de balyês.",
-       "filedelete-archive-read-only": "Lo dossiér d’arch·ivâjo « $1 » pôt pas étre changiê per lo sèrvor.",
+       "pageinfo-protect-cascading-from": "Les protèccions sont en cascâda dês",
+       "pageinfo-category-info": "Enformacions sur la catègoria",
+       "pageinfo-category-total": "Soma totâla de membros",
+       "pageinfo-category-pages": "Nombro de pâges",
+       "pageinfo-category-subcats": "Nombro de sot-catègories",
+       "pageinfo-category-files": "Nombro de fichiérs",
+       "markaspatrolleddiff": "Marcar coment gouardâ",
+       "markaspatrolledtext": "Marcar cela pâge coment gouardâye",
+       "markaspatrolledtext-file": "Marcar cela vèrsion de fichiér coment gouardâye",
+       "markedaspatrolled": "Marcâ coment gouardâ",
+       "markedaspatrolledtext": "La vèrsion chouèsia de [[:$1]] est étâye marcâye coment gouardâye.",
+       "rcpatroldisabled": "La gouârda des dèrriérs changements est dèsactivâye",
+       "rcpatroldisabledtext": "Ora la fonccionalitât de gouârda des dèrriérs changements est dèsactivâye.",
+       "markedaspatrollederror": "Pôt pas étre marcâ coment gouardâ",
+       "markedaspatrollederrortext": "Vos dête spècifiar na vèrsion por la povêr marcar coment gouardâye.",
+       "markedaspatrollederror-noautopatrol": "Vos éd pas lo drêt de marcar los voutros changements coment gouardâs.",
+       "markedaspatrollednotify": "Cél changement de $1 est étâ marcâ coment gouardâ.",
+       "markedaspatrollederrornotify": "Falyita du marcâjo du changement coment gouardâ.",
+       "patrol-log-page": "Jornâl de gouârda",
+       "patrol-log-header": "Vê-que un jornâl de les vèrsions gouardâyes.",
+       "log-show-hide-patrol": "$1 lo jornâl de gouârda",
+       "log-show-hide-tag": "$1 lo jornâl de les balises",
+       "deletedrevision": "Vielye vèrsion $1 suprimâye",
+       "filedeleteerror-short": "Fôta pendent la suprèssion du fichiér : $1",
+       "filedeleteerror-long": "Des fôtes sont étâyes rencontrâyes pendent la suprèssion du fichiér :\n\n$1",
+       "filedelete-missing": "Lo fichiér « $1 » pôt pas étre suprimâ, ègziste pas.",
+       "filedelete-old-unregistered": "La vèrsion du fichiér spècifiâye « $1 » est pas dedens la bâsa de balyês.",
+       "filedelete-current-unregistered": "Lo fichiér spècifiâ « $1 » est pas dedens la bâsa de balyês.",
+       "filedelete-archive-read-only": "Lo rèpèrtouèro d’arch·ivâjo « $1 » est pas enscriptiblo per lo sèrvior Vouèbe.",
        "previousdiff": "← Changement devant",
        "nextdiff": "Changement aprés →",
-       "mediawarning": "'''Atencion :''' ceti tipo de fichiér pôt contegnir de code mâlvelyent.\nSe vos l’ègzécutâd, voutron sistèmo pôt étre compromês.",
-       "imagemaxsize": "Format lo ples grant de les émâges :<br />''(por les pâges de dèscripcion d’émâges)''",
-       "thumbsize": "Talye de la figura :",
+       "mediawarning": "<strong>Atencion :</strong> cél tipo de fichiér pôt contegnir de code mâlvelyent.\nSe vos l’ègzécutâd, voutron sistèmo pôt étre compromètu.",
+       "imagemaxsize": "Talye maximon de les émâges :<br /><em>(por les pâges de dèscripcion de fichiérs)</em>",
+       "thumbsize": "Talye de la miniatura :",
        "widthheightpage": "$1 × $2, $3 pâge{{PLURAL:$3||s}}",
        "file-info": "Talye du fichiér : $1, tipo MIME : $2",
        "file-info-size": "$1 × $2 pixèls, talye du fichiér : $3, tipo MIME : $4",
        "file-info-size-pages": "$1 × $2 pixèls, talye du fichiér : $3, tipo MIME : $4, $5 pâge{{PLURAL:$5||s}}",
-       "file-nohires": "Gins de rèsolucion ples hôta disponibla.",
-       "svg-long-desc": "Fichiér SVG, rèsolucion de $1 × $2 pixèls, talye : $3",
-       "svg-long-error": "Fichiér SVG envalido : $1",
+       "file-nohires": "Niona rèsolucion ples hôta disponibla.",
+       "svg-long-desc": "Fichiér SVG, nominalament $1 × $2 pixèls, talye du fichiér : $3",
+       "svg-long-desc-animated": "Fichiér SVG animâ, nominalament $1 × $2 pixèls, talye du fichiér : $3",
+       "svg-long-error": "Fichiér SVG pas justo : $1",
        "show-big-image": "Fichiér d’origina",
-       "show-big-image-preview": "Talye de ceti apèrçu : $1.",
+       "show-big-image-preview": "Talye de cél apèrçu : $1.",
+       "show-big-image-preview-differ": "Talye de cél apèrçu $3 du fichiér $2 : $1.",
        "show-big-image-other": "{{PLURAL:$2|Ôtra rèsolucion|Ôtres rèsolucions}} : $1.",
        "show-big-image-size": "$1 × $2 pixèls",
        "file-info-gif-looped": "en boclla",
        "file-info-png-looped": "en boclla",
        "file-info-png-repeat": "jouyê $1 côp{{PLURAL:$1||s}}",
        "file-info-png-frames": "$1 émâge{{PLURAL:$1||s}}",
-       "newimages": "Galerie des novéls fichiérs",
-       "imagelisttext": "Vê-que una lista de '''$1''' {{PLURAL:$1|fichiér rengiê|fichiérs rengiês}} $2.",
-       "newimages-summary": "Ceta pâge spèciâla montre los dèrriérs fichiérs tèlèchargiês.",
-       "newimages-legend": "Nom du fichiér",
-       "newimages-label": "Nom du fichiér (ou ben una partia de ceti) :",
-       "noimages": "Gins de fichiér a fâre vêre.",
+       "file-no-thumb-animation": "<strong>Nota : a côsa de limitacions tècniques, les miniatures de cél fichiér seront pas animâyes.</strong>",
+       "file-no-thumb-animation-gif": "<strong>Nota : a côsa de limitacions tècniques, les miniatures d’émâges GIF en hôta rèsolucion coment ceta seront pas animâyes.</strong>",
+       "newimages": "Galeria des novéls fichiérs",
+       "imagelisttext": "Vê-que na lista de <strong>$1</strong> {{PLURAL:$1|fichiér rengiê|fichiérs rengiês}} $2.",
+       "newimages-summary": "Cela pâge spèciâla montre los dèrriérs fichiérs tèlèchargiês.",
+       "newimages-legend": "Filtro",
+       "newimages-label": "Nom du fichiér (ou ben na partia de ceti) :",
+       "newimages-showbots": "Montrar los tèlèchargements per los robots",
+       "newimages-hidepatrolled": "Cachiér los tèlèchargements gouardâs",
+       "noimages": "Ren a fâre vêre.",
        "ilsubmit": "Rechèrchiér",
        "bydate": "per dâta",
        "sp-newimages-showfrom": "Montrar los novéls fichiérs dês lo $1 a $2",
        "minutes": "$1 menut{{PLURAL:$1|a|es}}",
        "hours": "$1 hor{{PLURAL:$1|a|es}}",
        "days": "$1 jorn{{PLURAL:$1||s}}",
+       "weeks": "$1 seman{{PLURAL:$1|a|es}}",
+       "months": "{{PLURAL:$1|$1 mês}}",
+       "years": "$1 an{{PLURAL:$1||s}}",
        "ago": "cen fât $1",
        "just-now": "drêt-ora",
-       "bad_image_list": "Lo format est ceti :\n\nSolament les listes d’ènumèracion (que començont per *) sont considèrâs.\nLo premiér lim d’una legne dêt étre vers celi d’una crouye émâge.\nLos ôtros lims sur la méma legne sont considèrâs coment des èxcèpcions, per ègzemplo des pâges sur lesquintes l’émâge pôt aparêtre.",
+       "hours-ago": "cen fât $1 hor{{PLURAL:$1|a|es}}",
+       "minutes-ago": "cen fât $1 menut{{PLURAL:$1|a|es}}",
+       "seconds-ago": "cen fât $1 second{{PLURAL:$1|a|es}}",
+       "monday-at": "Delon a $1",
+       "tuesday-at": "Demârs a $1",
+       "wednesday-at": "Demécro a $1",
+       "thursday-at": "Dejô a $1",
+       "friday-at": "Devendro a $1",
+       "saturday-at": "Dessando a $1",
+       "sunday-at": "Demenge a $1",
+       "yesterday-at": "Hièr a $1",
+       "bad_image_list": "Lo format est ceti :\n\nSolament les piéces de lista (les legnes que començont per *) sont considèrâyes.\nLo premiér lim d’una legne dêt étre celi d’un crouyo fichiér.\nLos ôtros lims sur la méma legne sont considèrâs coment d’èxcèpcions, per ègzemplo des pâges que lo fichiér pôt aparêtre dessus.",
        "metadata": "Mètabalyês",
-       "metadata-help": "Ceti fichiér contint des enformacions de ples, probâblament apondues per l’aparèly-fotô numerico ou ben lo scanor utilisâ por lo fâre.\nSe lo fichiér at étâ changiê dês son ètat originâl, quârques dètalys pôvont pas reflètar a chavon l’émâge changiê.",
-       "metadata-expand": "Montrar los dètalys ètendus",
-       "metadata-collapse": "Cachiér los dètalys ètendus",
-       "metadata-fields": "Los champs de mètabalyês d’émâge listâs dens cél mèssâjo seront betâs dedens la pâge de dèscripcion de l’émâge quand la trâbla de mètabalyês serat rèduita.\nLos ôtros champs seront cachiês per dèfôt.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
+       "metadata-help": "Cél fichiér contint d’enformacions de més, probâblament apondues per l’aparèly-fotô numerico lo scanor empleyê por lo fâre numerisar.\nSe lo fichiér est étâ changiê dês son ètat originâl, quârques dètalys pôvont pas remandar a chavon lo fichiér changiê.",
+       "metadata-expand": "Montrar los dètalys de més",
+       "metadata-collapse": "Cachiér los dètalys de més",
+       "metadata-fields": "Los champs de mètabalyês d’émâge listâs dens cél mèssâjo seront rapondus dedens la pâge de dèscripcion de l’émâge quand la trâbla de mètabalyês serat rèduita.\nLos ôtros champs seront cachiês per dèfôt.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "metadata-langitem": "'''$2 :''' $1",
        "exif-imagewidth": "Largior",
        "exif-imagelength": "Hôtior",
        "exif-samplesperpixel": "Nombro de composentes",
        "exif-planarconfiguration": "Arrengement de les balyês",
        "exif-ycbcrsubsampling": "Quota de sot-èchantelyonâjo de Y a C",
-       "exif-ycbcrpositioning": "Posicionement Y et C",
+       "exif-ycbcrpositioning": "Posicionament Y et C",
        "exif-xresolution": "Rèsolucion plana",
        "exif-yresolution": "Rèsolucion drêta",
-       "exif-stripoffsets": "Emplacement de les balyês de l’émâge",
+       "exif-stripoffsets": "Endrêt de les balyês de l’émâge",
        "exif-rowsperstrip": "Nombro de legnes per benda",
-       "exif-stripbytecounts": "Talye en octèts per benda",
+       "exif-stripbytecounts": "Octèts per benda comprimâye",
        "exif-jpeginterchangeformat": "Posicion du SOI JPEG",
-       "exif-jpeginterchangeformatlength": "Talye en octèts de les balyês JPEG",
+       "exif-jpeginterchangeformatlength": "Octèts de les balyês JPEG",
        "exif-whitepoint": "Cromaticitât du pouent blanc",
        "exif-primarychromaticities": "Cromaticitât de les colors primères",
        "exif-ycbcrcoefficients": "Factors de la matrice de transformacion de l’èspâço colorimètrico",
-       "exif-referenceblackwhite": "Valors de refèrence nêr et blanc",
+       "exif-referenceblackwhite": "Cobla de valors de rèference nêr et blanc",
        "exif-datetime": "Dâta et hora de changement du fichiér",
        "exif-imagedescription": "Titro de l’émâge",
        "exif-make": "Fabrecant de l’aparèly-fotô",
        "exif-model": "Modèlo de l’aparèly-fotô",
-       "exif-software": "Programeria utilisâ",
+       "exif-software": "Programeria empleyêe",
        "exif-artist": "Ôtor",
-       "exif-copyright": "Dètentor du drêt d’ôtor",
+       "exif-copyright": "Dètentior des drêts d’ôtor",
        "exif-exifversion": "Vèrsion Exif",
-       "exif-flashpixversion": "Vèrsion FlashPix recognua",
+       "exif-flashpixversion": "Vèrsion Flashpix recognua",
        "exif-colorspace": "Èspâço colorimètrico",
        "exif-componentsconfiguration": "Significacion de châque composenta",
        "exif-compressedbitsperpixel": "Fôrma de comprèssion de l’émâge",
        "exif-pixelydimension": "Largior de l’émâge",
        "exif-pixelxdimension": "Hôtior de l’émâge",
-       "exif-usercomment": "Comentèros a l’usanciér",
+       "exif-usercomment": "Comentèros de l’utilisator",
        "exif-relatedsoundfile": "Fichiér ôdiô associyê",
-       "exif-datetimeoriginal": "Dâta et hora de la g·ènèracion de les balyês",
+       "exif-datetimeoriginal": "Dâta et hora de la prêsa originâla",
        "exif-datetimedigitized": "Dâta et hora de la numerisacion",
-       "exif-subsectime": "Dâta et hora en fraccions de secondes de changement du fichiér",
-       "exif-subsectimeoriginal": "Dâta et hora en fraccions de secondes de la g·ènèracion de les balyês",
-       "exif-subsectimedigitized": "Dâta et hora en fraccions de secondes de la numerisacion",
+       "exif-subsectime": "Dâta et hora en fraccions de seconda",
+       "exif-subsectimeoriginal": "Dâta et hora de la prêsa originâla en fraccions de seconda",
+       "exif-subsectimedigitized": "Dâta et hora de la numerisacion en fraccions de seconda",
        "exif-exposuretime": "Temps d’èxposicion",
-       "exif-exposuretime-format": "$1 s ($2)",
-       "exif-fnumber": "Nombro f",
+       "exif-exposuretime-format": "$1 s ($2 s)",
+       "exif-fnumber": "Uvèrtura",
        "exif-exposureprogram": "Programo d’èxposicion",
        "exif-spectralsensitivity": "Sensibilitât spèctrâla",
        "exif-isospeedratings": "Sensibilitât ISO",
        "exif-shutterspeedvalue": "Vitèsse d’ètopâ de l’APEX",
        "exif-aperturevalue": "Uvèrtura de l’APEX",
-       "exif-brightnessvalue": "Luminance APEX",
-       "exif-exposurebiasvalue": "Corrèccion d’èxposicion",
-       "exif-maxaperturevalue": "Uvèrtura la ples granta",
-       "exif-subjectdistance": "Distance du sujèt",
+       "exif-brightnessvalue": "Brilyent de l’APEX",
+       "exif-exposurebiasvalue": "Corrèccion d’èxposicion de l’APEX",
+       "exif-maxaperturevalue": "Uvèrtura maximon",
+       "exif-subjectdistance": "Distance de la chousa",
        "exif-meteringmode": "Fôrma de mesera",
        "exif-lightsource": "Sôrsa de lumiére",
        "exif-flash": "Èludo",
        "exif-focallength": "Longior focâla",
-       "exif-subjectarea": "Emplacement du sujèt",
-       "exif-flashenergy": "Nèrf de l’èludo",
+       "exif-subjectarea": "Sôl de la chousa",
+       "exif-flashenergy": "Ènèrg·ia de l’èludo",
        "exif-focalplanexresolution": "Rèsolucion plana de la vision focâla",
        "exif-focalplaneyresolution": "Rèsolucion drêta de la vision focâla",
        "exif-focalplaneresolutionunit": "Unitât de rèsolucion de la vision focâla",
-       "exif-subjectlocation": "Posicion du sujèt",
-       "exif-exposureindex": "Endèxe d’èxposicion",
+       "exif-subjectlocation": "Endrêt de la chousa",
+       "exif-exposureindex": "Endèx d’èxposicion",
        "exif-sensingmethod": "Tipo de captior",
        "exif-filesource": "Sôrsa du fichiér",
        "exif-scenetype": "Tipo de scèna",
        "exif-customrendered": "Rendu d’émâge pèrsonalisâ",
        "exif-exposuremode": "Fôrma d’èxposicion",
        "exif-whitebalance": "Balance des blancs",
-       "exif-digitalzoomratio": "Quota d’agrantissement numerico (''zoom'')",
-       "exif-focallengthin35mmfilm": "Longior focâla por un filme 35 mm",
-       "exif-scenecapturetype": "Tipo de prêsa de la scèna",
-       "exif-gaincontrol": "Contrôlo de scèna",
-       "exif-contrast": "Contraste",
+       "exif-digitalzoomratio": "Quota d’agrantissement numerico (<em>zoom</em>)",
+       "exif-focallengthin35mmfilm": "Longior focâla por un filmo 35 mm",
+       "exif-scenecapturetype": "Tipo de captura de la scèna",
+       "exif-gaincontrol": "Contrôlo de la scèna",
+       "exif-contrast": "Contrasto",
        "exif-saturation": "Saturacion",
-       "exif-sharpness": "Prècision",
+       "exif-sharpness": "Nètetât",
        "exif-devicesettingdescription": "Dèscripcion de la configuracion du dispositif",
-       "exif-subjectdistancerange": "Distance du sujèt",
-       "exif-imageuniqueid": "Numerô solèt de l’émâge",
+       "exif-subjectdistancerange": "Èchiéla de distance de la chousa",
+       "exif-imageuniqueid": "Identifient solèt de l’émâge",
        "exif-gpsversionid": "Vèrsion de la balisa GPS",
-       "exif-gpslatituderef": "Latituda bise (''nord'') ou mié-jorn (''sud'')",
+       "exif-gpslatituderef": "Latituda bise (<em>nord</em>) ou ben mié-jorn (<em>sud</em>)",
        "exif-gpslatitude": "Latituda",
-       "exif-gpslongituderef": "Longituda levant (''èst'') ou ponant (''ouèst'')",
+       "exif-gpslongituderef": "Longituda levant (<em>èste</em>) ou ben cuchient (<em>ouèste</em>)",
        "exif-gpslongitude": "Longituda",
-       "exif-gpsaltituderef": "Refèrence d’hôtior",
+       "exif-gpsaltituderef": "Rèference d’hôtior",
        "exif-gpsaltitude": "Hôtior",
        "exif-gpstimestamp": "Hora GPS (relojo atomico)",
-       "exif-gpssatellites": "Satèlites utilisâs por la mesera",
+       "exif-gpssatellites": "Satèlitos empleyês por la mesera",
        "exif-gpsstatus": "Ètat du recevior",
        "exif-gpsmeasuremode": "Fôrma de mesera",
        "exif-gpsdop": "Prècision de la mesera",
-       "exif-gpsspeedref": "Unitât de vitèsse du recevior GPS",
+       "exif-gpsspeedref": "Unitât de vitèsse",
        "exif-gpsspeed": "Vitèsse du recevior GPS",
-       "exif-gpstrackref": "Refèrence por la dirèccion du mouvement",
+       "exif-gpstrackref": "Rèference por la dirèccion du mouvement",
        "exif-gpstrack": "Dirèccion du mouvement",
-       "exif-gpsimgdirectionref": "Refèrence por la dirèccion de l’émâge",
+       "exif-gpsimgdirectionref": "Rèference por la dirèccion de l’émâge",
        "exif-gpsimgdirection": "Dirèccion de l’émâge",
-       "exif-gpsmapdatum": "Sistèmo g·eodèsico utilisâ",
-       "exif-gpsdestlatituderef": "Refèrence por la latituda de la dèstinacion",
+       "exif-gpsmapdatum": "Balyês de sondâjo g·eodèsico empleyêes",
+       "exif-gpsdestlatituderef": "Rèference por la latituda de la dèstinacion",
        "exif-gpsdestlatitude": "Latituda de la dèstinacion",
-       "exif-gpsdestlongituderef": "Refèrence por la longituda de la dèstinacion",
+       "exif-gpsdestlongituderef": "Rèference por la longituda de la dèstinacion",
        "exif-gpsdestlongitude": "Longituda de la dèstinacion",
-       "exif-gpsdestbearingref": "Refèrence por lo relèvament de la dèstinacion",
+       "exif-gpsdestbearingref": "Rèference por lo relèvament de la dèstinacion",
        "exif-gpsdestbearing": "Relèvament de la dèstinacion",
-       "exif-gpsdestdistanceref": "Refèrence por la distance a la dèstinacion",
+       "exif-gpsdestdistanceref": "Rèference por la distance a la dèstinacion",
        "exif-gpsdestdistance": "Distance a la dèstinacion",
-       "exif-gpsprocessingmethod": "Nom du tipo de trètament du GPS",
-       "exif-gpsareainformation": "Nom de la zona GPS",
+       "exif-gpsprocessingmethod": "Nom de la mètoda de trètament du GPS",
+       "exif-gpsareainformation": "Nom du sôl GPS",
        "exif-gpsdatestamp": "Dâta GPS",
        "exif-gpsdifferential": "Corrèccion difèrencièla GPS",
        "exif-jpegfilecomment": "Comentèro de fichiér JPEG",
        "exif-keywords": "Mots-cllâfs",
-       "exif-worldregioncreated": "Règ·ion du mondo que la fotô at étâ prêsa",
-       "exif-countrycreated": "Payis que la fotô at étâ prêsa",
-       "exif-countrycodecreated": "Code du payis que la fotô at étâ prêsa",
-       "exif-provinceorstatecreated": "Province ou ben ètat que la fotô at étâ prêsa",
-       "exif-citycreated": "Vela que la fotô at étâ prêsa",
-       "exif-sublocationcreated": "Partia de la vela que la fotô at étâ prêsa",
-       "exif-worldregiondest": "Règ·ion du mondo montrâ",
+       "exif-worldregioncreated": "Règ·ion du mondo yô que la fotô est étâye prêsa",
+       "exif-countrycreated": "Payis yô que la fotô est étâye prêsa",
+       "exif-countrycodecreated": "Code du payis yô que la fotô est étâye prêsa",
+       "exif-provinceorstatecreated": "Province Ètat yô que la fotô est étâye prêsa",
+       "exif-citycreated": "Vela yô que la fotô est étâye prêsa",
+       "exif-sublocationcreated": "Partia de la vela yô que la fotô est étâye prêsa",
+       "exif-worldregiondest": "Règ·ion du mondo montrâye",
        "exif-countrydest": "Payis montrâ",
        "exif-countrycodedest": "Code du payis montrâ",
-       "exif-provinceorstatedest": "Province ou ben ètat montrâ",
-       "exif-citydest": "Vela montrâ",
-       "exif-sublocationdest": "Partia de la vela montrâ",
+       "exif-provinceorstatedest": "Province Ètat montrâ(ye)",
+       "exif-citydest": "Vela montrâye",
+       "exif-sublocationdest": "Partia de la vela montrâye",
        "exif-objectname": "Titro côrt",
        "exif-specialinstructions": "Enstruccions spèciâles",
        "exif-headline": "Titro",
        "exif-credit": "Crèdit / fornissor",
        "exif-source": "Sôrsa",
        "exif-editstatus": "Statut èditoriâl de l’émâge",
-       "exif-urgency": "Urgence",
-       "exif-fixtureidentifier": "Nom de l’outil",
+       "exif-urgency": "Prèssa",
+       "exif-fixtureidentifier": "Nom de la colona",
        "exif-locationdest": "Endrêt fotografiâ",
        "exif-locationdestcode": "Code de l’endrêt fotografiâ",
-       "exif-objectcycle": "Moment de la jornâ que ceti mèdia est dèstinâ",
-       "exif-contact": "Enformacions de contacte",
+       "exif-objectcycle": "Temps de la jornâ que cél mèdiâ y est dèstinâ",
+       "exif-contact": "Enformacions de contacto",
        "exif-writer": "Ôtor",
        "exif-languagecode": "Lengoua",
        "exif-iimversion": "Vèrsion IIM",
-       "exif-iimcategory": "Catègorie",
-       "exif-iimsupplementalcategory": "Catègories de ples",
-       "exif-datetimeexpires": "Pas utilisar aprés",
+       "exif-iimcategory": "Catègoria",
+       "exif-iimsupplementalcategory": "Catègories de s",
+       "exif-datetimeexpires": "Pas empleyér aprés",
        "exif-datetimereleased": "Paru lo",
-       "exif-originaltransmissionref": "Code de l’endrêt de la transmission originâla",
-       "exif-identifier": "Numerô",
-       "exif-lens": "Lentelye utilisâ",
+       "exif-originaltransmissionref": "Code d’endrêt de la transmission originâla",
+       "exif-identifier": "Identifient",
+       "exif-lens": "Lentelye empleyêe",
        "exif-serialnumber": "Numerô de sèria de l’aparèly-fotô",
        "exif-cameraownername": "Propriètèro de l’aparèly-fotô",
        "exif-label": "Lambél",
        "exif-datetimemetadata": "Dâta du dèrriér changement de les mètabalyês",
-       "exif-nickname": "Nom enformèl de l’émâge",
+       "exif-nickname": "Nom famelyér de l’émâge",
        "exif-rating": "Nota (sur 5)",
-       "exif-rightscertificate": "Cèrtificat d’administracion des drêts",
+       "exif-rightscertificate": "Cèrtificat de maneyance des drêts",
        "exif-copyrighted": "Statut des drêts d’ôtor",
-       "exif-copyrightowner": "Propriètèro du drêt d’ôtor",
+       "exif-copyrightowner": "Dètentior des drêts d’ôtor",
        "exif-usageterms": "Condicions d’usâjo",
-       "exif-webstatement": "Dècllaracion des drêts d’ôtor en legne",
-       "exif-originaldocumentid": "Numerô solèt du document originâl",
-       "exif-licenseurl": "URL de la licence",
+       "exif-webstatement": "Dècllaracion de drêts d’ôtor en legne",
+       "exif-originaldocumentid": "Identifient solèt du document originâl",
+       "exif-licenseurl": "URL de la licence des drêts d’ôtor",
        "exif-morepermissionsurl": "Enformacions sur les licences altèrnatives",
-       "exif-attributionurl": "Pendent lo reusâjo de cela ôvra, volyéd liyér a",
-       "exif-preferredattributionname": "Pendent lo reusâjo de cela ôvra, volyéd crèditar",
+       "exif-attributionurl": "Pendent lo reusâjo de cel’ôvra, se vos plét liyéd a",
+       "exif-preferredattributionname": "Pendent lo reusâjo de cel’ôvra, se vos plét crèditâd",
        "exif-pngfilecomment": "Comentèro de fichiér PNG",
-       "exif-disclaimer": "Avèrtissement",
-       "exif-contentwarning": "Avèrtissement sur lo contegnu",
+       "exif-disclaimer": "Semonce de nan-rèsponsabilitât",
+       "exif-contentwarning": "Semonce sur lo contegnu",
        "exif-giffilecomment": "Comentèro de fichiér GIF",
-       "exif-intellectualgenre": "Tipo d’èlèment",
-       "exif-subjectnewscode": "Code du sujèt",
+       "exif-intellectualgenre": "Tipo de piéce",
+       "exif-subjectnewscode": "Code de la chousa",
        "exif-scenecode": "Code de scèna IPTC",
        "exif-event": "Èvènement fotografiâ",
-       "exif-organisationinimage": "Organisacion fotografiâ",
-       "exif-personinimage": "Pèrsona fotografiâ",
-       "exif-originalimageheight": "Hôtior de l’émâge devant qu’el èye étâ tornâ cadrar",
-       "exif-originalimagewidth": "Largior de l’émâge devant qu’el èye étâ tornâ cadrar",
-       "exif-compression-1": "Pas comprèssâ",
-       "exif-compression-2": "CCITT tropa 3 longior du codâjo Huffman changiê de dimension 1",
-       "exif-compression-3": "CCITT tropa 3 codâjo du faxe",
-       "exif-compression-4": "CCITT tropa 4 codâjo du faxe",
+       "exif-organisationinimage": "Organisacion fotografiâye",
+       "exif-personinimage": "Pèrsona fotografiâye",
+       "exif-originalimageheight": "Hôtior de l’émâge devant que seye étâye recadrâye",
+       "exif-originalimagewidth": "Largior de l’émâge devant que seye étâye recadrâye",
+       "exif-compression-1": "Pas damâ",
+       "exif-compression-2": "CCITT Groupo 3 Longior du codâjo Huffman changiê de dimension 1",
+       "exif-compression-3": "CCITT Groupo 3 codâjo du faxe",
+       "exif-compression-4": "CCITT Groupo 4 codâjo du faxe",
        "exif-compression-6": "JPEG (viely)",
-       "exif-copyrighted-true": "Somês a drêt d’ôtor",
-       "exif-copyrighted-false": "Domêno publico",
+       "exif-copyrighted-true": "Protègiê per los drêts d’ôtor",
+       "exif-copyrighted-false": "Ètat des drêts d’ôtor pas dèfeni",
+       "exif-photometricinterpretation-1": "Nêr et blanc (0 por lo nêr)",
        "exif-unknowndate": "Dâta encognua",
        "exif-orientation-1": "Normala",
-       "exif-orientation-2": "Envèrsâ d’aplan",
-       "exif-orientation-3": "Veriê de 180°",
-       "exif-orientation-4": "Envèrsâ d’aplomb",
-       "exif-orientation-5": "Veriê de 90° dens la dirèccion antihorèra et envèrsâ d’aplomb",
-       "exif-orientation-6": "Veriê de 90° dens la dirèccion antihorèra",
-       "exif-orientation-7": "Veriê de 90° dens la dirèccion horèra et envèrsâ d’aplomb",
-       "exif-orientation-8": "Veriê de 90° dens la dirèccion horèra",
-       "exif-planarconfiguration-1": "Balyês ategnentes",
-       "exif-planarconfiguration-2": "Balyês sèparâs",
+       "exif-orientation-2": "Envèrsâye d’aplan",
+       "exif-orientation-3": "Veriêe de 180°",
+       "exif-orientation-4": "Envèrsâye d’aplomb",
+       "exif-orientation-5": "Veriêe de 90° du fllanc antihorèro et envèrsâye d’aplomb",
+       "exif-orientation-6": "Veriêe de 90° du fllanc antihorèro",
+       "exif-orientation-7": "Veriêe de 90° du fllanc horèro et envèrsâye d’aplomb",
+       "exif-orientation-8": "Veriêe de 90° du fllanc horèro",
+       "exif-planarconfiguration-1": "format en bocons",
+       "exif-planarconfiguration-2": "format plan",
        "exif-colorspace-65535": "Pas calibrâ",
-       "exif-componentsconfiguration-0": "Ã\88gziste pas",
+       "exif-componentsconfiguration-0": "ègziste pas",
        "exif-componentsconfiguration-5": "V",
        "exif-exposureprogram-0": "Pas dèfeni",
-       "exif-exposureprogram-1": "Manuèl",
+       "exif-exposureprogram-1": "Manuâl",
        "exif-exposureprogram-2": "Programo normal",
        "exif-exposureprogram-3": "Prioritât a l’uvèrtura",
        "exif-exposureprogram-4": "Prioritât a l’ètopior",
        "exif-exposureprogram-5": "Programo crèacion (prèference a la provondior de champ)",
        "exif-exposureprogram-6": "Programo accion (prèference a la vitèsse d’ètopâ)",
-       "exif-exposureprogram-7": "Fôrma portrèt (por clich·ês de prés avouéc fond pas nèt)",
-       "exif-exposureprogram-8": "Fôrma payisâjo (por des clich·ês de payisâjos nèts)",
-       "exif-subjectdistance-value": "$1 mètre{{PLURAL:$1||s}}",
+       "exif-exposureprogram-7": "Fôrma portrèt (por visions de prés avouéc dèrriér troblo)",
+       "exif-exposureprogram-8": "Fôrma payisâjo (por visions de payisâjos avouéc dèrriér nèt)",
+       "exif-subjectdistance-value": "$1 mètro{{PLURAL:$1||s}}",
        "exif-meteringmode-0": "Encognua",
        "exif-meteringmode-1": "Moyena",
-       "exif-meteringmode-2": "Moyena èquilibrâ u centro",
+       "exif-meteringmode-2": "Moyena d’aplomb u centro",
        "exif-meteringmode-3": "Pouent",
        "exif-meteringmode-4": "MultiPouent",
        "exif-meteringmode-5": "Modèlo",
        "percent": "$1&#160;%",
        "imgmultipageprev": "← pâge devant",
        "imgmultipagenext": "pâge aprés →",
-       "imgmultigo": "Listar !",
+       "imgmultigo": "Emmodar !",
        "imgmultigoto": "Alar a la pâge $1",
+       "img-lang-go": "Emmodar",
        "ascending_abbrev": "que crêt",
        "descending_abbrev": "que dècrêt",
        "table_pager_next": "Pâge aprés",
        "table_pager_last": "Dèrriére pâge",
        "table_pager_limit": "Montrar $1 èlèment{{PLURAL:$1||s}} per pâge",
        "table_pager_limit_label": "Rèsultats per pâge :",
-       "table_pager_limit_submit": "Listar",
+       "table_pager_limit_submit": "Emmodar",
        "table_pager_empty": "Gins de rèsultat",
        "autosumm-blank": "Pâge blanchia",
        "autosumm-replace": "Contegnu remplaciê per « $1 »",
        "version-entrypoints": "URL de pouent d’entrâ",
        "version-entrypoints-header-entrypoint": "Pouent d’entrâ",
        "version-entrypoints-header-url": "URL",
+       "redirect-submit": "Emmodar",
        "fileduplicatesearch": "Rechèrche des fichiérs en doblo",
        "fileduplicatesearch-summary": "Rechèrche des fichiérs en doblo d’aprés lor mârca de chaplâjo.",
        "fileduplicatesearch-legend": "Rechèrche d’un doblo",
index 0306e65..e5b4171 100644 (file)
@@ -10,7 +10,8 @@
                        "아라",
                        "Purodha",
                        "Macofe",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Ferwisangen onerstrik:",
        "recentchangeslinked-page": "Sidjennööm:",
        "recentchangeslinked-to": "Wise feranrangen üüb sidjen, diar heerhen ferwise.",
        "recentchanges-page-added-to-category": "[[:$1]] tu kategorii saat",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] an {{PLURAL:$2|ian sidj muar|$2 muar sidjen}} tu kategorii saat",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] an [[Special:WhatLinksHere/$1|{{PLURAL:$2|ian sidj muar|$2 muar sidjen}}]] tu kategorii saat",
        "recentchanges-page-removed-from-category": "[[:$1]] faan't kategorii wechnimen",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] an {{PLURAL:$2|ian sidj muar|$2 muar sidjen}} faan det kategorii wechnimen",
        "upload": "Datei huuchschüür",
index 80329a0..36a2170 100644 (file)
@@ -15,7 +15,8 @@
                        "Robin0van0der0vliet",
                        "Macofe",
                        "Xð",
-                       "Robin van der Vliet"
+                       "Robin van der Vliet",
+                       "PiefPafPier"
                ]
        },
        "tog-underline": "Keppelings ûnderstreekje:",
        "nstab-template": "Berjocht",
        "nstab-help": "Helpside",
        "nstab-category": "Kategory",
+       "mainpage-nstab": "Haadside",
        "nosuchaction": "Unbekende aksje.",
        "nosuchactiontext": "De opdracht yn de URL is ûnjildich.\nMooglik hasto in typefout makke yn de URL of in ferkearde keppeling folge.\nIt soe likegoed in programmatuerflater fan {{SITENAME}} wêze kinne.",
        "nosuchspecialpage": "Unbekende side",
        "contributions": "{{GENDER:$1|Meidogger}}-bydragen",
        "contributions-title": "Bydragen fan $1",
        "mycontris": "Bydragen",
+       "anoncontribs": "Bydragen",
        "contribsub2": "Foar {{GENDER:$3|$1}} ($2)",
        "nocontribs": "Der binne gjin feroarings fûn dyt't hjirmei oerienkomme.",
        "uctop": "(lêste feroaring)",
        "tooltip-pt-preferences": "Myn foarkarynstellings",
        "tooltip-pt-watchlist": "List fan siden dy'sto besjochst op feroarings",
        "tooltip-pt-mycontris": "Oersjocht fan jo bydragen",
-       "tooltip-pt-login": "Jo wurde fan herten útnoege jo oan te melden, mar it hoecht net.",
+       "tooltip-pt-login": "Jo wurde fan herten útnûge jo oan te melden, mar it hoecht net.",
        "tooltip-pt-logout": "Ofmelde",
        "tooltip-ca-talk": "Oerlis oer dizze side",
        "tooltip-ca-edit": "Jo kinne dizze side bewurkje. Brûk a.j.w. de foarbyldwerjefteknop foar't Jo de boel bewarje.",
        "comparepages": "Siden ferlykje",
        "compare-page1": "Side 1",
        "compare-page2": "Side 2",
-       "compare-rev1": "Revyzje 1",
-       "compare-rev2": "Revyzje 2",
+       "compare-rev1": "Refyzje 1",
+       "compare-rev2": "Refyzje 2",
        "compare-submit": "Ferlykje",
        "compare-invalid-title": "Unjildige titel.",
        "htmlform-submit": "Ferstjoere",
        "duration-weeks": "$1 {{PLURAL:$1|wike|wiken}}",
        "duration-years": "$1 {{PLURAL:$1|jier|jierren}}",
        "duration-decades": "$1 {{PLURAL:$1|desennium|desennia}}",
-       "duration-centuries": "$1 {{PLURAL:$1|ieu|ieuwen}}",
+       "duration-centuries": "$1 {{PLURAL:$1|iuw|iuwen}}",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|sekonde|sekonden}}",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|sekonde|sekonden}}",
        "limitreport-ppvisitednodes-value": "$1/$2",
        "special-characters-group-arabic": "Arabysk",
        "special-characters-group-arabicextended": "Arabysk útwreide",
        "special-characters-group-persian": "Perzysk",
-       "special-characters-group-hebrew": "Hebrieusk",
+       "special-characters-group-hebrew": "Hebriuwsk",
        "special-characters-group-bangla": "Bengaalsk",
        "special-characters-group-tamil": "Tamyl",
        "special-characters-group-telugu": "Telugu",
index 0beaec8..170d19e 100644 (file)
@@ -19,7 +19,8 @@
                        "පසිඳු කාවින්ද",
                        "아라",
                        "SeoMac",
-                       "Macofe"
+                       "Macofe",
+                       "Tem"
                ]
        },
        "tog-underline": "Folínte faoi naisc:",
        "actions": "Gníomhartha",
        "namespaces": "Ainmspásanna",
        "variants": "Leaganacha Malartacha",
+       "navigation-heading": "Roghchlár nascleanúna",
        "errorpagetitle": "Earráid",
        "returnto": "Fill ar ais go $1.",
        "tagline": "Ó {{SITENAME}}.",
        "articlepage": "Féach ar an alt",
        "talk": "Plé",
        "views": "Radhairc",
-       "toolbox": "Bosca uirlisí",
+       "toolbox": "Uirlisí",
        "userpage": "Féach ar lch úsáideora",
        "projectpage": "Féach ar lch thionscadail",
        "imagepage": "Féach ar lch comhaid",
        "nstab-template": "Teimpléad",
        "nstab-help": "Cabhair",
        "nstab-category": "Catagóir",
+       "mainpage-nstab": "An príomhleathanach",
        "nosuchaction": "Níl a leithéid de ghníomh ann",
        "nosuchactiontext": "Níl aithníonn an vicí an gníomh atá ann san URL.\nAn ndearna tú botún san URL, no ar lean tú nasc mícheart?\nAn bhfuil fadhb sna bogearraí atá in usáid ar {{SITENAME}}?",
        "nosuchspecialpage": "Níl a leithéid de leathanach speisialta ann",
        "welcomecreation-msg": "Cruthaíodh do chuntas.",
        "yourname": "D'ainm úsáideora",
        "userlogin-yourname": "Ainm úsáideora",
+       "userlogin-yourname-ph": "Iontráil d'ainm úsáideora",
        "yourpassword": "D'fhocal faire",
+       "userlogin-yourpassword": "Pasfhocal",
+       "userlogin-yourpassword-ph": "Iontráil do phasfhocal",
+       "createacct-yourpassword-ph": "Iontráil pasfhocal",
        "yourpasswordagain": "Athiontráil d'fhocal faire",
+       "createacct-yourpasswordagain": "Deimhnigh an pasfhocal",
+       "createacct-yourpasswordagain-ph": "Iontráil an pasfhocal arís",
        "remembermypassword": "Cuimhnigh ar m'fhocal faire ar an ríomhaire seo (ar feadh uastréimhse de $1 {{PLURAL:$1|lá|lá}})",
+       "userlogin-remembermypassword": "Coinnigh logáilte isteach mé",
        "yourdomainname": "D'fhearann",
        "externaldberror": "Bhí earráid bhunachair sonraí ann maidir le fíordheimhniú seachtrach, nóThere was either an external authentication database error or you are not allowed to update your external account.",
        "login": "Logáil isteach",
        "logout": "Logáil amach",
        "userlogout": "Logáil amach",
        "notloggedin": "Níl tú logáilte isteach",
+       "userlogin-noaccount": "Níl cuntas agat?",
+       "userlogin-joinproject": "Cláraigh le {{SITENAME}}",
        "nologin": "Nach bhfuil logáil isteach agat? '''$1'''.",
        "nologinlink": "Cruthaigh cuntas",
        "createaccount": "Cruthaigh cuntas nua",
        "gotaccount": "An bhfuil cuntas agat cheana féin? '''$1'''.",
        "gotaccountlink": "Logáil isteach",
        "userlogin-resetlink": "Sonraí logála isteach dearmadta agat?",
+       "userlogin-resetpassword-link": "Pasfhocal dearmadta?",
+       "userlogin-helplink2": "Cabhair le logáil isteach",
        "createacct-emailrequired": "Seoladh ríomhphoist",
+       "createacct-emailoptional": "Seoladh ríomhphoist (roghnach)",
        "createacct-email-ph": "Iontráil do sheoladh ríomhphoist",
        "createacct-another-email-ph": "Iontráil seoladh ríomhphoist",
        "createaccountmail": "le ríomhphost",
        "createaccount-title": "Cuntas cruthú le {{SITENAME}}",
        "createaccount-text": "Chruthaigh duine éigin cuntas do do sheoladh ríomhphoist ar {{SITENAME}} ($4) leis an ainm \"$2\" agus pasfhocal \"$3\". Ba cheart duit logáil isteach agus do phasfhocal a athrú anois. Is féidir leat neamhaird a thabhairt don teachtaireacht seo má cruthaíodh trí earráid í.",
        "loginlanguagelabel": "Teanga: $1",
+       "pt-login": "Logáil isteach",
+       "pt-login-button": "Logáil isteach",
+       "pt-createaccount": "Cruthaigh cuntas",
+       "pt-userlogout": "Logáil amach",
        "php-mail-error-unknown": "Earráid anaithnid i bhfeidhm mail() de chuid PHP",
        "changepassword": "Athraigh d'fhocal faire",
        "resetpass_announce": "Tá tú logáilte isteach le cód sealadach a seoladh chugat i r-phost.\nChun d'iarratas logáil isteach a chríochnú, caithfidh tú focal faire nua a roghnú anseo:",
        "action-minoredit": "an athrú seo a mharcáil mar mionathrú",
        "action-upload": "uaslódáil an comhad",
        "nchanges": "{{PLURAL:$1|Athrú amháin|$1 athruithe}}",
+       "enhancedrc-history": "stair",
        "recentchanges": "Athruithe is déanaí",
        "recentchanges-legend": "Roghanna do na hathruithe is déanaí",
        "recentchanges-summary": "Déan faire ar na hathruithe is déanaí sa vicí ar an leathanach seo.",
        "recentchanges-feed-description": "Rianaigh na n-athruite vicí is déanaí sa fotha seo.",
+       "recentchanges-label-newpage": "Cruthaíodh lch nua leis an eagarthóireacht seo",
        "recentchanges-label-minor": "Mionathrú é seo",
        "recentchanges-label-bot": "Chomhlíon róbó an t-athrú seo",
+       "recentchanges-legend-heading": "<strong>Eochair:</strong>",
        "recentchanges-legend-newpage": "$1 - leathanach nua",
        "rcnotefrom": "Is iad seo a leanas na hathruithe ó <b>$2</b> (go dti <b>$1</b> taispeánaithe).",
        "rclistfrom": "Taispeáin athruithe nua ó $3 $2 anuas",
        "rcshowhideminor": "$1 mionathruithe",
+       "rcshowhideminor-show": "Taispeáin",
+       "rcshowhideminor-hide": "Folaigh",
        "rcshowhidebots": "$1 róbónna",
-       "rcshowhideliu": "$1 úsáideoirí atá logáilte isteach",
+       "rcshowhidebots-show": "Taispeáin",
+       "rcshowhidebots-hide": "Folaigh",
+       "rcshowhideliu": "$1 úsáideoir cláraithe",
+       "rcshowhideliu-hide": "Folaigh",
        "rcshowhideanons": "$1 úsáideoirí gan ainm",
+       "rcshowhideanons-show": "Taispeáin",
+       "rcshowhideanons-hide": "Folaigh",
        "rcshowhidepatr": "$1 athruithe faoi phatról",
        "rcshowhidemine": "$1 mo chuid athruithe",
+       "rcshowhidemine-show": "Taispeáin",
+       "rcshowhidemine-hide": "Folaigh",
        "rclinks": "Taispeáin an $1 athrú is déanaí sa $2 lá seo caite<br />$3",
        "diff": "difr",
        "hist": "stair",
        "boteditletter": "r",
        "number_of_watching_users_pageview": "[{{PLURAL:$1|úsáideoir amháin|$1 úsáideoirí}} ag faire]",
        "rc_categories_any": "Aon chatagóir",
+       "rc-change-size-new": "$1 {{PLURAL:$1|bheart|beart}} tar éis an athraithe",
        "newsectionsummary": "/* $1 */ mír nua",
        "rc-enhanced-expand": "Taispeáin mionsonraithe (JavaScript riachtanach)",
        "rc-enhanced-hide": "Folaigh shonraí",
        "pager-older-n": "{{PLURAL:$1|1 níos sine|$1 níos sine}}",
        "booksources": "Leabharfhoinsí",
        "booksources-search-legend": "Cuardaigh le foinsí leabhar",
+       "booksources-search": "Cuardaigh",
        "specialloguserlabel": "Úsáideoir:",
        "speciallogtitlelabel": "Teideal:",
        "log": "Logaí",
        "contributions": "Dréachtaí {{GENDER:$1|úsáideora}}",
        "contributions-title": "Dréachtaí úsáideora do $1",
        "mycontris": "Dréachtaí",
+       "anoncontribs": "Dréachtaí",
        "contribsub2": "Do $1 ($2)",
        "nocontribs": "Ní bhfuarthas aon athrú a bhí cosúil le na crítéir seo.",
        "uctop": " (barr)",
        "tooltip-pt-anonuserpage": "Leathanach úsáideora don IP ina dhéanann tú do chuid athruithe",
        "tooltip-pt-mytalk": "Do leathanach phlé",
        "tooltip-pt-anontalk": "Plé maidir le na hathruithe a dhéantar ón seoladh IP seo",
-       "tooltip-pt-preferences": "Mo chuid sainroghanna",
+       "tooltip-pt-preferences": "{{GENDER:|Do}}  chuid sainroghanna",
        "tooltip-pt-watchlist": "Liosta de na leathanaigh a bhfuil tú á bhfaire ar athruithe",
        "tooltip-pt-mycontris": "Liosta do chuid dréachtaí",
        "tooltip-pt-login": "Moltar duit logáil isteach, ach níl sé riachtanach.",
        "file-nohires": "Níl aon taifeach is mó ar fáil.",
        "svg-long-desc": "Comhad SVG, ainmniúil $1 × $2 picteilíni, méid comhaid: $3",
        "show-big-image": "Taispeáin leagan ardtaifigh den íomhá",
+       "show-big-image-size": "$1 × $2 picteilín",
        "newimages": "Gailearaí na n-íomhánna nua",
        "imagelisttext": "Tá liosta thíos de {{PLURAL:$1|comhad amháin|$1 comhaid $2}}.",
        "newimages-label": "Comhadainm (nó cuid de):",
        "specialpages-group-wiki": "Sonraí vicí agus uirslí",
        "specialpages-group-spam": "Uirlisí turscar",
        "blankpage": "Leathanach bán",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|chlib amháin|clib}}]]: $2)",
        "htmlform-selectorother-other": "Eile",
+       "logentry-move-move": "{{GENDER:$2|Bhog}} $1 an leathanach $3 go $4",
        "feedback-cancel": "Cealaigh",
        "feedback-message": "Teachtaireacht:",
        "searchsuggest-search": "Cuardaigh",
index 0c59e35..15e0175 100644 (file)
@@ -21,7 +21,8 @@
                        "Breogan2008",
                        "VaiPolaSombra",
                        "Macofe",
-                       "Banjo"
+                       "Banjo",
+                       "Josep Maria Roca Peña"
                ]
        },
        "tog-underline": "Subliñar as ligazóns:",
        "noemail": "O usuario \"$1\" non posúe ningún enderezo de correo electrónico rexistrado.",
        "noemailcreate": "Ten que proporcionar un enderezo de correo electrónico válido",
        "passwordsent": "Enviouse un contrasinal novo ao enderezo de correo electrónico rexistrado de \"$1\".\nPor favor, acceda ao sistema de novo tras recibilo.",
-       "blocked-mailpassword": "O seu enderezo IP está bloqueado e ten restrinxida a edición de artigos. Tampouco se lle permite usar a función de recuperación do contrasinal para evitar abusos do sistema.",
+       "blocked-mailpassword": "O seu enderezo IP está bloqueado para editar. Tampouco se lle permite usar a función de recuperación do contrasinal para evitar abusos do sistema.",
        "eauthentsent": "Envióuselle un correo electrónico de confirmación ao enderezo especificado.\nAntes de que se lle envíe calquera outro correo a esta conta terá que seguir as instrucións que aparecen nesa mensaxe para confirmar que a conta é realmente súa.",
        "throttled-mailpassword": "Enviouse un correo electrónico de restablecemento do contrasinal {{PLURAL:$1|na última hora|nas últimas $1 horas}}.\nPara evitar o abuso do sistema só se enviará unha mensaxe de restablecemento cada {{PLURAL:$1|hora|$1 horas}}.",
        "mailerror": "Produciuse un erro ao enviar o correo electrónico: $1",
        "botpasswords-insert-failed": "Erro ao engadir o nome de bot \"$1\". Revise se xa foi engadido previamente.",
        "botpasswords-update-failed": "Erro ao actualizar o nome de bot \"$1\". Revise se foi borrado.",
        "botpasswords-created-title": "Contrasinal de bot creado",
-       "botpasswords-created-body": "Creouse o contrasinal de bot \"$1\".",
+       "botpasswords-created-body": "Creouse o contrasinal para o bot de nome \"$1\" do usuario \"$2\".",
        "botpasswords-updated-title": "Contrasinal de bot actualizado",
-       "botpasswords-updated-body": "O contrasinal de bot \"$1\" foi actualizado.",
+       "botpasswords-updated-body": "O contrasinal de bot do bot de nome \"$1\" do usuario \"$2\" foi actualizado.",
        "botpasswords-deleted-title": "Contrasinal de bot borrado",
-       "botpasswords-deleted-body": "O contrasinal de bot \"$1\" foi borrado.",
+       "botpasswords-deleted-body": "O contrasinal de bot do bot de nome \"$1\" do usuario \"$2\" foi borrado.",
        "botpasswords-newpassword": "O novo contrasinal para acceder con strong>$1</strong> é <strong>$2</strong>. <em>Por favor, rexistra isto para referencia futura.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider non está dispoñible.",
        "botpasswords-restriction-failed": "Restricións de contrasinal de bots evitaron esta conexión.",
        "recentchangeslinked-page": "Nome da páxina:",
        "recentchangeslinked-to": "Mostrar os cambios relacionados das páxinas que ligan coa dada",
        "recentchanges-page-added-to-category": "\"[[:$1]]\" engadiuse á categoría",
-       "recentchanges-page-added-to-category-bundled": "\"[[:$1]]\" e {{PLURAL:$2|unha páxina|$2 páxinas}} engadíronse á categoría",
+       "recentchanges-page-added-to-category-bundled": "\"[[:$1]]\" e [[Special:WhatLinksHere/$1|{{PLURAL:$2|unha páxina|$2 páxinas}}]] engadíronse á categoría",
        "recentchanges-page-removed-from-category": "\"[[:$1]]\" eliminouse da categoría",
-       "recentchanges-page-removed-from-category-bundled": "\"[[:$1]]\" e {{PLURAL:$2|unha páxina|$2 páxinas}} elimináronse da categoría",
+       "recentchanges-page-removed-from-category-bundled": "\"[[:$1]]\" e [[Special:WhatLinksHere/$1|{{PLURAL:$2|unha páxina|$2 páxinas}}]] elimináronse da categoría",
        "autochange-username": "Cambio automático de MediaWiki",
        "upload": "Subir un ficheiro",
        "uploadbtn": "Subir un ficheiro",
        "uploadstash-badtoken": "A acción fallou, probablemente porque caducou a información de acceso. Por favor, inténteo de novo.",
        "uploadstash-errclear": "Fallou o borrado de ficheiros.",
        "uploadstash-refresh": "Actualizar a lista de ficheiros",
+       "uploadstash-thumbnail": "ver miniatura",
        "invalid-chunk-offset": "Desprazamento inválido do fragmento",
        "img-auth-accessdenied": "Acceso rexeitado",
        "img-auth-nopathinfo": "Falta a PATH_INFO.\nO seu servidor non está configurado para pasar esta información.\nPode ser que estea baseado en CGI e non soporte img_auth.\nVéxase https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "checkbox-select": "Seleccionar: $1",
        "checkbox-all": "Todos",
        "checkbox-none": "Ningún",
-       "checkbox-invert": "Invertir",
+       "checkbox-invert": "Inverter",
        "allpages": "Todas as páxinas",
        "nextpage": "Páxina seguinte ($1)",
        "prevpage": "Páxina anterior ($1)",
        "changecontentmodel-title-label": "Título da páxina",
        "changecontentmodel-model-label": "Novo modelo de contido",
        "changecontentmodel-reason-label": "Motivo:",
+       "changecontentmodel-submit": "Cambiar",
        "changecontentmodel-success-title": "O modelo de contido foi modificado",
        "changecontentmodel-success-text": "O tipo de contido de [[:$1]] foi modificado.",
        "changecontentmodel-cannot-convert": "O contido en [[:$1]] non pode converterse ó tipo de $2.",
        "changecontentmodel-nodirectediting": "O modelo de contido $1 non permite a modificación directa",
        "log-name-contentmodel": "Rexistro de cambios de modelo de contido",
        "log-description-contentmodel": "Eventos relacinados cos modelos de contido dunha páxina",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|creou}} a páxina $3 usando un modelo de contido non predeterminado \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|cambiou}} o modelo de contido da páxina $3 de \"$4\" a \"$5\"",
        "logentry-contentmodel-change-revertlink": "reverter",
        "logentry-contentmodel-change-revert": "reverter",
        "ipb-unblock": "Desbloquear un usuario ou enderezo IP",
        "ipb-blocklist": "Ver os bloqueos vixentes",
        "ipb-blocklist-contribs": "Contribucións de {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 restantes",
        "unblockip": "Desbloquear un usuario",
        "unblockiptext": "Use o seguinte formulario para dar de novo acceso de escritura a un enderezo IP ou usuario que estea bloqueado.",
        "ipusubmit": "Retirar o bloqueo",
        "import-logentry-upload-detail": "{{PLURAL:$1|Importouse $1 revisión|Importáronse $1 revisións}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|Importouse $1 revisión|Importáronse $1 revisións}} desde $2",
        "javascripttest": "Proba de JavaScript",
-       "javascripttest-pagetext-noframework": "Esta páxina está reservada para executar probas do JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Descoñécese a infraestrutura dixital \"$1\" de probas.",
        "javascripttest-pagetext-unknownaction": "Acción descoñecida \"$1\".",
-       "javascripttest-pagetext-frameworks": "Seleccione unha das seguintes infraestruturas dixitais de probas: $1",
-       "javascripttest-pagetext-skins": "Escolla a aparencia na que executar as probas:",
        "javascripttest-qunit-intro": "Bótelle unha ollada á [$1 documentación das probas] en mediawiki.org.",
        "tooltip-pt-userpage": "A súa páxina de {{GENDER:|usuario|usuaria}}",
        "tooltip-pt-anonuserpage": "A páxina de usuario do enderezo IP desde o que está a editar",
        "version-libraries-description": "Descrición",
        "version-libraries-authors": "Autores",
        "redirect": "Redirixir por nome de ficheiro, usuario, páxina, modificación ou identificador de rexistro",
-       "redirect-legend": "Redirixir a un ficheiro ou unha páxina",
        "redirect-summary": "Esta páxina especial redirixe cara a un ficheiro (dado o nome), unha páxina (dado o ID da páxina ou o dunha revisión) ou unha páxina de usuario (dado o ID dun usuario), ou unha entrada do rexistro (dada polo ID do rexistro). Utilización: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] ou [[{{#Special:Redirect}}/user/101]], ou [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Continuar",
        "redirect-lookup": "Procurar:",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|protexeu}} a $3 $4 [en cascada]",
        "logentry-protect-modify": "$1 {{GENDER:$2|cambiou}} o nivel de protección de $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|cambiou}} o nivel de protección de $3 $4 [en cascada]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|cambiou}} o grupo ao que pertence $3 de $4 a $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|cambiou}} o grupo ao que pertence {{GENDER:$3|$3}} de $4 a $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|cambiou}} o grupo ao que pertence $3",
        "logentry-rights-autopromote": "$1 foi {{GENDER:$2|promovido|promovida}} automaticamente de $4 a $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|cargou}} \"$3\"",
        "api-error-unknownerror": "Erro descoñecido: \"$1\".",
        "api-error-uploaddisabled": "As cargas están desactivadas neste wiki.",
        "api-error-verification-error": "Este ficheiro podería estar corrupto ou ter unha extensión incorrecta.",
+       "api-error-was-deleted": "Un ficheiro con este mesmo nome xa foi cargado con anterioridade e posteriormente eliminado.",
        "duration-seconds": "$1 {{PLURAL:$1|segundo|segundos}}",
        "duration-minutes": "$1 {{PLURAL:$1|minuto|minutos}}",
        "duration-hours": "$1 {{PLURAL:$1|hora|horas}}",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "Símbolos",
        "special-characters-group-greek": "Grego",
+       "special-characters-group-greekextended": "Grego estendido",
        "special-characters-group-cyrillic": "Cirílico",
        "special-characters-group-arabic": "Árabe",
        "special-characters-group-arabicextended": "Árabe estendido",
        "sessionprovider-generic": "sesións $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesións baseadas nas cookies",
        "sessionprovider-nocookies": "As cookies poden estar desactivadas. Asegúrese de que ten activas as cookies e comece de novo.",
-       "randomrootpage": "Páxina raíz ao chou"
+       "randomrootpage": "Páxina raíz ao chou",
+       "log-action-filter-block": "Tipo de bloqueo:",
+       "log-action-filter-delete": "Tipo de borrado:",
+       "log-action-filter-patrol": "Tipo de vixilancia:",
+       "log-action-filter-protect": "Tipo de protección:",
+       "log-action-filter-upload": "Tipo de subida:",
+       "log-action-filter-all": "Todas",
+       "log-action-filter-block-block": "Bloquear",
+       "log-action-filter-block-reblock": "Modificación de bloqueo",
+       "log-action-filter-block-unblock": "Desbloquear",
+       "log-action-filter-delete-delete": "Borrado de páxinas",
+       "log-action-filter-delete-restore": "Restauración de páxinas",
+       "log-action-filter-delete-event": "Borrado de rexistros",
+       "log-action-filter-delete-revision": "Borrado de revisión",
+       "log-action-filter-patrol-patrol": "Verificación manual",
+       "log-action-filter-patrol-autopatrol": "Verificación automática",
+       "log-action-filter-protect-protect": "Protección",
+       "log-action-filter-protect-modify": "Modificación de protección",
+       "log-action-filter-protect-unprotect": "Desproteccion",
+       "log-action-filter-upload-upload": "Nova subida",
+       "log-action-filter-upload-overwrite": "Resubida"
 }
index 5343a48..d2611fe 100644 (file)
        "sort-descending": "Devtea kromacher kromboddh kor",
        "sort-ascending": "Chodtea kromacher kromboddh kor",
        "nstab-main": "Pan",
-       "nstab-user": "Vapuddpeachem pan",
+       "nstab-user": "Vaporpeachem pan",
        "nstab-media": "Madheomachem pan",
        "nstab-special": "Vixex pan",
        "nstab-project": "Prokolpache pan",
        "badtitletext": "Tuven maglelem panache nanv chukichem, rintem, vo ek sarkem zodunk-naslelem bhase-modlem vo wiki-modlem nanv.\n\nTantun ek vo sabaar okxor asot jenka nanvanim uzar korunk zainan.",
        "viewsource": "Mull polloi",
        "welcomeuser": "Ievkar, $1!",
-       "yourname": "Vapuddpeachem nanv:",
+       "yourname": "Vaporpeachem nanv:",
        "userlogin-yourname": "Vangdiachem nanv",
        "userlogin-yourname-ph": "Tujem 'vangdeachem nanv' boroi",
        "createacct-another-username-ph": "Vapurpeachem nanv boroi",
        "rcshowhidebots": "$1 robot",
        "rcshowhidebots-show": "Dakhoi",
        "rcshowhidebots-hide": "Lipoi",
-       "rcshowhideliu": "$1 nond zalele vapuddpi",
+       "rcshowhideliu": "$1 nond zalele vaporpi",
        "rcshowhideliu-hide": "Lipoi",
        "rcshowhideanons": "$1 nanv-naslelim vapurpi",
        "rcshowhideanons-show": "Dakhoi",
        "linksearch-ok": "Sod",
        "linksearch-line": "$1 $2 savn zoddlelem asa",
        "listusers-submit": "Dakhoi",
-       "listgrouprights-members": "(vapuddpeanchi suchi)",
+       "listgrouprights-members": "(vaporpeanchi suchi)",
        "emailuser": "Email dhadd",
        "emailusername": "Vapurpeachem nanv:",
        "watchlist": "Sadurvolleri",
        "namespace_association": "Sombondhit nanvtholl",
        "tooltip-namespace_association": "Vinchlele nanvthollache sombondhit bhasabhas vo vixoiacho nanvthollakui gheupak hem boks khunnai",
        "blanknamespace": "(Mukhel)",
-       "contributions": "{{GENDER:$1|Vapuddpi}} yogdanam",
-       "contributions-title": "$1 hea vapuddpean kelelim yogdanam",
+       "contributions": "{{GENDER:$1|Vaporpi}} yogdanam",
+       "contributions-title": "$1 hea vaporpean kelelim yogdanam",
        "mycontris": "Yogdanam",
        "anoncontribs": "Yogdanam",
        "contribsub2": "{{GENDER:$3|$1}} hacheo ($2)",
        "sp-contributions-logs": "sotr",
        "sp-contributions-talk": "bhasabhas",
        "sp-contributions-search": "Yogdanam sod",
-       "sp-contributions-username": "Antorzall namo vo vapuddpeachem nanv:",
+       "sp-contributions-username": "Antorzall namo vo vaporpeachem nanv:",
        "sp-contributions-toponly": "Fokot halincheo uzollnneo dakhoi",
        "sp-contributions-submit": "Sod",
        "whatlinkshere": "Hanga kitem zoddta",
        "whatlinkshere-hideimages": "Failinchim zoddpam $1",
        "whatlinkshere-filters": "Challnio",
        "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",
-       "ipblocklist": "Addhailele vapuddpi",
+       "ipblocklist": "Addhailele vaporpi",
        "blocklink": "addavnnni",
        "unblocklink": "Addavnni kadd",
        "change-blocklink": "Addavnnni bodol",
        "allmessagesdefault": "Falta sondex mozkur",
        "thumbnail-more": "Vhodlem kor",
        "thumbnail_error": "Lhan-imaz toiar kortana chuk zali. Karonn: $1",
-       "tooltip-pt-userpage": "{{GENDER:|Tujem vapuddpachem}} pan",
+       "tooltip-pt-userpage": "{{GENDER:|Tujem vaporpeachem}} pan",
        "tooltip-pt-mytalk": "{{GENDER:|Tumchem}} bhasabhasachem pan",
        "tooltip-pt-preferences": "{{GENDER:|Tumcheo}} avddi",
        "tooltip-pt-watchlist": "Bodlachea dekhrekh korpachea panachi volleri",
        "tooltip-t-whatlinkshere": "Hanga zoddlelea sogllea wiki pananchi volleri",
        "tooltip-t-recentchangeslinked": "Hea panak-sun zoddlelea panachim halinche bodol",
        "tooltip-feed-atom": "Hea panak Atom purovnni",
-       "tooltip-t-contributions": "{{GENDER:$1|Hea vapuddpeachea}} yogdanachi suchi",
-       "tooltip-t-emailuser": "{{GENDER:$1|Hea vapuddpeak}} email patthoi",
+       "tooltip-t-contributions": "{{GENDER:$1|Hea vaporpeachea}} yogdanachi suchi",
+       "tooltip-t-emailuser": "{{GENDER:$1|Hea vaporpeak}} email dhadd",
        "tooltip-t-upload": "Faili upload kor",
        "tooltip-t-specialpages": "Sogllea vixex pananchi volleri",
        "tooltip-t-print": "Hea panachem chap'pakyogya avrutti",
        "tooltip-t-permalink": "Hea panache hea uzollnnek togpi zoddni",
        "tooltip-ca-nstab-main": "Mozkur pan polloi",
-       "tooltip-ca-nstab-user": "Vapuddpeachem pan polloi",
+       "tooltip-ca-nstab-user": "Vaporpeachem pan polloi",
        "tooltip-ca-nstab-special": "Hem ek kherit pan, ani hem bodlunk zaina",
        "tooltip-ca-nstab-project": "Prokolpachem pan polloi",
        "tooltip-ca-nstab-image": "Failichem pan polloi",
index 72e24cc..d3b1f94 100644 (file)
@@ -28,9 +28,9 @@
        "tog-extendwatchlist": "Ἐφοροδιαλογὴν ἐκτείνειν ἵνα φανῶσιν ἅπασαι αἱ ἀλλαγαὶ, οὐχὶ μόνον αἱ ἁρμόδιαι",
        "tog-usenewrc": "Χρῆσθαι προσκεκοσμημέναις προσφάτοις ἀλλαγαῖς (ἀπαιτεῖται JavaScript)",
        "tog-numberheadings": "Ἐξαριθμεῖν ἐπικεφαλίδας αὐτομάτως",
-       "tog-showtoolbar": "Δεικνύναι τὴν τῶν ἐργαλείων μεταγραφῆς μετώπην (ἀπαιτεῖται JavaScript)",
-       "tog-editondblclick": "Ἐπὶ δέλτων δὶς θλίψας, μετάγραψον αὐτάς (ἀπαιτεῖται JavaScript)",
-       "tog-editsectiononrightclick": "Καθιστάναι δυνατὸν τὸ μεταγράφειν τμήματα διὰ τοῦ ἐπὶ τῶν ἐπιγραφῶν τῶν τμημάτων θλίβειν δεξιῶς (ἀπαιτεῖται JavaScript)",
+       "tog-showtoolbar": "Δεικνύναι τὴν τῶν ἐργαλείων μεταγραφῆς μετώπην",
+       "tog-editondblclick": "Ἐπὶ δέλτων δὶς θλίψας, μετάγραψον αὐτάς",
+       "tog-editsectiononrightclick": "Καθιστάναι δυνατὸν τὸ μεταγράφειν τμήματα διὰ τοῦ ἐπὶ τῶν ἐπιγραφῶν τῶν τμημάτων θλίβειν δεξιῶς",
        "tog-watchcreations": "Προστιθέναι τὰς δέλτους ἃς ποιῶ τοῖς ἐφορωμένοις μου",
        "tog-watchdefault": "Προστιθέναι τὰς δέλτους ἃς μεταγράφω τοῖς ἐφορωμένοις μου",
        "tog-watchmoves": "Προστιθέναι τὰς δέλτους ἃς κινῶ τοῖς ἐφορωμένοις μου",
        "histlegend": "Σύγκρισις διαφορῶν: Ἐπιλέξατε τὰς συγκριτέας ἐκδόσεις καὶ πατήσατε enter ἢ τὸ κομβίον  \"Συγκρίνειν...\". <br />\nὙπόμνημα: (τρέχον) = διαφοραὶ ὡς πρὸς τὴν τρέχουσαν ἐκδοχήν,\n(ὕστατον) = διαφοραὶ ὡς πρὸς τὴν προηγουμένην ἔκδοσιν, μ = ἀλλαγαὶ μικρῆς κλίμακος.",
        "history-fieldset-title": "Ζήτησις ἐν ταῖς προτέραις",
        "history-show-deleted": "Διαγραφεῖσαι μόνον",
-       "histfirst": "πρώτη",
-       "histlast": "ἐσχάτη",
+       "histfirst": "ἐσχάτη",
+       "histlast": "νεωτέρα",
        "historysize": "({{PLURAL:$1|1 δυφίον|$1 δυφία}})",
        "historyempty": "(κενόν)",
        "history-feed-title": "Ἱστορία ἀναθεωρήσεων",
        "action-block": "φράττειν τὸ μεταγράφειν τοῦδε τοῦ χρωμένου",
        "action-protect": "ἀλλάττειν τὴν κλίμακα προστασίας τῆσδε τῆς δελτου",
        "action-import": "εἰσάγειν τήνδε τὴν δέλτον ἐξ ἑτέρου βίκι",
-       "action-importupload": "εἰσάγειν τήνδε τὴν δέλτον ἐξ ἐπιφορτίσεώς τινος ἀρχείου",
+       "action-importupload": "εἰσάγειν τήνδε τὴν δέλτον ἐξ ἐπιφορτίσεώς ἀρχείου",
        "action-patrol": "σημαίνειν τὰς μεταγραφὰς ἑτέρων ὡς φρουρουμένας",
        "action-autopatrol": "σήμανσις τῆς μεταγραφῆς σου ὡς περιπολουμένης",
        "action-unwatchedpages": "ὁρᾶν τὴν διαλογὴν τῶν μὴ ἐφορωμένων δέλτων",
        "action-siteadmin": "Κλῄειν ἢ ἐκκλῄειν τὴν βάσιν δεδομένων",
        "nchanges": "$1 {{PLURAL:$1|μεταβολή|μεταβολαί}}",
        "enhancedrc-history": "Αἱ πρότεραι",
-       "recentchanges": "Î\91á¼± Î½έαι μεταβολαί",
+       "recentchanges": "Î\9dέαι μεταβολαί",
        "recentchanges-legend": "Ἐπιλογαὶ προσφάτων μεταβολῶν",
        "recentchanges-summary": "Ἀνιχνεύσειν τὰς πλείω πρόσφατους ἀλλαγὰς οῦ βίκι ἐν τῇδε τῇ δέλτῳ.",
        "recentchanges-feed-description": "Παρακολουθεῖν τὰς πλείω προσφάτους ἀλλαγὰς τοῦ βίκι ἐν ταύτῃ περιλήψει.",
index 77cfb9e..6a82cac 100644 (file)
        "recentchangeslinked-page": "Syte:",
        "recentchangeslinked-to": "Zeig Änderige uf Syte, wu uff die Syte verwyyse",
        "recentchanges-page-added-to-category": "[[:$1]] zur Kategorie derzue ta",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] und {{PLURAL:$2|ei|$2}} anderi Syte zur Kategorie derzue ta",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] und [[Special:WhatLinksHere/$1|{{PLURAL:$2|ei|$2}}]] anderi Syte zur Kategorie derzue ta",
        "recentchanges-page-removed-from-category": "[[:$1]] vor Kategorie furtgnoh",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] und {{PLURAL:$2|ei|$2}} anderi Syte vor Kategorie furtgnoh",
        "autochange-username": "Automatischi MediaWiki-Änderig",
index 35bdcc0..804c4f9 100644 (file)
        "morenotlisted": "આ યાદી પૂર્ણ નથી.",
        "mypage": "પાનું",
        "mytalk": "ચર્ચા",
-       "anontalk": "àª\86 IP àª®àª¾àª\9fà«\87નà«\81àª\82 àª\9aરà«\8dàª\9aા àªªàª¾àª¨à«\81àª\82",
+       "anontalk": "àª\9aરà«\8dàª\9aા",
        "navigation": "ભ્રમણ",
        "and": "&#32;અને",
        "qbfind": "શોધો",
        "createacct-reason": "કારણ",
        "createacct-reason-ph": "તમે કેમ બીજું ખાતું બનાવો છો",
        "createacct-submit": "તમારું ખાતું બનાવો",
-       "createacct-another-submit": "બà«\80àª\9cà«\81àª\82 àª\96ાતà«\81àª\82 àª¬àª¨àª¾àªµà«\8b",
+       "createacct-another-submit": "ખાતું બનાવો",
        "createacct-benefit-heading": "{{SITENAME}} એ તમારા જેવા લોકોએ બનાવેલ છે.",
        "createacct-benefit-body1": "{{PLURAL:$1|ફેરફાર|ફેરફારો}}",
        "createacct-benefit-body2": "{{PLURAL:$1|પાનું|પાનાં}}",
        "sig_tip": "સમયછાપ સાથે તમારા હસ્તાક્ષર",
        "hr_tip": "આડી લીટી (શક્ય તેટલો ઓછો ઉપયોગ કરો)",
        "summary": "સારાંશ:",
-       "subject": "વિષય/શીર્ષક:",
+       "subject": "વિષય:",
        "minoredit": "આ એક નાનો સુધારો છે",
        "watchthis": "આ પાનાને ધ્યાનમાં રાખો",
        "savearticle": "પાનું સાચવો",
        "apihelp-no-such-module": "સાધન જૂથ \"$1\" ન મળ્યું.",
        "apisandbox-submit": "વિનંતી કરો",
        "apisandbox-reset": "સાફ કરો",
-       "apisandbox-examples": "ઉદાહરણ",
-       "apisandbox-results": "પરિણામ",
+       "apisandbox-examples": "ઉદાહરણ",
+       "apisandbox-results": "પરિણામ",
        "booksources": "પુસ્તક સ્રોત",
        "booksources-search-legend": "પુસ્તક સ્રોત શોધો",
        "booksources-isbn": "આઇએસબીએન:",
        "movenotallowedfile": "તમને ફાઈલ ખસેડવાની પરવાનગી નથી.",
        "cant-move-user-page": "તમને સભ્ય પાના હટાવવાની પરવાનગી નથી (ઉપપાના સિવાય).",
        "cant-move-to-user-page": "તમને   કોઇ પાનાને સભ્ય પાનામાં ખસેડવાની પ્રવાનગી નથી (સિવાય કે સભ્ય ઉપપાના)",
-       "newtitle": "àª\86 àª¨àªµà«\81àª\82 àª¨àª¾àª® àª\86પà«\8b:",
+       "newtitle": "નવà«\81àª\82 àª¶à«\80રà«\8dષàª\95:",
        "move-watch": "આ પાનું ધ્યાનમાં રાખો",
        "movepagebtn": "પાનું ખસેડો",
        "pagemovedsub": "પાનું સફળતા પૂર્વક ખસેડવામાં આવ્યું છે",
        "tooltip-feed-rss": "આ પાના માટે આર.એસ.એસ. ફીડ",
        "tooltip-feed-atom": "આ પાના માટે એટમ ફીડ",
        "tooltip-t-contributions": "{{GENDER:$1|આ સભ્ય}} વડે કરાયેલા યોગદાનોની યાદી",
-       "tooltip-t-emailuser": "આ સભ્યને ઇ-મેલ મોકલો",
+       "tooltip-t-emailuser": "{{GENDER:$1|આ સભ્ય}}ને ઇમેલ મોકલો",
        "tooltip-t-info": "આ પાનાં વિષે વધુ માહિતી",
        "tooltip-t-upload": "ફાઇલ ચડાવો",
        "tooltip-t-specialpages": "બધા ખાસ પાનાંઓની યાદી",
        "expand_templates_ok": "મંજૂર",
        "expand_templates_remove_comments": "ટીપ્પણીઓ દૂર કરો",
        "expand_templates_preview": "પૂર્વાવલોકન",
-       "pagelanguage": "પાનાની ભાષાનો ચયનકર્તા",
+       "pagelanguage": "પાનાની ભાષા બદલો",
        "pagelang-name": "પાનું",
        "pagelang-language": "ભાષા",
        "pagelang-use-default": "(મૂળભુત ભાષા)",
index ffa4ee3..60bbaab 100644 (file)
        "customjsprotected": "אינך מורשה לערוך דף JavaScript זה כיוון שהוא כולל הגדרות אישיות של משתמש אחר.",
        "mycustomcssprotected": "אין לך הרשאה לערוך דף CSS זה.",
        "mycustomjsprotected": "אין לך הרשאה לערוך דף JavaScript זה.",
-       "myprivateinfoprotected": "אין לך הרשאה לערוך את המידע הפרטי שלך",
+       "myprivateinfoprotected": "אין לך הרשאה לערוך את המידע הפרטי שלך.",
        "mypreferencesprotected": "אין לך הרשאה לערוך את ההעדפות שלך.",
        "ns-specialprotected": "לא ניתן לערוך דפים מיוחדים.",
        "titleprotected": "[[User:$1|$1]] {{GENDER:$1|הפעיל|הפעילה}} הגנה על הדף הזה מפני יצירה.\nהסיבה שניתנה לכך היא <em>$2</em>.",
        "nocookieslogin": "{{SITENAME}} משתמש בעוגיות כדי להכניס משתמשים למערכת.\nבדפדפן שלכם העוגיות מבוטלות.\nאנא הפעילו אותן מחדש ונסו שוב.",
        "nocookiesfornew": "חשבון המשתמש לא נוצר, כיוון שלא יכולנו לוודא את מקורו.\nודאו שהעוגיות מופעלות בדפדפן שלכם, העלו מחדש דף זה ונסו שוב.",
        "noname": "לא הכנסת שם משתמש תקין",
-       "loginsuccesstitle": "×\94×\9b× ×\99ס×\94 ×\94×\95ש×\9c×\9e×\94",
+       "loginsuccesstitle": "× ×\9bנסת ×\9c×\97ש×\91×\95×\9f",
        "loginsuccess": "'''נכנסת ל{{grammar:תחילית|{{SITENAME}}}} בשם \"$1\".'''",
        "nosuchuser": "אין משתמש בשם \"$1\".\nאנא ודאו שהאיות נכון (כולל אותיות רישיות וקטנות), או [[Special:UserLogin/signup|צרו חשבון חדש]].",
        "nosuchusershort": "אין משתמש בשם \"$1\".\nאנא ודאו שהאיות נכון.",
        "noemail": "לא רשומה כתובת דואר אלקטרוני עבור ה{{GENDER:$1|משתמש|משתמשת}} \"$1\".",
        "noemailcreate": "יש לספק כתובת דואר אלקטרוני תקינה.",
        "passwordsent": "סיסמה חדשה נשלחה לכתובת הדואר האלקטרוני הרשומה עבור \"$1\".\nאנא היכנסו חזרה לאתר אחרי שתקבלו אותה.",
-       "blocked-mailpassword": "כתובת ה־IP שלך נחסמה מעריכה, ולפיכך אינך מורשה להשתמש באפשרות שחזור הסיסמה, וזאת כדי למנוע ניצול לרעה של התכונה.",
+       "blocked-mailpassword": "כתובת ה־IP שלך נחסמה מעריכה. כדי למנוע ניצול לרעה, אינך מורשה להשתמש באפשרות שחזור הסיסמה.",
        "eauthentsent": "דוא\"ל אימות נשלח לכתובת הדוא\"ל שצוינה.\nלפני שדברי דוא\"ל אחרים יישלחו לחשבון הזה, יהיה עליכם לפעול לפי ההוראות בדוא\"ל, כדי לאשר שהחשבון אכן שייך לכם.",
        "throttled-mailpassword": "כבר נשלח דוא\"ל לאיפוס הסיסמה ב{{PLURAL:$1|שעה האחרונה|שעתיים האחרונות|־$1 השעות האחרונות}}.\nכדי למנוע ניצול לרעה, יכול להישלח רק דוא\"ל אחד כזה בכל {{PLURAL:$1|שעה|שעתיים|$1 שעות}}.",
        "mailerror": "שגיאה בשליחת דואר: $1",
        "createaccount-title": "יצירת חשבון ב{{grammar:תחילית|{{SITENAME}}}}",
        "createaccount-text": "מישהו יצר חשבון בשם $2 ב{{grammar:תחילית|{{SITENAME}}}} ($4), והסיסמה הזמנית של החשבון היא \"$3\". עליכם להיכנס ולשנות עכשיו את הסיסמה.\n\nבאפשרותכם להתעלם מהודעה זו, אם החשבון נוצר בטעות.",
        "login-throttled": "ביצעתם לאחרונה ניסיונות רבים מדי להיכנס לחשבון זה.\nאנא המתינו $1 לפני שתנסו שוב.",
-       "login-abort-generic": "×\94×\9b× ×\99ס×\94 ×\9c×\97ש×\91×\95×\9f × ×\9bש×\9cה - היא הופסקה",
+       "login-abort-generic": "×\9b× ×\99סת×\9a ×\9c×\97ש×\91×\95×\9f ×\9c×\90 ×\94צ×\9c×\99×\97ה - היא הופסקה",
        "login-migrated-generic": "חשבון המשתמש שלך הועבר, ושם המשתמש שלך כבר לא קיים באתר ויקי זה.",
        "loginlanguagelabel": "שפה: $1",
        "suspicious-userlogout": "בקשתך לצאת מהחשבון נדחתה כיוון שנראה שהיא נשלחה על־ידי דפדפן שבור או שרת פרוקסי עם זיכרון מטמון.",
        "botpasswords-insert-failed": "הוספת שם הבוט \"$1\" נכשלה. האם הוא כבר נוסף?",
        "botpasswords-update-failed": "לא היה אפשר לעדכן את שם הבוט \"$1\". האם הוא נמחק?",
        "botpasswords-created-title": "ססמת הבוט נוצרה",
-       "botpasswords-created-body": "ססמת הבוט \"$1\" נוצרה.",
+       "botpasswords-created-body": "ססמת הבוט עבור בוט בשם \"$1\" של המשתמש \"$2\" נוצרה.",
        "botpasswords-updated-title": "ססמת הבוט עודכנה",
-       "botpasswords-updated-body": "ססמת הבוט \"$1\" עודכנה.",
+       "botpasswords-updated-body": "ססמת הבוט עבור בוט בשם \"$1\" של המשתמש \"$2\" עודכנה.",
        "botpasswords-deleted-title": "ססמת הבוט נמחקה",
-       "botpasswords-deleted-body": "ססמת הבוט \"$1\" נמחקה.",
+       "botpasswords-deleted-body": "ססמת הבוט עבור בוט בשם \"$1\" של המשתמש \"$2\" נמחקה.",
        "botpasswords-newpassword": "הססמה החדשה לכניסה <strong>$1</strong> היא <strong>$2</strong>. <em>נא לשמור מידע זה לצורך עיון עתידי.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider אינו זמין.",
        "botpasswords-restriction-failed": "כניסה זו נמנעה בשל הגבלות על ססמאות בוט.",
        "sectioneditnotsupported-title": "עריכת פסקאות אינה נתמכת",
        "sectioneditnotsupported-text": "עריכת פסקאות אינה נתמכת בדף זה.",
        "permissionserrors": "שגיאת הרשאה",
-       "permissionserrorstext": "×\90×\99× ×\9a ×\9e×\95רש×\94 לבצע פעולה זו, {{PLURAL:$1|מהסיבה הבאה|מהסיבות הבאות}}:",
-       "permissionserrorstext-withaction": "×\90×\99× ×\9a ×\9e×\95רש×\94 $2, ×\9e×\94{{PLURAL:$1|ס×\99×\91×\94 ×\94×\91×\90×\94|סיבות הבאות}}:",
+       "permissionserrorstext": "×\90×\99× ×\9b×\9d ×\9e×\95רש×\99×\9d לבצע פעולה זו, {{PLURAL:$1|מהסיבה הבאה|מהסיבות הבאות}}:",
+       "permissionserrorstext-withaction": "×\90×\99× ×\9b×\9d ×\9e×\95רש×\99×\9d $2, {{PLURAL:$1|×\9e×\94ס×\99×\91×\94 ×\94×\91×\90×\94\9e×\94סיבות הבאות}}:",
        "contentmodelediterror": "לא ניתן לערוך את הגרסה הזאת כי מודל התוכן שלה הוא <code>$1</code>, השונה ממודל התוכן הנוכחי של הדף, <code>$2</code>.",
        "recreate-moveddeleted-warn": "'''אזהרה: הנכם יוצרים דף חדש שנמחק בעבר.'''\n\nכדאי לשקול אם יהיה זה נכון להמשיך לערוך את הדף.\nיומני המחיקות וההעברות של הדף מוצגים להלן:",
        "moveddeleted-notice": "דף זה נמחק.\nיומני המחיקות וההעברות של הדף מוצגים להלן.",
        "parser-unstrip-loop-warning": "נמצאה לולאה בפריסה",
        "parser-unstrip-recursion-limit": "עומק הרקורסיה של הפריסה עבר את המגבלה ($1)",
        "converter-manual-rule-error": "התגלתה שגיאה בכלל המרת שפה ידני",
-       "undo-success": "ניתן לבטל את העריכה. אנא בִדקו את השוואת הגרסאות למטה כדי לוודא שזה מה שאתם רוצים לעשות, ואז שמרו את השינויים למטה כדי לבצע את ביטול העריכה.",
+       "undo-success": "ניתן לבטל את העריכה.\nאנא בִּדקו את השוואת הגרסאות למטה כדי לוודא שזה אכן מה שאתם רוצים לעשות, ואז שִׁמרו את השינויים למטה כדי לסיים את ביטול העריכה.",
        "undo-failure": "לא ניתן היה לבטל את העריכה עקב התנגשות עם עריכות מאוחרות יותר.",
        "undo-norev": "לא ניתן היה לבטל את העריכה כי היא אינה קיימת או כי היא נמחקה.",
        "undo-nochange": "נראה שהעריכה כבר בוטלה.",
        "rev-deleted-unhide-diff": "אחת מהגרסאות שביקשתם להשוות '''נמחקה'''.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].\nאתם עדיין יכולים [$1 לצפות בהבדלים בין הגרסאות] אם ברצונכם להמשיך.",
        "rev-suppressed-unhide-diff": "אחת מהגרסאות שביקשתם להשוות <strong>הועלמה</strong>.\nניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההעלמות].\nאתם עדיין יכולים [$1 לצפות בהבדלים בין הגרסאות] אם ברצונכם להמשיך.",
        "rev-deleted-diff-view": "אחת מהגרסאות שביקשתם להשוות '''נמחקה'''.\nאתם עדיין יכולים לצפות בהבדלים בין הגרסאות; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} יומן המחיקות].",
-       "rev-suppressed-diff-view": "אחת מהגרסאות שביקשתם להשוות <strong>הועלמה</strong>\nאתם יכולים לצפות בהבדלים בין הגרסאות; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן  ההעלמות].",
-       "rev-delundel": "×\94צ×\92×\94\94סתרה",
+       "rev-suppressed-diff-view": "אחת מהגרסאות שביקשתם להשוות <strong>הועלמה</strong>.\nאתם יכולים לצפות בהבדלים בין הגרסאות; ניתן למצוא פרטים על כך ב[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} יומן ההעלמות].",
+       "rev-delundel": "ש×\99× ×\95×\99 ×\9eצ×\91 ×\94תצ×\95×\92ה",
        "rev-showdeleted": "הצגה",
        "revisiondelete": "מחיקה ושחזור של גרסאות",
        "revdelete-nooldid-title": "גרסת מטרה בלתי תקינה",
        "revdelete-unsuppress": "הסרת הגבלות בגרסאות המשוחזרות",
        "revdelete-log": "סיבה:",
        "revdelete-submit": "ביצוע על {{PLURAL:$1|הגרסה שנבחרה|הגרסאות שנבחרו}}",
-       "revdelete-success": "'''מצב הסתרת הגרסה עודכן.'''",
-       "revdelete-failure": "'''לא ניתן היה לעדכן את מצב הסתרת הגרסה:'''\n$1",
-       "logdelete-success": "'''הסתרת פעולת היומן הושלמה.'''",
-       "logdelete-failure": "'''לא ניתן היה לבצע את הסתרת פעולת היומן:'''\n$1",
-       "revdel-restore": "ש×\99× ×\95×\99 ×\94×\94צגה",
+       "revdelete-success": "מצב התצוגה של הגרסה שׁוּנה.",
+       "revdelete-failure": "לא ניתן היה לשנות את מצב התצוגה של הגרסה:\n$1",
+       "logdelete-success": "מצב התצוגה של פעולת היומן שׁוּנה.",
+       "logdelete-failure": "לא ניתן היה לשנות את מצב התצוגה של פעולת היומן:\n$1",
+       "revdel-restore": "ש×\99× ×\95×\99 ×\9eצ×\91 ×\94תצ×\95גה",
        "pagehist": "היסטוריית הדף",
        "deletedhist": "הגרסאות המחוקות",
        "revdelete-hide-current": "שגיאה בהסתרת הפריט מתאריך $2, $1: זו הגרסה הנוכחית.\nלא ניתן להסתיר אותה.",
        "revdelete-show-no-access": "שגיאה בהצגת הפריט מתאריך $2, $1: פריט זה סומן כ\"מוגבל\".\nאין לך גישה אליו.",
        "revdelete-modify-no-access": "שגיאה בשינוי הפריט מתאריך $2, $1: פריט זה סומן כ\"מוגבל\".\nאין לכם גישה אליו.",
        "revdelete-modify-missing": "שגיאה בשינוי פריט מספר $1: הוא אינו נמצא בבסיס הנתונים!",
-       "revdelete-no-change": "'''אזהרה:''' לפריט מתאריך $2, $1 כבר יש את הגדרות ההצגה הנדרשות.",
+       "revdelete-no-change": "<strong>אזהרה:</strong> לפריט מ־$2, $1 כבר היו את הגדרות התצוגה שביקשת.",
        "revdelete-concurrent-change": "שגיאה בשינוי הפריט מתאריך $2, $1: נראה שמצבו שונה על־ידי מישהו אחר בזמן שאתם ניסיתם לשנות אותו.\nאנא בדקו ביומנים.",
        "revdelete-only-restricted": "שגיאה בהסתרת הפריט מתאריך $2, $1: אין באפשרותך להעלים פריטים ממפעילי המערכת מבלי לבחור גם באחת מאפשרויות הנראוּת האחרות.",
        "revdelete-reason-dropdown": "* סיבות מחיקה נפוצות\n** הפרת זכויות יוצרים\n** תקציר עריכה או מידע אישי לא הולמים\n** שם משתמש לא הולם\n** מידע שעלול להיות לשון הרע",
        "mergelogpagetext": "זוהי רשימה של המיזוגים האחרונים של גרסאות מדף אחד לתוך דף שני.",
        "history-title": "היסטוריית גרסאות של הדף \"$1\"",
        "difference-title": "הבדלים בין גרסאות בדף \"$1\"",
-       "difference-title-multipage": "×\94×\91×\93×\9c×\99×\9d ×\91×\99×\9f ×\94×\93×£ \"$1\" ×\9c×\91×\99×\9f ×\94×\93×£ \"$2\"",
+       "difference-title-multipage": "הבדלים בין הדף \"$1\" לדף \"$2\"",
        "difference-multipage": "(הבדלים בין דפים)",
        "lineno": "שורה $1:",
        "compareselectedversions": "השוואת הגרסאות שנבחרו",
-       "showhideselectedversions": "×\94צ×\92ת/×\94סתרת הגרסאות שנבחרו",
+       "showhideselectedversions": "ש×\99× ×\95×\99 ×\9eצ×\91 ×\94תצ×\95×\92×\94 ×©×\9c הגרסאות שנבחרו",
        "editundo": "ביטול",
        "diff-empty": "(אין הבדלים)",
        "diff-multi-sameuser": "({{PLURAL:$1|גרסת ביניים אחת|$1 גרסאות ביניים}} של אותו משתמש {{PLURAL:$1|אינה מוצגת|אינן מוצגות}})",
        "userrights-changeable-col": "קבוצות שבאפשרותכם לשנות",
        "userrights-unchangeable-col": "קבוצות שאין באפשרותכם לשנות",
        "userrights-conflict": "התנגשות בין שינויי הרשאות משתמש! אנא בדקו את השינויים שלכם ואשרו אותם.",
-       "userrights-removed-self": "הסרת את הרשאות המשתמש שלך. לכן אין לך כעת אפשרות לגשת לדף זה.",
+       "userrights-removed-self": "הסרת את הרשאות המשתמש של עצמך. לכן אין לך כעת אפשרות לגשת לדף זה.",
        "group": "קבוצה:",
        "group-user": "משתמשים",
        "group-autoconfirmed": "משתמשים ותיקים",
        "recentchangeslinked-page": "שם הדף:",
        "recentchangeslinked-to": "הצגת השינויים בדפים המקשרים לדף הנתון במקום זאת",
        "recentchanges-page-added-to-category": "הדף [[:$1]] נוסף לקטגוריה",
-       "recentchanges-page-added-to-category-bundled": "הדף [[:$1]] {{PLURAL:$2|ועוד דף אחד|ועוד $2 דפים}} נוספו לקטגוריה",
+       "recentchanges-page-added-to-category-bundled": "הדף [[:$1]] [[Special:WhatLinksHere/$1|{{PLURAL:$2|ועוד דף אחד|ועוד $2 דפים}}]] נוספו לקטגוריה",
        "recentchanges-page-removed-from-category": "הדף [[:$1]] הוסר מקטגוריה",
-       "recentchanges-page-removed-from-category-bundled": "הדף [[:$1]] {{PLURAL:$2|ועוד דף אחד|ועוד $2 דפים}} הוסרו מקטגוריה",
+       "recentchanges-page-removed-from-category-bundled": "הדף [[:$1]] [[Special:WhatLinksHere/$1|{{PLURAL:$2|ועוד דף אחד|ועוד $2 דפים}}]] הוסרו מקטגוריה",
        "autochange-username": "שינוי אוטומטי של מדיה־ויקי",
        "upload": "העלאת קובץ לשרת",
        "uploadbtn": "העלאה",
        "largefileserver": "גודל הקובץ חורג ממגבלת השרת.",
        "emptyfile": "נראה שהקובץ שהעלית ריק.\nייתכן שהסיבה לכך היא שגיאת הקלדה בשם הקובץ.\nיש לוודא שזה הקובץ שברצונך להעלות.",
        "windows-nonascii-filename": "אתר ויקי זה אינו תומך בשמות קבצים עם תווים מיוחדים או תווים שאינם באנגלית.",
-       "fileexists": "קובץ בשם הזה כבר קיים, אנא בדקו את <strong>[[:$1]]</strong> אם אינכם בטוחים שברצונכם להחליף אותו.\n[[$1|thumb]]",
+       "fileexists": "קובץ בשם הזה כבר קיים, אנא בִּדקו את <strong>[[:$1]]</strong> אם אינכם בטוחים שברצונכם להחליף אותו.\n[[$1|thumb]]",
        "filepageexists": "דף תיאור הקובץ עבור קובץ זה כבר נוצר ב<strong>[[:$1]]</strong>, אך לא קיים קובץ בשם זה.\nתיאור הקובץ שתכתבו לא יופיע בדף תיאור הקובץ.\nכדי לגרום לו להופיע שם, יהיה עליכם לערוך אותו ידנית. [[$1|thumb]]",
        "fileexists-extension": "קובץ עם שם דומה כבר קיים: [[$2|thumb]]\n* שם הקובץ המועלה: <strong>[[:$1]]</strong>\n* שם הקובץ הקיים: <strong>[[:$2]]</strong>\nאולי כדאי לתת לקובץ שם ספציפי יותר?",
        "fileexists-thumbnail-yes": "נראה שהקובץ הוא תמונה מוקטנת (ממוזערת).\n[[$1|thumb]]\nיש לבדוק את הקובץ <strong>[[:$1]]</strong>.\nאם הקובץ שבדקת הוא אותה התמונה בגודל מקורי, אין זה הכרחי להעלות גם תמונה ממוזערת.",
        "upload-description": "תיאור הקובץ",
        "upload-options": "אפשרויות העלאה",
        "watchthisupload": "מעקב אחרי קובץ זה",
-       "filewasdeleted": "קובץ בשם זה כבר הועלה בעבר, ולאחר מכן נמחק. אנא בדקו את הדף $1 לפני שתמשיכו להעלותו שנית.",
+       "filewasdeleted": "קובץ בשם זה כבר הועלה בעבר, ולאחר מכן נמחק.\nאנא בִּדקו את $1 לפני שתמשיכו להעלות את הקובץ שנית.",
        "filename-thumb-name": "נראה שכותרת הקובץ היא כותרת של תמונה מוקטנת (ממוזערת). יש להימנע מהעלאת תמונות ממוזערות בחזרה לאותו אתר ויקי. אם זו אינה תמונה ממוזערת, יש לתקן את שם הקובץ כך שיהיה משמעותי יותר ושלא יכלול את הקידומת של תמונה ממוזערת.",
        "filename-bad-prefix": "שם הקובץ שאתם מעלים מתחיל ב־<strong>\"$1\"</strong>, שהוא שם שאינו מתאר את הקובץ ובדרך כלל מוקצה אוטומטית על־ידי מצלמות דיגיטליות.\nיש לבחור שם מתאים יותר לקובץ, שיתאר את תכניו.",
        "filename-prefix-blacklist": " #<!-- נא להשאיר שורה זו בדיוק כפי שהיא --> <pre>\n# התחביר הוא כדלקמן:\n#   * כל דבר מתו \"#\" לסוף השורה הוא הערה\n#   * כל שורה לא ריקה היא קידומת לשמות קבצים טיפוסיים שמצלמות דיגיטליות נותנות אוטומטית\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # מספר טלפונים סלולריים\nIMG # כללי\nJD # Jenoptik\nMGP # Pentax\nPICT # שונות\n #</pre> <!-- נא להשאיר שורה זו בדיוק כפי שהיא -->",
        "uploadstash-summary": "דף זה מאפשר גישה לקבצים שהועלו (או נמצאים בתהליך העלאה), אך טרם פורסמו באתר הוויקי. קבצים אלה אינם גלויים לאיש מלבד המשתמש שהעלה אותם.",
        "uploadstash-clear": "מחיקת הקבצים בסליק",
        "uploadstash-nofiles": "אין לכם קבצים בסליק.",
-       "uploadstash-badtoken": "×\91×\99צ×\95×¢ ×\94פע×\95×\9c×\94 × ×\9bש×\9c, ×\90×\95×\9c×\99 ×\91×\92×\9c×\9c ×¤×§×\99עת ×ª×\95קפ×\95 ×©×\9c ×\90ס×\99×\9e×\95×\9f ×\94ער×\99×\9b×\94 ×©×\9c×\9b×\9d. × ×¡×\95 שוב.",
+       "uploadstash-badtoken": "×\91×\99צ×\95×¢ ×\94פע×\95×\9c×\94 × ×\9bש×\9c, ×\90×\95×\9c×\99 ×\91×\92×\9c×\9c ×¤×§×\99עת ×ª×\95קפ×\95 ×©×\9c ×\90ס×\99×\9e×\95×\9f ×\94ער×\99×\9b×\94 ×©×\9c×\9b×\9d. × ×\90 ×\9cנס×\95ת שוב.",
        "uploadstash-errclear": "מחיקת הקבצים נכשלה.",
        "uploadstash-refresh": "רענון רשימת הקבצים",
+       "uploadstash-thumbnail": "הצגת תמונה ממוזערת",
        "invalid-chunk-offset": "היסט גוש לא תקין",
        "img-auth-accessdenied": "הגישה נדחתה",
        "img-auth-nopathinfo": "PATH_INFO חסר.\nהשרת אינו מוגדר להעברת מידע זה.\nייתכן שהוא מבוסס על CGI ולכן אינו יכול לתמוך ב־img_auth.\nראו https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "alllogstext": "תצוגה משולבת של כל סוגי היומנים הזמינים ב{{grammar:תחילית|{{SITENAME}}}}.\nניתן לצמצם את התצוגה על־ידי בחירת סוג היומן, שם המשתמש (תלוי רישיות) או הדף המושפע (גם כן תלוי רישיות).",
        "logempty": "אין פריטים תואמים ביומן.",
        "log-title-wildcard": "חיפוש כותרות המתחילות באותיות אלה",
-       "showhideselectedlogentries": "×\94צ×\92ת/×\94סתרת פעולות היומן שנבחרו",
-       "log-edit-tags": "ער×\99×\9bת ×\94ת×\92×\99×\95ת ×©×\9c ×¨×©×\95×\9eות היומן שנבחרו",
+       "showhideselectedlogentries": "ש×\99× ×\95×\99 ×\9eצ×\91 ×\94תצ×\95×\92×\94 ×©×\9c פעולות היומן שנבחרו",
+       "log-edit-tags": "ער×\99×\9bת ×\94ת×\92×\99×\95ת ×©×\9c ×¤×¢×\95×\9cות היומן שנבחרו",
        "checkbox-select": "בחירה: $1",
        "checkbox-all": "הכול",
        "checkbox-none": "לא כלום",
-       "checkbox-invert": "×\9c×\94פ×\95×\9a",
+       "checkbox-invert": "×\94פ×\99×\9b×\94",
        "allpages": "כל הדפים",
        "nextpage": "הדף הבא ($1)",
        "prevpage": "הדף הקודם ($1)",
        "allpagesfrom": "הצגת דפים החל מ:",
        "allpagesto": "הצגת דפים עד:",
        "allarticles": "כל הדפים",
-       "allinnamespace": "כל הדפים (מרחב שם $1)",
+       "allinnamespace": "×\9b×\9c ×\94×\93פ×\99×\9d (×\9eר×\97×\91 ×\94ש×\9d $1)",
        "allpagessubmit": "הצגה",
        "allpagesprefix": "הדפים ששמם מתחיל ב־:",
        "allpagesbadtitle": "כותרת הדף שניתנה הייתה בלתי־תקינה או שהייתה בה קידומת של קישור לשפה אחרת או לוויקי אחר.\nייתכן שהיא מכילה תו אחד או יותר האסורים לשימוש בכותרות.",
        "changecontentmodel-title-label": "כותרת הדף",
        "changecontentmodel-model-label": "מודל התוכן החדש",
        "changecontentmodel-reason-label": "סיבה:",
+       "changecontentmodel-submit": "שינוי",
        "changecontentmodel-success-title": "מודל התוכן שוּנה",
        "changecontentmodel-success-text": "מודל התוכן של [[:$1]] שוּנה.",
        "changecontentmodel-cannot-convert": "התוכן בדף [[:$1]] אינו יכול להיות מומר לסוג של $2.",
        "ipb-unblock": "הסרת חסימה של שם משתמש או כתובת IP",
        "ipb-blocklist": "הצגת החסימות הנוכחיות",
        "ipb-blocklist-contribs": "התרומות של {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "נותרו $1",
        "unblockip": "שחרור חסימה",
        "unblockiptext": "השתמשו בטופס שלהלן כדי להחזיר את הרשאות הכתיבה למשתמש או כתובת IP חסומים.",
        "ipusubmit": "שחרור חסימה",
        "movepage-moved-redirect": "נוצרה הפניה.",
        "movepage-moved-noredirect": "יצירת ההפניה בוטלה.",
        "articleexists": "קיים כבר דף באותו שם, או שהשם שבחרת אינו תקין.\nנא לבחור שם אחר.",
-       "cantmove-titleprotected": "×\90×\99× ×\9a ×\9e×\95רש×\94 ×\9c×\94×¢×\91×\99ר ×\90ת ×\94×\93×£ ×\9cש×\9d ×\96×\94 ×\9b×\99×\95×\95×\9f ×©×\94ש×\9d ×\94×\97×\93ש ×\9e×\95×\92×\9f ×\9eפנ×\99 ×\99צ×\99ר×\94",
+       "cantmove-titleprotected": "×\90×\99×\9f ×\9c×\9a ×\94רש×\90×\94 ×\9c×\94×¢×\91×\99ר ×\90ת ×\94×\93×£ ×\9c×\9b×\90×\9f, ×\9b×\99 ×\94ש×\9d ×\94×\97×\93ש ×\9e×\95×\92×\9f ×\9eפנ×\99 ×\99צ×\99ר×\94.",
        "movetalk": "העברה גם של דף השיחה",
        "move-subpages": "העברת כל דפי המשנה (עד $1)",
        "move-talk-subpages": "העברת כל דפי המשנה של דף השיחה (עד $1)",
        "import-logentry-upload-detail": "{{PLURAL:$1|גרסה אחת יובאה|$1 גרסאות יובאו}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|גרסה אחת של הדף $2 יובאה|$1 גרסאות של הדף $2 יובאו}}",
        "javascripttest": "בדיקת JavaScript",
-       "javascripttest-pagetext-noframework": "דף זה שמור להרצת בדיקות JavaScript.",
-       "javascripttest-pagetext-unknownframework": "סביבת הבדיקות \"$1\" אינה ידועה.",
        "javascripttest-pagetext-unknownaction": "הפעולה \"$1\" אינה ידועה.",
-       "javascripttest-pagetext-frameworks": "נא לבחור אחת מסביבות הבדיקות הבאות: $1",
-       "javascripttest-pagetext-skins": "בחירת עיצוב שאיתו יורצו הבדיקות:",
        "javascripttest-qunit-intro": "ראו את [$1 תיעוד הבדיקות] באתר mediawiki.org.",
        "tooltip-pt-userpage": "דף {{GENDER:|המשתמש|המשתמשת}} שלך",
        "tooltip-pt-anonuserpage": "דף המשתמש של משתמש אנונימי זה",
        "tooltip-pt-watchlist": "רשימת הדפים שאתם עוקבים אחרי השינויים בהם",
        "tooltip-pt-mycontris": "רשימת התרומות שלך",
        "tooltip-pt-anoncontribs": "רשימת העריכות שנעשו מכתובת ה־IP הזאת",
-       "tooltip-pt-login": "×\9e×\95×\9e×\9c×¥ ×\9c×\94×\99רש×\9d, ×\90×\9a ×\90×\99×\9f ×\97×\95×\91×\94 ×\9cעש×\95ת ×\9b×\9f",
+       "tooltip-pt-login": "×\9e×\95×\9e×\9c×¥ ×\9c×\94×\99×\9bנס ×\9c×\97ש×\91×\95×\9f; ×¢×\9d ×\96×\90ת, ×\96×\94 ×\9c×\90 ×\97×\95×\91×\94",
        "tooltip-pt-logout": "יציאה מהחשבון",
-       "tooltip-pt-createaccount": "×\9e×\95×\9e×\9c×¥ ×\9c×\99צ×\95ר ×\97ש×\91×\95×\9f ×\95×\9c×\94×\99×\9bנס ×\90×\9c×\99×\95; ×¢×\9d ×\96×\90ת, ×\96×\95 ×\90×\99× ×\94 חובה",
+       "tooltip-pt-createaccount": "×\9e×\95×\9e×\9c×¥ ×\9c×\99צ×\95ר ×\97ש×\91×\95×\9f ×\95×\9c×\94×\99×\9bנס ×\90×\9c×\99×\95; ×¢×\9d ×\96×\90ת, ×\96×\94 ×\9c×\90 חובה",
        "tooltip-ca-talk": "שיחה על דף זה",
        "tooltip-ca-edit": "עריכת דף זה באמצעות קוד ויקי",
        "tooltip-ca-addsection": "הוספת פסקה חדשה",
        "tooltip-t-emailuser": "שליחת דואר אלקטרוני {{GENDER:$1|למשתמש זה|למשתמשת זו}}",
        "tooltip-t-info": "מידע נוסף על דף זה",
        "tooltip-t-upload": "העלאת קבצים",
-       "tooltip-t-specialpages": "רש×\99×\9eת כל הדפים המיוחדים",
+       "tooltip-t-specialpages": "רש×\99×\9e×\94 ×©×\9c כל הדפים המיוחדים",
        "tooltip-t-print": "גרסה להדפסה של דף זה",
        "tooltip-t-permalink": "קישור קבוע לגרסה זו של הדף",
        "tooltip-ca-nstab-main": "צפייה בדף התוכן",
        "tooltip-ca-nstab-category": "צפייה בדף הקטגוריה",
        "tooltip-minoredit": "סימון עריכה זו כמשנית",
        "tooltip-save": "שמירת השינויים שלך",
-       "tooltip-preview": "תצוגה מקדימה, אנא השתמשו באפשרות זו לפני השמירה!",
+       "tooltip-preview": "תצוגה מקדימה של השינויים שלך. נא להשתמש באפשרות זו לפני השמירה.",
        "tooltip-diff": "צפייה בשינויים שערכתם בטקסט",
        "tooltip-compareselectedversions": "צפייה בהשוואת שתי גרסאות של דף זה",
        "tooltip-watch": "הוספת דף זה לרשימת המעקב",
        "file-no-thumb-animation-gif": "'''לתשומת לבך: בשל מגבלות טכניות, תמונות ממוזערות של תמונות GIF בעלות רזולוציה גבוהה כמו זאת לא תהיינה מונפשות.'''",
        "newimages": "גלריית קבצים חדשים",
        "imagelisttext": "להלן רשימה של {{PLURAL:$1|קובץ אחד|$1 קבצים}}, ממוינים $2:",
-       "newimages-summary": "דף זה מציג את הקבצים האחרונים שהועלו",
+       "newimages-summary": "דף זה מציג את הקבצים האחרונים שהועלו.",
        "newimages-legend": "מסנן",
        "newimages-label": "שם הקובץ (או חלק ממנו):",
        "newimages-showbots": "הצגת העלאות שבוצעו על־ידי בוטים",
        "version-libraries-description": "תיאור",
        "version-libraries-authors": "יוצרים",
        "redirect": "הפניה לפי שם קובץ, מספר משתמש, מספר דף, מספר גרסה או מזהה יומן",
-       "redirect-legend": "הפניה לקובץ או לדף",
        "redirect-summary": "דף מיוחד זה מפנה לקובץ (בהינתן שם הקובץ), לדף (בהינתן מספר גרסה או מספר דף), לדף משתמש (בהינתן מספר משתמש), או לרשומת יומן (בהינתן מזהה יומן). דוגמאות לשימוש: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], או [[{{#Special:Redirect}}/user/101]], או [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "מעבר",
        "redirect-lookup": "סוג:",
        "revdelete-uname-unhid": "הסתרת שם המשתמש בוטלה",
        "revdelete-restricted": "נוספו הגבלות למפעילי מערכת",
        "revdelete-unrestricted": "הוסרו הגבלות ממפעילי מערכת",
-       "logentry-block-block": "$1 {{GENDER:$2|×\97ס×\9d\97ס×\9e×\94}} ×\90ת {{GENDER:$4|$3}} ×¢×\9d ×\96×\9e×\9f ×¤×§×\99×¢×\94 ×©×\9c $5 $6",
+       "logentry-block-block": "$1 {{GENDER:$2|×\97ס×\9d\97ס×\9e×\94}} ×\90ת {{GENDER:$4|$3}} ×\9c×\9eש×\9a $5 $6",
        "logentry-block-unblock": "$1 {{GENDER:$2|שחרר|שחררה}} את החסימה של {{GENDER:$4|$3}}",
        "logentry-block-reblock": "$1 {{GENDER:$2|שינה|שינתה}} את הגדרות החסימה של {{GENDER:$4|$3}} עם זמן פקיעה של $5 $6",
        "logentry-suppress-block": "$1 {{GENDER:$2|חסם|חסמה}} את {{GENDER:$4|$3}} עם זמן פקיעה של $5 $6",
        "logentry-import-upload": "$1 {{GENDER:$2|ייבא|ייבאה}} את $3 באמצעות העלאת קובץ",
        "logentry-import-upload-details": "$1 {{GENDER:$2|ייבא|ייבאה}} את $3 באמצעות העלאת קובץ ({{PLURAL:$4|גרסה אחת|$4 גרסאות}})",
        "logentry-import-interwiki": "$1 {{GENDER:$2|ייבא|ייבאה}} את $3 מאתר ויקי אחר",
-       "logentry-import-interwiki-details": "$1 {{GENDER:$2|ייבא|ייבאה}} את $3 מ־$5 ({{PLURAL:$4|גרסה אחת|$4 גרסאות}})",
+       "logentry-import-interwiki-details": "$1 {{GENDER:$2|ייבא|ייבאה}} את $3 מ־$5&rlm; ({{PLURAL:$4|גרסה אחת|$4 גרסאות}})&rlm;",
        "logentry-merge-merge": "$1 {{GENDER:$2|מיזג|מיזגה}} את $3 לתוך $4 (גרסאות עד $5)",
-       "logentry-move-move": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 ל{{GRAMMAR:תחילית|$4}}",
+       "logentry-move-move": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 ל{{GRAMMAR:תחילית|$4}}&rlm;",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 ל{{GRAMMAR:תחילית|$4}} בלי להשאיר הפניה",
        "logentry-move-move_redir": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 ל{{GRAMMAR:תחילית|$4}} תוך דריסת הפניה",
        "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 ל{{GRAMMAR:תחילית|$4}} תוך דריסת הפניה ובלי להשאיר הפניה",
        "logentry-newusers-autocreate": "חשבון המשתמש $1 {{GENDER:$2|נוצר}} אוטומטית",
        "logentry-protect-move_prot": "$1 {{GENDER:$2|העביר|העבירה}} את הגדרות ההגנה מהדף $4 אל הדף $3",
        "logentry-protect-unprotect": "$1 {{GENDER:$2|הסיר|הסירה}} את ההגנה מהדף $3",
-       "logentry-protect-protect": "$1 {{GENDER:$2|×\94×\92×\9f\94×\92× ×\94}} על הדף $3 $4",
-       "logentry-protect-protect-cascade": "$1 {{GENDER:$2|×\94×\92×\9f\94×\92× ×\94}} על הדף $3 $4 [מדורג]",
+       "logentry-protect-protect": "$1 {{GENDER:$2|×\94פע×\99×\9c\94פע×\99×\9c×\94}} ×\94×\92× ×\94 על הדף $3 $4",
+       "logentry-protect-protect-cascade": "$1 {{GENDER:$2|×\94פע×\99×\9c\94פע×\99×\9c×\94}} ×\94×\92× ×\94 על הדף $3 $4 [מדורג]",
        "logentry-protect-modify": "$1 {{GENDER:$2|שינה|שינתה}} את רמת ההגנה של הדף $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|שינה|שינתה}} את רמת ההגנה של הדף $3 $4 [מדורג]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|שינה|שינתה}} את ההרשאות של $3 מ{{GRAMMAR:תחילית|$4}} ל{{GRAMMAR:תחילית|$5}}&rlm;",
+       "logentry-rights-rights": "$1 {{GENDER:$2|שינה|שינתה}} את ההרשאות של {{GENDER:$3|$3}} מ{{GRAMMAR:תחילית|$4}} ל{{GRAMMAR:תחילית|$5}}&rlm;",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|שינה|שינתה}} את ההרשאות של $3&rlm;",
        "logentry-rights-autopromote": "$1 קודם אוטומטית מ{{GRAMMAR:תחילית|$4}} ל{{GRAMMAR:תחילית|$5}}",
        "logentry-upload-upload": "$1 {{GENDER:$2|העלה|העלתה}} את $3",
        "log-name-managetags": "יומן ניהול תגיות",
        "log-description-managetags": "דף זה כולל רשימה של פעולות ניהול הקשורות ל[[Special:Tags|תגיות]]. היומן כולל רק פעולות שבוצעו ידנית על־ידי מפעיל מערכת; ייתכן שתגיות ייווצרו או יימחקו על־ידי תוכנת הוויקי ללא הוספת ערך ליומן זה.",
        "logentry-managetags-create": "$1 {{GENDER:$2|יצר|יצרה}} את התגית \"$4\"",
-       "logentry-managetags-delete": "$1 {{GENDER:$2|מחק|מחקה}} את התגית \"4$\" (שהוסרה {{PLURAL:$5|מגרסה אחת/פריט יומן אחד|מ־$5 גרסאות ו/או פריטי יומן}})",
+       "logentry-managetags-delete": "$1 {{GENDER:$2|מחק|מחקה}} את התגית \"$4\" (שהוסרה {{PLURAL:$5|מגרסה אחת/פריט יומן אחד|מ־$5 גרסאות ו/או פריטי יומן}})",
        "logentry-managetags-activate": "$1 {{GENDER:$2|הפעיל|הפעילה}} את התגית \"$4\" לשימוש על־ידי משתמשים ובוטים",
        "logentry-managetags-deactivate": "$1 {{GENDER:$2|ביטל|ביטלה}} את הפעלת התגית \"$4\" לשימוש על־ידי משתמשים ובוטים",
        "log-name-tag": "יומן תגיות",
        "api-error-unknownerror": "שגיאה בלתי ידועה: \"$1\".",
        "api-error-uploaddisabled": "ההעלאה מבוטלת באתר הוויקי הזה.",
        "api-error-verification-error": "קובץ זה עשוי להיות פגום או בעל סיומת שגויה.",
+       "api-error-was-deleted": "קובץ בשם הזה הועלה מוקדם יותר ונמחק לאחר מכן.",
        "duration-seconds": "{{PLURAL:$1|שנייה|$1 שניות}}",
        "duration-minutes": "{{PLURAL:$1|דקה|$1 דקות}}",
        "duration-hours": "{{PLURAL:$1|שעה|שעתיים|$1 שעות}}",
        "special-characters-group-ipa": "אלפבית פונטי בינלאומי (IPA)",
        "special-characters-group-symbols": "סימנים",
        "special-characters-group-greek": "יווני",
+       "special-characters-group-greekextended": "יוונית מורחבת",
        "special-characters-group-cyrillic": "קירילי",
        "special-characters-group-arabic": "ערבי",
        "special-characters-group-arabicextended": "ערבי מורחב",
        "sessionprovider-generic": "התחברויות של $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "התחברויות המבוססות על עוגיות",
        "sessionprovider-nocookies": "ייתכן שאפשרות השימוש בעוגיות כבויה. יש לוודא שאפשרות השימוש בעוגיות מופעלת ולהתחיל מחדש.",
-       "randomrootpage": "דף שורש אקראי"
+       "randomrootpage": "דף שורש אקראי",
+       "log-action-filter-block": "סוג החסימות:",
+       "log-action-filter-delete": "סוג המחיקות:",
+       "log-action-filter-patrol": "סוג השינויים הבדוקים:",
+       "log-action-filter-protect": "סוג ההגנות:",
+       "log-action-filter-upload": "סוג ההעלאות:",
+       "log-action-filter-all": "הכול",
+       "log-action-filter-block-block": "חסימות",
+       "log-action-filter-block-reblock": "שינויי חסימה",
+       "log-action-filter-block-unblock": "שחרורי חסימה",
+       "log-action-filter-delete-delete": "מחיקת דפים",
+       "log-action-filter-delete-restore": "שחזור דפים מחוקים",
+       "log-action-filter-delete-event": "מחיקת פעולות יומן",
+       "log-action-filter-delete-revision": "מחיקת גרסאות",
+       "log-action-filter-patrol-patrol": "סימוניים ידניים כבדוק",
+       "log-action-filter-patrol-autopatrol": "סימונים אוטומטיים כבדוק",
+       "log-action-filter-protect-protect": "הגנות",
+       "log-action-filter-protect-modify": "שינויי הגנה",
+       "log-action-filter-protect-unprotect": "הסרות הגנה",
+       "log-action-filter-upload-upload": "העלאות חדשות",
+       "log-action-filter-upload-overwrite": "דריסת קבצים קיימים"
 }
index 5c5119a..c645b0c 100644 (file)
@@ -71,7 +71,9 @@
                        "Niharika29",
                        "जनक राज भट्ट",
                        "YmKavishwar",
-                       "Upendradutt93"
+                       "Upendradutt93",
+                       "Nemo bis",
+                       "Wassan.anmol"
                ]
        },
        "tog-underline": "कड़ियाँ अधोरेखन:",
        "tog-watchlisthidebots": "मेरी ध्यानसूची से बॉट द्वारा किए परिवर्तन छिपाएँ",
        "tog-watchlisthideminor": "मेरी ध्यानसूची से छोटे परिवर्तन छिपाएँ",
        "tog-watchlisthideliu": "मेरी ध्यानसूची में सत्रारम्भित सदस्यों के सम्पादन न दिखाएँ",
+       "tog-watchlistreloadautomatically": "जब भी छननी बदलने पर ध्यानसूची को अपने आप ही लोड करें (जावास्क्रिप्ट अनिवार्य)",
        "tog-watchlisthideanons": "आई॰पी॰ सदस्यों द्वारा किए सम्पादनों को मेरी ध्यानसूची में न दिखायें",
        "tog-watchlisthidepatrolled": "परीक्षित सम्पादन मेरी ध्यानसूची में छुपाएँ",
        "tog-watchlisthidecategorization": "पृष्ठों का श्रेणीकरण छुपाएँ",
        "fri": "शुक्र",
        "sat": "शनि",
        "january": "जनवरी",
-       "february": "फ़रवरà¥\80",
+       "february": "फरवरी",
        "march": "मार्च",
        "april": "अप्रैल",
        "may_long": "मई",
        "november": "नवम्बर",
        "december": "दिसम्बर",
        "january-gen": "जनवरी",
-       "february-gen": "फ़रवरà¥\80",
+       "february-gen": "फरवरी",
        "march-gen": "मार्च",
        "april-gen": "अप्रैल",
        "may-gen": "मई",
        "november-gen": "नवम्बर",
        "december-gen": "दिसम्बर",
        "jan": "जन॰",
-       "feb": "फ़र॰",
+       "feb": "फर॰",
        "mar": "मार्च",
        "apr": "अप्रै॰",
        "may": "मई",
        "nov": "नव॰",
        "dec": "दिस॰",
        "january-date": "$1 जनवरी",
-       "february-date": "$1 à¤«à¤¼à¤°à¤µà¤°à¥\80",
+       "february-date": "$1 फरवरी",
        "march-date": "$1 मार्च",
        "april-date": "$1 अप्रैल",
        "may-date": "$1 मई",
        "versionrequired": "मीडीयाविकी का $1 अवतरण ज़रूरी है।",
        "versionrequiredtext": "यह पृष्ठ प्रयोग करने के लिये मीडियाविकी का $1 अवतरण ज़रूरी है।\nदेखें [[Special:Version|अवतरण पृष्ठ]]।",
        "ok": "ठीक है",
+       "pagetitle": "$1 - {{SITENAME}}",
+       "pagetitle-view-mainpage": "{{SITENAME}}",
+       "backlinksubtitle": "← $1",
        "retrievedfrom": "\"$1\" से लिया गया",
        "youhavenewmessages": "आपके लिए $1 हैं। ($2)",
        "youhavenewmessagesfromusers": "आपके लिये {{PLURAL:$3|एक अन्य सदस्य|$3 अन्य सदस्यों}} के $1 हैं। ($2)",
        "databaseerror-query": "अनुरोध: $1",
        "databaseerror-function": "फ़ंक्शन: $1",
        "databaseerror-error": "त्रुटि: $1",
+       "transaction-duration-limit-exceeded": "अत्यधिक बोझ को कम करने लिए यह कार्य रोक दिया गया है, क्योंकि यह लिखने की अवधि ($1) से बढ़ कर $2 {{PLURAL:$2|सेकंड|सेकंड}} को पार कर गया।\nIf यदि आप  बहुत सारे वस्तु को एक साथ बदल रहे हैं, तो कृपया छोटे होते रूप में बदलें।",
        "laggedslavemode": "'''चेतावनी:''' यह पृष्ठ अद्यतनीत जानकारी-युक्त ना होने की आशंका है।",
        "readonly": "डाटाबेस लॉक किया हुआ है",
        "enterlockreason": "लॉक करने का कारण दीजिए, साथ ही लॉक खुलने के समय का लगभग आकलन दीजिये।",
-       "readonlytext": "शायद मेंटेनन्स के चलते डाटाबेस नये संपादन और अन्य बदलावों से लॉक किया गया है, जिसके बाद यह सामान्य स्थिति में आ जाना चाहिये।\n\nजिस प्रबंधक ने यह लॉक किया था उसने यह कारण दिया है: $1",
+       "readonlytext": "शायद à¤®à¥\87à¤\82à¤\9fà¥\87ननà¥\8dस à¤\95à¥\87 à¤\9aलतà¥\87 à¤¡à¤¾à¤\9fाबà¥\87स à¤¨à¤¯à¥\87 à¤¸à¤\82पादन à¤\94र à¤\85नà¥\8dय à¤¬à¤¦à¤²à¤¾à¤µà¥\8bà¤\82 à¤¸à¥\87 à¤²à¥\89à¤\95 à¤\95िया à¤\97या à¤¹à¥\88, à¤\9cिसà¤\95à¥\87 à¤¬à¤¾à¤¦ à¤¯à¤¹ à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dय à¤¸à¥\8dथिति à¤®à¥\87à¤\82 à¤\86 à¤\9cाना à¤\9aाहियà¥\87।\n\nà¤\9cिस à¤\95ारà¥\8dयà¤\95ारà¥\80 à¤ªà¥\8dरबà¤\82धà¤\95 à¤¨à¥\87 à¤¯à¤¹ à¤²à¥\89à¤\95 à¤\95िया à¤¥à¤¾ à¤\89सनà¥\87 à¤¯à¤¹ à¤\95ारण à¤¦à¤¿à¤¯à¤¾ à¤¹à¥\88: $1",
        "missing-article": "डाटाबेस में $2 के अंदर कहीं भी \"$1\" नहीं मिला।\n\nआम तौर पर हटाए जा चुके पृष्ठ की इतिहास कड़ी का प्रयोग करने पर ऐसा होता है।\n\nअगर ऐसा नहीं है, तो शायद आपने सॉफ़्टवेयर में त्रुटि खोज ली है।\nकृपया यू॰आर॰एल पते समेत किसी [[Special:ListUsers/sysop|प्रबंधक]] को इसका ब्यौरा दें।",
        "missingarticle-rev": "(अवतरण#: $1)",
        "missingarticle-diff": "(अंतर: $1, $2)",
        "mypreferencesprotected": "आपके पास अपनी वरीयताएँ बदलने की अनुमति नहीं है।",
        "ns-specialprotected": "विशेष पृष्ठ सम्पादित नहीं किये जा सकते।",
        "titleprotected": "सदस्य [[User:$1|$1]] ने इस शीर्षक का पृष्ठ बनाने से सुरक्षित किया हुआ है।\nइसके लिये निम्न कारण दिया गया है: <em>$2</em>",
-       "filereadonlyerror": "\"$1\" फ़ाइल को बदलने में असक्षम क्योंकि भण्डार \"$2\" इस समय 'केवल पाठन हेतु' (रीड ओनली) है।\n\nजिस प्रबंधक ने ये प्रबंध लगाया है उन्होंने निम्न विवरण प्रदान किया है: \"$3\"।",
+       "filereadonlyerror": "\"$1\" à¤«à¤¼à¤¾à¤\87ल à¤\95à¥\8b à¤¬à¤¦à¤²à¤¨à¥\87 à¤®à¥\87à¤\82 à¤\85सà¤\95à¥\8dषम à¤\95à¥\8dयà¥\8bà¤\82à¤\95ि à¤­à¤£à¥\8dडार \"$2\" à¤\87स à¤¸à¤®à¤¯ 'à¤\95à¥\87वल à¤ªà¤¾à¤ à¤¨ à¤¹à¥\87तà¥\81' (रà¥\80ड à¤\93नलà¥\80) à¤¹à¥\88।\n\nà¤\9cिस à¤\95ारà¥\8dयà¤\95ारà¥\80 à¤ªà¥\8dरबà¤\82धà¤\95 à¤¨à¥\87 à¤¯à¥\87 à¤ªà¥\8dरबà¤\82ध à¤²à¤\97ाया à¤¹à¥\88 à¤\89नà¥\8dहà¥\8bà¤\82नà¥\87 à¤¨à¤¿à¤®à¥\8dन à¤µà¤¿à¤µà¤°à¤£ à¤ªà¥\8dरदान à¤\95िया à¤¹à¥\88: \"$3\"।",
        "invalidtitle-knownnamespace": "\"$2\" नामस्थान और \"$3\" नाम वाला गलत शीर्षक",
        "invalidtitle-unknownnamespace": "अज्ञात नामस्थान संख्या $1 और नाम \"$2\" वाला गलत शीर्षक",
        "exception-nologin": "लॉग इन नहीं किया है",
        "virus-unknownscanner": "अज्ञात ऐंटीवायरस:",
        "logouttext": "'''अब आप लॉग आउट कर चुके हैं।'''\n\nध्यान दें कि जब तक आप अपनी ब्राउज़र कैशे खाली नहीं करते हैं, कुछ पृष्ठ अब भी ऐसे दिख सकते हैं जैसे कि आप अभी भी लॉगिन हैं।",
        "cannotlogoutnow-title": "अभी प्रस्थान नहीं हो रहा है",
+       "cannotlogoutnow-text": "$1 के उपयोग समय प्रस्थान नहीं किया जा सकता है।",
        "welcomeuser": "आपका स्वागत है, $1!",
        "welcomecreation-msg": "आपका खाता बना दिया गया है।\nअपनी [[Special:Preferences|{{SITENAME}} वरीयताएँ]] बदलना ना भूलियेगा।",
        "yourname": "सदस्यनाम:",
        "nav-login-createaccount": "सत्रारंभ / खाता खोलें",
        "userlogin": "सत्रारंभ / खाता खोलें",
        "userloginnocreate": "लॉग इन",
-       "logout": "सतà¥\8dराà¤\82त",
-       "userlogout": "सतà¥\8dराà¤\82त",
+       "logout": "पà¥\8dरसà¥\8dथान à¤\95रà¥\87à¤\82",
+       "userlogout": "पà¥\8dरसà¥\8dथान à¤\95रà¥\87à¤\82",
        "notloggedin": "लॉग इन नहीं किया है",
        "userlogin-noaccount": "खाता नहीं है?",
        "userlogin-joinproject": "{{SITENAME}} से जुड़ें",
        "nologinlink": "नया खाता बनाएँ",
        "createaccount": "खाता बनाएँ",
        "gotaccount": "पहले से आपका खाता है? '''$1''' करें।",
-       "gotaccountlink": "लà¥\89à¤\97 à¤\87न",
+       "gotaccountlink": "पà¥\8dरवà¥\87श à¤\95रà¥\87à¤\82",
        "userlogin-resetlink": "अपनी प्रवेश जानकारी भूल गए हैं?",
        "userlogin-resetpassword-link": "अपना पासवर्ड भूल गए?",
        "userlogin-helplink2": "लॉग इन करने में सहायता",
        "nocookieslogin": "{{SITENAME}} पर लॉग इन करने के लिये कुकीज़ का प्रयोग होता है।\nआपने कुकीज़ अक्षम कर रखी हैं।\nकृपया अपने ब्राउज़र में कुकीज़ सक्षम करें और फिर पुनः कोशिश करें।",
        "nocookiesfornew": "स्रोत की पुष्टि ना हो पाने के कारण यह खाता निर्मित नहीं किया गया। \nसुनिश्चित करें कि आपने कुकीज़ सक्षम की हैं, पृष्ठ को पुनः लोड करें और पुनः प्रयास करें।",
        "noname": "आपने वैध सदस्यनाम नहीं दिया है।",
-       "loginsuccesstitle": "लà¥\89à¤\97 à¤\87न à¤¹à¥\8b à¤\97या à¤¹à¥\88",
+       "loginsuccesstitle": "पà¥\8dरवà¥\87श à¤¹à¥\81à¤\86",
        "loginsuccess": "'''आप {{SITENAME}} में \"$1\" सदस्यनाम से लॉग इन हो {{GENDER:$1|चुके|चुकी|चुके}} हैं।'''",
        "nosuchuser": "\"$1\" नाम का कोई सदस्य नहीं है।\nसदस्यनाम में लघु और दीर्घ अक्षरों से फ़र्क पड़ता है।\nअपनी वर्तनी जाँचें, या [[Special:UserLogin/signup|नया खाता खोलें]]।",
        "nosuchusershort": "\"$1\" नाम का कोई सदस्य नहीं है।\nकृपया अपनी दी हुई वर्तनी जाँचें।",
        "wrongpasswordempty": "कूटशब्द खाली है।\nपुनः यत्न करें।",
        "passwordtooshort": "आपका कूटशब्द कम से कम {{PLURAL:$1|1 अक्षर|$1 अक्षरों}} का होना चाहिये।",
        "passwordtoolong": "पासवर्ड {{PLURAL:$1|1 वर्ण|$1 वर्णों}} से ज़्यादा लम्बे नही हो सकते।",
+       "passwordtoopopular": "आम पासवर्ड आप नहीं चुन सकते हैं। कृपया अनोखा पासवर्ड चुनें।",
        "password-name-match": "आपका कूटशब्द आपके सदस्यनाम से भिन्न होना चाहिए।",
        "password-login-forbidden": "इस सदस्यनाम और कूटशब्द का उपयोग वर्जित है।",
        "mailmypassword": "कूटशब्द पुनःस्थापित करें",
        "createaccount-title": "{{SITENAME}} के लिये खाता बनाएँ",
        "createaccount-text": "आपके ई-मेल पते के लिये किसी ने {{SITENAME}} ($4) पर \"$2\" सदस्य नाम से \"$3\" कूटशब्द (पासवर्ड) सहित खाता खोला है।\nआपको लॉग इन कर के अपना कूटशब्द (पासवर्ड) तुरंत बदल लेना चाहिये।\n\nयदि यह खाता गलती से खोला गया है, तो आप इस मेसेज को नज़रंदाज़ कर सकते हैं।",
        "login-throttled": "आपने हाल ही में कई बार लॉग इन करने के प्रयास किये हैं।\nपुनः प्रयास करने से पहले कृपया $1 प्रतीक्षा करें।",
-       "login-abort-generic": "à¤\86पà¤\95ा à¤¸à¤¤à¥\8dरारमà¥\8dभ à¤\85सफल à¤°à¤¹à¤¾ - à¤¨à¤¿à¤·à¥\8dफलित",
+       "login-abort-generic": "à¤\86पà¤\95ा à¤ªà¥\8dरवà¥\87श à¤\85सफल à¤¹à¥\81à¤\86 - à¤°à¥\8bà¤\95ा à¤\97या",
        "login-migrated-generic": "आपका खाता माइग्रेट हो गया है और आपका सदस्यनाम इस विकी पर अब मौजूद नहीं है।",
        "loginlanguagelabel": "भाषा: $1",
        "suspicious-userlogout": "अपका लॉग आउट करने का अनुरोध अस्वीकृत कर दिया गया है क्योंकि ऐसा प्रतीत होता है कि यह किसी खराब ब्राउज़र या कैश करने वाली प्रॉक्सी द्वारा भेजा गया था।",
        "changepassword-success": "आपका कूटशब्द बदल दिया गया है!",
        "changepassword-throttled": "आपने हाल ही में कई बार लॉग इन करने के प्रयास किये हैं।\nपुनः प्रयास करने से पहले कृपया $1 प्रतीक्षा करें।",
        "botpasswords": "बॉट पासवर्ड",
+       "botpasswords-summary": "<em>बॉट पासवर्ड</em> सदस्य खाते को एपीआई के द्वारा बिना मुख्य खाते के जानकारी के उपयोग करने देता है। बॉट पासवर्ड का उपयोग कर के प्रवेश करने पर यदि पाबंदी होने पर सदस्य अधिकार उपलब्ध रहेगा।\n\nयदि आपको इस बारे में कुछ नहीं पता तो इसका उपयोग न करें। कोई भी आपसे इसे निर्मित करने के लिए नहीं पूछेगा।",
        "botpasswords-disabled": "बॉट पासवर्ड अभी निष्क्रिय है।",
+       "botpasswords-no-central-id": "बॉट पासवर्ड का उपयोग करने के लिए आपको मुख्य खाते से प्रवेश करना होगा।",
        "botpasswords-existing": "वर्तमान बॉट पासवर्ड",
        "botpasswords-createnew": "बॉट के लिए नया पासवर्ड बनाएँ",
        "botpasswords-editexisting": "बॉट के वर्तमान पासवर्ड को बदलें",
        "botpasswords-label-cancel": "रद्द करें",
        "botpasswords-label-delete": "हटाएँ",
        "botpasswords-label-resetpassword": "पासवर्ड पुनः तय करें",
+       "botpasswords-label-grants": "अनुदान आवेदन:",
+       "botpasswords-help-grants": "हर अनुदान जो सदस्य अधिकार में  पहले से आता है, उसे अधिकार तक पहुँच देता है।  देखें : [[Special:ListGrants|अनुदान सारणी]]",
+       "botpasswords-label-restrictions": "उपयोग मनाही:",
+       "botpasswords-label-grants-column": "प्रदान किया",
+       "botpasswords-bad-appid": "बॉट नाम \"$1\" मान्य नहीं है।",
+       "botpasswords-insert-failed": "बॉट नाम \"$1\" को जोड़ने में विफल हुआ। क्या यह पहले से है?",
+       "botpasswords-update-failed": "बॉट नाम \"$1\" को अद्यतन करने में विफल हुआ। क्या ये हट गया?",
        "botpasswords-created-title": "बॉट पासवर्ड निर्मित हुआ",
-       "botpasswords-created-body": "बà¥\89à¤\9f à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड \"$1\" à¤¸à¤«à¤²à¤¤à¤¾à¤ªà¥\82रà¥\8dवà¤\95 निर्मित हुआ।",
+       "botpasswords-created-body": "सदसà¥\8dय \"$2\" à¤\95à¥\87 à¤¬à¥\89à¤\9f à¤¨à¤¾à¤® \"$1\" à¤\95à¥\87 à¤²à¤¿à¤\8f à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड निर्मित हुआ।",
        "botpasswords-updated-title": "बॉट पासवर्ड अद्यतन हुआ",
-       "botpasswords-updated-body": "बà¥\89à¤\9f à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड \"$1\" सफलतापूर्वक अद्यतन हुआ।",
+       "botpasswords-updated-body": "सदसà¥\8dय \"$2\" à¤\95à¥\87 à¤¬à¥\89à¤\9f à¤¨à¤¾à¤® \"$1\" à¤\95ा à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड सफलतापूर्वक अद्यतन हुआ।",
        "botpasswords-deleted-title": "बॉट पासवर्ड हट गया",
-       "botpasswords-deleted-body": "बॉट पासवर्ड \"$1\" हट गया।",
+       "botpasswords-deleted-body": "सदस्य \"$2\" के बॉट नाम \"$1\" का पासवर्ड हट गया।",
+       "botpasswords-newpassword": "आपका नया पासवर्ड आपके प्रवेश <strong>$1</strong> के साथ <strong>$2</strong> है। <em>भविष्य में उपयोग करने हेतु इसे याद रखें</em>",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider उपलब्ध नहीं है।",
+       "botpasswords-restriction-failed": "इस प्रवेश में बॉट पासवर्ड रुकावट डाल रहा है।",
+       "botpasswords-invalid-name": "जो सदस्य नाम आप बता रहे हो, उसमें बॉट पासवर्ड अलग करने वाला (\"$1\") नहीं है।",
+       "botpasswords-not-exist": "सदस्य \"$1\" के आप बॉट पासवर्ड नहीं है, जिसका नाम \"$2\" है।",
        "resetpass_forbidden": "कूटशब्द बदले नहीं जा सकते",
        "resetpass-no-info": "इस पृष्ठ का सीधे प्रयोग करने के लिए आपको लॉग इन करना होगा।",
        "resetpass-submit-loggedin": "कूटशब्द बदलें",
        "resetpass-submit-cancel": "रद्द करें",
-       "resetpass-wrong-oldpass": "à¤\85वà¥\88ध à¤\85सà¥\8dथायà¥\80 à¤¯à¤¾ à¤µà¤°à¥\8dतमान à¤\95à¥\82à¤\9fशबà¥\8dद।\nसंभव है कि या तो आपने पहले ही सफलतापूर्वक अपना कूटशब्द बदल लिया हो, या आपने एक नए अस्थायी कूटशब्द का अनुरोध किया हो।",
+       "resetpass-wrong-oldpass": "à¤\85सà¥\8dथायà¥\80 à¤¯à¤¾ à¤µà¤°à¥\8dतमान à¤\95à¥\82à¤\9fशबà¥\8dद à¤\85वà¥\88ध à¤¹à¥\88।\nसंभव है कि या तो आपने पहले ही सफलतापूर्वक अपना कूटशब्द बदल लिया हो, या आपने एक नए अस्थायी कूटशब्द का अनुरोध किया हो।",
        "resetpass-recycled": "रीसेट करने के लिए नये पासवर्ड में कृपया अपने वर्तमान पासवर्ड के अलावा किसी अन्य पासवर्ड का प्रयोग करें।",
        "resetpass-temp-emailed": "आपने एक अस्थायी ईमेल किये गये कोड के साथ लॉग इन किया।\nलॉग इन सम्पूर्ण करने के लिए आपको यहाँ एक नया पासवर्ड सेट करना होगा:",
        "resetpass-temp-password": "अस्थायी कूटशब्द:",
        "passwordreset-emailtext-ip": "किसी ने (शायद आपने ही, $1 आइ॰पी पते से) {{SITENAME}} ($4) पर अपने {{PLURAL:$3|कूटशब्द|कूटशब्दों}} को रीसेट करने का अनुरोध किया है। इस ई-मेल पते से निम्न {{PLURAL:$3|खाता जुड़ा है|खाते जुड़े हैं}}:\n\n$2\n\n{{PLURAL:$3|यह|ये}} अस्थायी कूटशब्द {{PLURAL:$5|एक दिन|$5 दिनों}} के बाद काम नहीं करेंगे। आपको लॉग इन करके एक नया कूटशब्द अभी चुन लेना चाहिए। यदि यह अनुरोध किसी और ने किया है, या फिर आपको अपना मूल कूटशब्द याद आ गया है, और आप {{PLURAL:$3|अपना|अपने}} कूटशब्द नहीं बदलना चाहते, आप इस संदेश को अनदेखा कर के अपने पुराने कूटशब्द का प्रयोग जारी रख सकते हैं।",
        "passwordreset-emailtext-user": "{{SITENAME}} ($4) पर सदस्य $1 ने आपके {{PLURAL:$3|खाते|खातों}} के कूटशब्द को रीसेट करने का अनुरोध किया है। इस ई-मेल पते से निम्न {{PLURAL:$3|खाता जुड़ा है|खाते जुड़े हैं}}:\n\n$2\n\n{{PLURAL:$3|यह|ये}} अस्थायी कूटशब्द {{PLURAL:$5|एक दिन|$5 दिनों}} के बाद काम नहीं करेंगे।\nआपको लॉग इन करके एक नया कूटशब्द अभी चुन लेना चाहिए। यदि यह अनुरोध किसी और ने किया है, या फिर आपको अपना मूल कूटशब्द याद आ गया है, और आप {{PLURAL:$3|अपना|अपने}} कूटशब्द नहीं बदलना चाहते, आप इस संदेश को अनदेखा कर के अपने पुराने कूटशब्द का प्रयोग जारी रख सकते हैं।",
        "passwordreset-emailelement": "सदस्यनाम: \n$1\n\nअस्थायी कूटशब्द: \n$2",
-       "passwordreset-emailsentemail": "à¤\8fà¤\95 à¤\95à¥\82à¤\9fशबà¥\8dद à¤°à¥\80सà¥\87à¤\9f à¤\88-मà¥\87ल भेज दिया गया है।",
+       "passwordreset-emailsentemail": "यदि à¤\86पà¤\95ा à¤¯à¤¹ à¤\88मà¥\87ल à¤\86पà¤\95à¥\87 à¤\96ातà¥\87 à¤\95à¥\87 à¤¸à¤¾à¤¥ à¤\9cà¥\8bड़ा à¤\97या à¤¹à¥\88 à¤¤à¥\8b à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤¬à¤¦à¤²à¤¨à¥\87 à¤\95ा à¤\88मà¥\87ल à¤\87समà¥\87à¤\82 भेज दिया गया है।",
        "passwordreset-emailsentusername": "यदि कोई ईमेल इस खाते से जुड़ी है तो पासवर्ड आपके ईमेल में भेज दिया जाएगा।",
        "passwordreset-emailsent-capture": "नीचे दिखाया गया कूटशब्द रीसेट ई-मेल भेज दिया गया है।",
        "passwordreset-emailerror-capture": "नीचे दृष्टित कूटशब्द रीसेट ई-मेल उत्पन्न किया गया था, परंतु उसे {{GENDER:$2|सदस्य}} को भेजना असफल रहा।\nत्रुटि: $1",
        "resettokens-done": "टोकन रीसेट कर दिए गए।",
        "resettokens-resetbutton": "चुने हुए टोकन रीसेट करें",
        "bold_sample": "मोटा पाठ",
-       "bold_tip": "बà¥\8bलà¥\8dड पाठ",
+       "bold_tip": "à¤\97हरा पाठ",
        "italic_sample": "तिरछा पाठ",
-       "italic_tip": "à¤\87à¤\9fà¥\88लिà¤\95 पाठ",
+       "italic_tip": "तिरà¤\9bा पाठ",
        "link_sample": "कड़ी शीर्षक",
        "link_tip": "आंतरिक कड़ी",
        "extlink_sample": "http://www.example.com कड़ी शीर्षक",
        "previewnote": "'''याद रखें, यह केवल एक झलक है।'''\nआपके बदलाव अभी तक संजोये नहीं गए हैं!",
        "continue-editing": "संपादन क्षेत्र को जाएँ",
        "previewconflict": "यह झलक ऊपरी पाठ सम्पादन क्षेत्र में हुए बदलाव दिखाती है, और यदि आप अभी संजोते हैं तो यही पाठ संजोया जाएगा।",
-       "session_fail_preview": "'''क्षमा करें! सेशन डाटा के नष्ट होने के कारण आपके बदलाव संजोये नहीं जा सके।'''\nकृपया पुन: यत्न करें।\nअगर इसके बाद भी ऐसा ही होता है तो कृपया [[Special:UserLogout|लॉग आउट]] कर के पुनः लॉग इन करें।",
-       "session_fail_preview_html": "'''क्षमा करें! सेशन डाटा के नष्ट होने के कारण आपके बदलाव संजोये नहीं जा सके।'''\n\n''चूँकि {{SITENAME}} पर raw HTML सक्षम है, जावास्क्रिप्ट हमलों से बचाव के लिये झलक नहीं दिखाई गई है।''\n\n'''अगर यह आपका वैध संपादन यत्न था, तो कृपया पुनः यत्न करें।'''\nअगर इसके बाद भी ऐसा ही होता है तो कृपया [[Special:UserLogout|लॉग आउट]] कर के पुनः लॉग इन करें।",
+       "session_fail_preview": "'''क्षमा करें! सेशन डाटा के नष्ट होने के कारण आपके बदलाव संजोये नहीं जा सके।'''\nकृपया पुन: यत्न करें। अगर इसके बाद भी ऐसा ही होता है तो कृपया [[Special:UserLogout|लॉग आउट]] कर के पुनः लॉग इन करें।",
+       "session_fail_preview_html": "क्षमा करें! सेशन डाटा के नष्ट होने के कारण आपके बदलाव संजोये नहीं जा सके।\n\n<em>चूँकि {{SITENAME}} पर raw HTML सक्षम है, जावास्क्रिप्ट हमलों से बचाव के लिये झलक नहीं दिखाई गई है।</em>\n\n<strong>अगर यह आपका वैध संपादन यत्न था, तो कृपया पुनः यत्न करें।</strong>\nअगर इसके बाद भी ऐसा ही होता है तो कृपया [[Special:UserLogout|लॉग आउट]] कर के पुनः लॉग इन करें तथा जांचिए यदि आपका ब्राउज़र इस साइट से कुकीज़ की अनुमति देता है।",
        "token_suffix_mismatch": "'''आपके द्वारा किये गये बदलाव रद्द कर दिये गये हैं क्योंकि आपके क्लायंट ने आपके संपादन टोकन में दिये हुए विरामचिन्हों में बदलाव किये हैं।'''\nलेख के पाठ में खराबी ना आये इसलिये आपके बदलाव रद्द कर दिये गये हैं।\nऐसा तब भी हो सकता है यदि आप कोई खराब वेब-आधारित अनामक प्रौक्सी प्रयोग कर रहे हों।",
        "edit_form_incomplete": "'''सम्पादन फ़ॉर्म के कुछ भाग सर्वर तक नहीं पहुँच पाए; जाँच लें कि आपके द्वारा किये बदलाव अक्षुण्ण हैं, और सहेजने का पुनः यत्न करें।'''",
        "editing": "$1 सम्पादन",
        "copyrightwarning2": "{{SITENAME}} पर किया कोई भी योगदान अन्य सदस्यों द्वारा बदला जा सकता है और हटाया भी जा सकता है।\nअगर आपको अपने लिखे हुए पाठ में संपादन होना नामंजूर है तो यहाँ पर न लिखें।<br />\nआप हमें यह भी वचन देतें हैं कि यह आपने स्वयं लिखा है अथवा सार्वजनिक क्षेत्र या किसी समान मुक्त स्रोत से प्रतिलिपित किया है (अधिक जानकारी के लिये $1 देखें)।\n'''कॉपीराइट सुरक्षित कार्यों को बिना अनुमति के यहाँ न डालें!'''",
        "editpage-cannot-use-custom-model": "इस पृष्ठ का मुख्य सामग्री परिवर्तित नहीं हुआ।",
        "longpageerror": "'''त्रुटि: आपका दिया हुआ पाठ {{PLURAL:|$1 किलोबाइट|$1 किलोबाइट}} लंबा है, जो {{PLURAL:|$2 किलोबाइट|$2 किलोबाइट}} की सीमा से बाहर है।\nइसे संजोया नहीं जा सकता।'''",
-       "readonlywarning": "'''सावधान: डाटाबेस को रख-रखाव के लिये बंद कर दिया गया है, इसलिये अभी आपके बदलाव संजोए नहीं जा सकते।\nअगर आप चाहें तो इस सामग्री को बाद के लिए कॉपी-पेस्ट कर के किसी टेक्स्ट फ़ाइल में रख सकते हैं।'''\n\nबंद करने वाले प्रबंधक ने बंद करने का यह कारण दिया है: $1",
+       "readonlywarning": "<strong>सावधान: डाटाबेस को रख-रखाव के लिये बंद कर दिया गया है, इसलिये अभी आपके बदलाव संजोए नहीं जा सकते।\nअगर आप चाहें तो इस सामग्री को बाद के लिए कॉपी-पेस्ट कर के किसी टेक्स्ट फ़ाइल में रख सकते हैं।</strong>\n\nबंद करने वाले कार्यकारी प्रबंधक ने बंद करने का यह कारण दिया है: $1",
        "protectedpagewarning": "'''चेतावनी: इस पृष्ठ को सुरक्षित कर दिया गया है और इसे केवल प्रबंधक ही सम्पादित कर सकते हैं।'''\nनवीनतम लॉग प्रविष्टि संदर्भ के लिये नीचे दी है:",
        "semiprotectedpagewarning": "'''सूचना:''' यह पृष्ठ सुरक्षित कर दिया गया है और इसे केवल पंजीकृत सदस्य ही सम्पादित कर सकते हैं।\nनवीनतम लॉग प्रविष्टि संदर्भ के लिये नीचे दी है:",
        "cascadeprotectedwarning": "'''सावधान:''' यह पृष्ठ निम्नलिखित सुरक्षा-सीढ़ी {{PLURAL:$1|पृष्ठ से|पन्नों से}} जुड़ा हुआ होने के कारण सुरक्षित है, और केवल प्रबंधक ही इसमें बदलाव कर सकते हैं:",
        "permissionserrors": "अधिकार त्रुटि",
        "permissionserrorstext": "निम्नलिखित {{PLURAL:$1|कारण|कारणों}} से आपको ऐसा करने की अनुमति नहीं हैं:",
        "permissionserrorstext-withaction": "आपको $2 की अनुमति नहीं हैं, निम्नलिखित {{PLURAL:$1|कारण|कारणों}} की वजह से:",
-       "contentmodelediterror": "à¤\86प à¤\87स à¤ªà¥\83षà¥\8dठ à¤\95ा à¤\87तिहास à¤®à¥\87à¤\82 à¤¸à¤®à¥\8dपादन à¤¨à¤¹à¥\80à¤\82 à¤\95र à¤¸à¤\95तà¥\87 à¤¹à¥\88à¤\82 à¤\95à¥\8dयà¥\8bà¤\82à¤\95ि à¤\87सà¤\95ा à¤¸à¤¾à¤®à¤\97à¥\8dरà¥\80 <code>$1</code>, à¤\94र à¤µà¤°à¥\8dतमान à¤¸à¤¾à¤®à¤\97à¥\8dरà¥\80 <code>$2</code> है।",
+       "contentmodelediterror": "à¤\86प à¤\87स à¤ªà¥\83षà¥\8dठ à¤\95ा à¤\87तिहास à¤®à¥\87à¤\82 à¤¸à¤®à¥\8dपादन à¤¨à¤¹à¥\80à¤\82 à¤\95र à¤¸à¤\95तà¥\87 à¤¹à¥\88à¤\82 à¤\95à¥\8dयà¥\8bà¤\82à¤\95ि à¤\87सà¤\95ा à¤¸à¤¾à¤®à¤\97à¥\8dरà¥\80 <code>$1</code>, à¤\9cà¥\8b à¤\95à¥\80 à¤µà¤°à¥\8dतमान à¤¸à¤¾à¤®à¤\97à¥\8dरà¥\80 à¤¸à¥\87 <code>$2</code> à¤\85लà¤\97 है।",
        "recreate-moveddeleted-warn": "'''चेतावनी: आप एक पहले हटाए गए पृष्ठ को पुनर्निर्मित कर रहे हैं।'''\n\nआप को विचार करना चाहिये कि क्या इस पृष्ठ का संपादन जारी रखना उचित होगा।\nइस पृष्ट के हटाने व स्थानांतरण का लॉग सुविधा के लिये उपलब्ध है:",
        "moveddeleted-notice": "यह पृष्ठ हटाया जा चुका है।\nपृष्ठ के हटाने और स्थानांतरण का लॉग संदर्भ के लिए नीचे दिया गया है।",
        "moveddeleted-notice-recent": "क्षमा करें, यह पृष्ठ कुछ ही समय पहले हटाया गया है। (24 घण्टों के भीतर)\nइसके हटाये और स्थानांतरित करने का लोग नीचे दिया हुआ है।",
        "editwarning-warning": "इस पृष्ठ को छोड़ने पर आपके द्वारा किये गए कोई भी बदलाव गायब हो जाएँगे।\nयदि आपने लॉग इन किया हुआ है तो आप इस सूचना का दिखना अपनी वरीयताओं के \"{{int:prefs-editing}}\" भाग में बंद कर सकते हैं।",
        "editpage-notsupportedcontentformat-title": "सामग्री स्वरूप समर्थित नहीं है",
        "editpage-notsupportedcontentformat-text": "$1 सामग्री स्वरूप $2 सामग्री मॉडल द्वारा समर्थित नहीं है।",
-       "content-model-wikitext": "विà¤\95िà¤\9fà¥\87à¤\95à¥\8dसà¥\8dà¤\9f",
+       "content-model-wikitext": "विà¤\95िपाठà¥\8dय",
        "content-model-text": "सामान्य पाठ",
        "content-model-javascript": "जावास्क्रिप्ट",
        "content-model-css": "सी॰एस॰एस",
+       "content-model-json": "जेसन",
        "content-json-empty-object": "रिक्त ऑब्जेक्ट",
        "content-json-empty-array": "रिक्त ऐरे",
        "duplicate-args-warning": "<strong>चेतावनी:</strong> [[:$1]] प्राचल \"$3\" के लिए [[:$2]] को एक से अधिक बार काम में ले रहा है। केवल अन्त में दिया गया मान ही काम में लिया जायेगा।",
        "revdelete-unsuppress": "पुनर्स्थापित अवतरणों पर से प्रतिबन्ध हटाएँ",
        "revdelete-log": "कारण:",
        "revdelete-submit": "चयनित {{PLURAL:$1|अवतरण|अवतरणों}} पर लागू करें",
-       "revdelete-success": "'''अवतरण दृश्यता सफलतापूर्वक अद्यातानीत की गई।'''",
+       "revdelete-success": "अवतरण दृश्यता सफलतापूर्वक अद्यातानीत की गई।",
        "revdelete-failure": "'''अवतरण दृश्यता अद्यातानीत नहीं की जा सकी:'''\n$1",
-       "logdelete-success": "'''लॉग दृष्यता बदली गई।'''",
+       "logdelete-success": "लॉग दृष्यता बदली गई।",
        "logdelete-failure": "'''लॉग दृश्यता का जमाव नहीं किया जा सका:'''\n$1",
        "revdel-restore": "दृश्यता बदलें",
        "pagehist": "पृष्ठ इतिहास",
        "mergehistory-empty": "कोई भी अवतरण एकत्रित नहीं कर सकते।",
        "mergehistory-done": "$1 {{PLURAL:$3|का|के}} $3 अवतरण [[:$2]] में एकत्रित कर {{PLURAL:$3|दिया गया है|दिये गए हैं}}।",
        "mergehistory-fail": "इतिहास एकत्रित नहीं कर सकते, कृपया पृष्ठ और समय की पुनः जाँच करें।",
+       "mergehistory-fail-bad-timestamp": "समय संख्या अमान्य",
        "mergehistory-fail-invalid-source": "अमान्य स्रोत पृष्ठ",
        "mergehistory-fail-invalid-dest": "अमान्य लक्ष्य पृष्ठ",
+       "mergehistory-fail-no-change": "इतिहास विलय किसी भी अवतरण को विलय नहीं कर पाया। कृपया लेख और समय को दोबारा देखें।",
+       "mergehistory-fail-permission": "इतिहास विलय हेतु अधिकार कम है।",
+       "mergehistory-fail-self-merge": "स्रोत और भेजने वाला पृष्ठ समान है।",
+       "mergehistory-fail-timestamps-overlap": "स्रोत अवतरण भेजने वाले अवतरण के बाद आ रहा है।",
        "mergehistory-fail-toobig": "इतिहास विलय करना संभव नहीं है क्योंकि अवतरण सीमा $1 से अधिक {{PLURAL:$1|अवतरण|अवतरणों}} को स्थानांतरित करना होगा।",
        "mergehistory-no-source": "स्रोत पृष्ठ $1 मौजूद नहीं है।",
        "mergehistory-no-destination": "लक्ष्य पृष्ठ $1 मौजूद नहीं है।",
        "savedrights": "प्रयोक्ता {{GENDER:$1|$1}} का सदस्य अधिकार सहेजा गया।",
        "timezonelegend": "समयमंडल:",
        "localtime": "स्थानीय समय:",
-       "timezoneuseserverdefault": "विà¤\95à¥\80 à¤¡à¤¿à¤«à¤¼à¥\89लà¥\8dà¤\9f का उपयोग करें ($1)",
+       "timezoneuseserverdefault": "विà¤\95ि à¤®à¥\82ल का उपयोग करें ($1)",
        "timezoneuseoffset": "अन्य (समयांतर निर्दिष्ट करें)",
        "servertime": "सर्वर का समय:",
        "guesstimezone": "ब्राउज़र से भरें",
        "userrights": "सदस्य अधिकार व्यवस्थापन",
        "userrights-lookup-user": "सदस्य समूहों का व्यवस्थापन करें",
        "userrights-user-editname": "सदस्यनाम दें:",
-       "editusergroup": "सदस्य समूहों का संपादन करें",
+       "editusergroup": "{{GENDER:$1|सदस्य}} समूहों का संपादन करें",
        "editinguser": "सदस्य '''[[User:$1|$1]]''' $2 के अधिकार बदलें\n{{GENDER:$1|सदस्य}} के सदस्य अधिकार बदले जा रहे हैं <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "सदस्य समूहों का संपादन करें",
-       "saveusergroups": "सदस्य समूह संजोएँ",
+       "saveusergroups": "{{GENDER:$1|सदस्य}} समूह सहेजें",
        "userrights-groupsmember": "निम्न {{PLURAL:$1|समूह|समूहों}} का सदस्य:",
        "userrights-groupsmember-auto": "निम्न {{PLURAL:$1|समूह|समूहों}} का अंतर्निहित सदस्य:",
        "userrights-groups-help": "आप इस सदस्य की समूह-सदस्यता बदल सकते हैं:\n* बक्से पर सही का निशान लगे होने का अर्थ है कि सदस्य उस समूह में है।\n* बक्से पर सही का निशान न लगे होने का अर्थ है कि सदस्य उस समूह में नहीं है।\n* एक * का अर्थ है कि एक बार जोड़ने के बाद वह समूह हटा नहीं सकते हैं, और हटाने के बाद जोड़ नहीं सकते हैं।",
        "group-bot": "बॉट",
        "group-sysop": "प्रबंधक",
        "group-bureaucrat": "प्रशासक",
-       "group-suppress": "à¤\93वरसाà¤\88à¤\9fà¥\8dस",
+       "group-suppress": "à¤\9bà¥\81पानà¥\87 à¤µà¤¾à¤²à¥\87",
        "group-all": "(सभी)",
        "group-user-member": "{{GENDER:$1|सदस्य}}",
        "group-autoconfirmed-member": "{{GENDER:$1|स्वतः स्थापित सदस्य}}",
        "group-bot-member": "{{GENDER:$1|बॉट}}",
        "group-sysop-member": "{{GENDER:$1|प्रबंधक}}",
        "group-bureaucrat-member": "{{GENDER:$1|प्रशासक}}",
-       "group-suppress-member": "{{GENDER:$1|à¤\93वरसाà¤\88à¤\9f}}",
+       "group-suppress-member": "{{GENDER:$1|à¤\9bà¥\81पानà¥\87 à¤µà¤¾à¤²à¥\87}}",
        "grouppage-user": "{{ns:project}}:सदस्य",
        "grouppage-autoconfirmed": "{{ns:project}}:स्वतः स्थापित सदस्य",
        "grouppage-bot": "{{ns:project}}:बॉट",
        "grouppage-sysop": "{{ns:project}}:प्रबंधक",
        "grouppage-bureaucrat": "{{ns:project}}:प्रशासक",
-       "grouppage-suppress": "{{ns:project}}:à¤\93वरसाà¤\88à¤\9f",
+       "grouppage-suppress": "{{ns:project}}:à¤\9bà¥\81पाना",
        "right-read": "पृष्ठ पढ़ें",
        "right-edit": "पृष्ठ सम्पादित करें",
        "right-createpage": "पृष्ठ बनाएँ (जो चर्चा पृष्ठ नहीं हैं)",
        "right-createtalk": "वार्ता पृष्ठ बनाएँ",
        "right-createaccount": "नये सदस्य खाते बनाएँ",
+       "right-autocreateaccount": "बाहरी खाते से स्वतः प्रवेश",
        "right-minoredit": "अपने बदलाव छोटे चिन्हित करें",
        "right-move": "पृष्ठ स्थानांतरित करें",
        "right-move-subpages": "पृष्ठ उपपृष्ठों सहित स्थानांतरीत करें",
        "right-managechangetags": "डेटाबेस से [[Special:Tags|चिप्पियाँ]] बनायें और हटायें",
        "right-applychangetags": "प्रयोग में लाइये [[Special:Tags|tags]] किसी के बदलाव के साथ।",
        "right-changetags": "जमा करो और हटाओ स्वतंत्र [[Special:Tags|टैग]] व्यक्तिगत अवतरणों और लॉग प्रविक्तियों पर",
+       "grant-generic": "\"$1\" अधिकार संग्रह",
+       "grant-group-page-interaction": "पृष्ठों से जुड़ें",
+       "grant-group-file-interaction": "मीडिया से जुड़ें",
+       "grant-group-watchlist-interaction": "ध्यानसूची से जुड़ें",
        "grant-group-email": "ई-मेल भेजें",
+       "grant-group-high-volume": "उच्च कार्य गतिविधि करें",
+       "grant-group-customization": "पसंद और तय",
+       "grant-group-administration": "प्रबंधकीय कार्य करें",
+       "grant-group-other": "अन्य गतिविधि",
+       "grant-blockusers": "प्रतिबंधित और अप्रतिबंधित करना",
        "grant-createaccount": "खाता बनाएँ",
+       "grant-createeditmovepage": "निर्माण, सम्पादन, और स्थानांतरण करना",
+       "grant-delete": "लेख, अवतरण और लॉग हटाना",
+       "grant-editinterface": "मीडियाविकि नामस्थान और सदस्य सीएसएस/जेएस को संपादित करना।",
+       "grant-editmycssjs": "अपने सदस्य सीएसएस/जेएस को संपादित करें",
+       "grant-editmyoptions": "अपने सदस्य पसंद को संपादित करें",
        "grant-editmywatchlist": "ध्यानसूची संपादित करें",
+       "grant-editpage": "बने पृष्ठ संपादित करें",
+       "grant-editprotected": "सुरक्षित पृष्ठ संपादित करें",
+       "grant-highvolume": "अत्यधिक तेजी से सम्पादन",
+       "grant-oversight": "सदस्य को छुपाना और अवतरण हटाना",
+       "grant-patrol": "पृष्ठों को जांचा हुआ चिन्हित करना",
+       "grant-protect": "पृष्ठों को सुरक्षित व असुरक्षित करना",
+       "grant-rollback": "पृष्ठ से सम्पादन वापस लेना",
+       "grant-sendemail": "अन्य सदस्यों को ई-मेल भेजें",
+       "grant-uploadeditmovefile": "फ़ाइल अपलोड, बदलना, स्थानांतरण करना",
+       "grant-uploadfile": "नए फ़ाइल डालें",
        "grant-basic": "सामान्य अधिकार",
+       "grant-viewdeleted": "हटाये गए फ़ाइल व पृष्ठ देखें",
        "grant-viewmywatchlist": "अपनी ध्यानसूची देखें",
        "newuserlogpage": "सदस्य खाता निर्माण लॉग",
        "newuserlogpagetext": "यह सदस्य खातों के निर्माण का लॉग है।",
        "action-createpage": "पृष्ठ बनाने",
        "action-createtalk": "वार्ता पृष्ठ बनाने",
        "action-createaccount": "यह सदस्य खाता खोलने",
+       "action-autocreateaccount": "स्वतः ही बाहरी सदस्य खाता बनायें",
        "action-history": "इस पृष्ठ का इतिहास देखने",
        "action-minoredit": "इस बदलाव को छोटा बदलाव चिन्हित करने",
        "action-move": "इस पृष्ठ को स्थानांतरित करने",
        "action-protect": "इस पृष्ठ के सुरक्षा स्तर बदलने",
        "action-rollback": "किसी पृष्ठ का अंतिम सम्पादन करने वाले सदस्य के सम्पादन वापिस लेने",
        "action-import": "किसी और विकि से पृष्ठ आयात करने",
-       "action-importupload": "फ़ाइल अपलोड द्वारा यह पृष्ठ आयात करे",
+       "action-importupload": "फ़ाइल अपलोड द्वारा यह पृष्ठ आयात करे",
        "action-patrol": "अन्य सदस्यों के सम्पादन परीक्षित करने",
        "action-autopatrol": "अपने सम्पादन स्वचालित रूप से परीक्षित करने",
        "action-unwatchedpages": "ऐसे पृष्ठ जो किसी की ध्यानसूची में नहीं हैं की सूची देखने",
        "recentchangeslinked-page": "पृष्ठ नाम:",
        "recentchangeslinked-to": "इसके बदले में दिये हुए पृष्ठसे जुडे पन्नोंके बदलाव दर्शायें",
        "recentchanges-page-added-to-category": "[[:$1]] श्रेणी में जुड़ा",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] और {{PLURAL:$2|एक पृष्ठ|$2 पृष्ठ}} श्रेणी में जुड़ा",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] और [[Special:WhatLinksHere/$1|{{PLURAL:$2|एक पृष्ठ|$2 पृष्ठ}}]] श्रेणी में जुड़ा",
        "recentchanges-page-removed-from-category": "[[:$1]] श्रेणी से हटा",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] और {{PLURAL:$2|एक पृष्ठ|$2 पृष्ठ}} श्रेणी से हटा",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] और [[Special:WhatLinksHere/$1|{{PLURAL:$2|एक पृष्ठ|$2 पृष्ठ}}]] श्रेणी से हटा",
        "autochange-username": "मीडियाविकि स्वतः परिवर्तन",
        "upload": "फ़ाइल अपलोड करें",
        "uploadbtn": "फ़ाइल अपलोड करें",
        "uploaded-script-svg": "अपलोड की गयी एसवीजी फ़ाइल में स्क्रीप्ट अवयव \"$1\" पाया गया।",
        "uploaded-hostile-svg": "अपलोड की गयी एसवीजी फाइल के शैली अवयव में असुरक्षित सीएसएस पायी गयी।",
        "uploaded-event-handler-on-svg": "सेटिंग ईवेंट हैंडलर (आयोजन प्रबन्धनकर्ता वरियता) <code>$1=\"$2\"</code> एसवीजी फ़ाइल में अनुमत नहीं है।",
+       "uploaded-href-attribute-svg": "href केवल एसवीजी फ़ाइल हेतु ही http:// या https:// उपयोग करने देता है। <code>&lt;$1 $2=\"$3\"&gt;</code>",
        "uploaded-href-unsafe-target-svg": "अपलोड की गयी फ़ाइल में असुरक्षित लक्ष्य <code>&lt;$1 $2=\"$3\"&gt;</code> पाये गए।",
        "uploaded-animate-svg": "चिप्पि \"animate\" पायी गई जिससे href परिवर्तित हो सकता है, अपलोड की गयी फ़ाइल में \"from\" विशेषता <code>&lt;$1 $2=\"$3\"&gt;</code> काम में ली जा रही है।",
        "uploaded-setting-event-handler-svg": "विकल्प आयोजन-संभालने वाला अवरोधित है, एसवीजी फ़ाइल में मिला <code>&lt;$1 $2=\"$3\"&gt;</code> है।",
        "upload-too-many-redirects": "इस यू॰आर॰एल में अत्यधिक पुनर्निर्देशन हैं",
        "upload-http-error": "एक एच॰टी॰टी॰पी त्रुटि आई: $1",
        "upload-copy-upload-invalid-domain": "कॉपी अपलोड इस डोमेन से उपलब्ध नहीं हैं।",
+       "upload-foreign-cant-upload": "यह विकि अन्य फ़ाइल संग्रह में अपलोड हेतु तय नहीं किया गया है।",
        "upload-dialog-title": "फ़ाइल डालें",
        "upload-dialog-button-cancel": "रद्द करें",
        "upload-dialog-button-done": "पूर्ण हुआ",
        "upload-dialog-button-upload": "डालें",
        "upload-form-label-infoform-title": "विवरण",
        "upload-form-label-infoform-name": "नाम",
+       "upload-form-label-infoform-name-tooltip": "एक अनोखा विवरण शीर्षक इस फ़ाइल हेतु डालें, जी इसे फ़ाइल के रूप में दिखाये। आप इसके लिए साधारण भाषा और रिक्त स्थान का उपयोग कर सकते हैं। फ़ाइल प्रारूप को न जोड़ें। \\",
        "upload-form-label-infoform-description": "विवरण",
+       "upload-form-label-infoform-description-tooltip": "छोटे रूप में बतायें इस के उलेखनीयता के बारे में। \n चित्र हेतु, जो मुख्य वस्तु नहीं दिखाया गया है आदि के स्थान।",
        "upload-form-label-usage-title": "उपयोग",
        "upload-form-label-usage-filename": "फ़ाइल का नाम",
        "foreign-structured-upload-form-label-own-work": "यह मेरा कार्य है",
        "backend-fail-read": "फ़ाइल $1 पढ़ी नहीं जा सकी।",
        "backend-fail-create": "फ़ाइल $1 लिखी नहीं जा सकी।",
        "backend-fail-maxsize": "फ़ाइल $1 लिखी नहीं जा सकी क्योंकि यह {{PLURAL:$2|$2 बाईट}} से बड़ी है।",
-       "backend-fail-readonly": "भंडारण बैकेंड \"$1\" इस समय केवल पढ़ा जा सकता है (रीड-ओन्ली है)। दिया गया कारण था: \"$2\"",
+       "backend-fail-readonly": "भंडारण बैकेंड \"$1\" इस समय केवल पढ़ा जा सकता है (रीड-ओन्ली है)। दिया गया कारण था: <em>$2</em>",
        "backend-fail-synced": "फ़ाइल \"$1\" आतंरिक भंडारण बैकेंड में असंगत स्थिति में है।",
        "backend-fail-connect": "\"$1\" भंडारण बैकेंड से सम्पर्क स्थापित नहीं किया जा सका।",
        "backend-fail-internal": "भंडारण बैकेंड \"$1\" में कोई अज्ञात त्रुटि उत्पन्न हुई।",
        "uploadstash-clear": "स्टैश की गई फ़ाइलें साफ़ करें",
        "uploadstash-nofiles": "आपके पास कोई स्टैश की हुई फ़ाइलें नहीं हैं।",
        "uploadstash-badtoken": "वह कार्य असफल रहा, सम्भवतः आपके सम्पादन प्रमाणपत्र की अवधि समाप्त हो गई है। पुनः प्रयास करें।",
-       "uploadstash-errclear": "à¥\9eाà¤\87लà¥\8bà¤\82 à¤\95à¥\8b à¤¸à¤¾à¥\9e करना असफल रहा।",
+       "uploadstash-errclear": "फ़ाà¤\87लà¥\8bà¤\82 à¤\95à¥\8b à¤¸à¤¾à¤«à¤¼ करना असफल रहा।",
        "uploadstash-refresh": "फ़ाइलों की सूची रिफ़्रेश करें",
+       "uploadstash-thumbnail": "छवि देखें",
        "invalid-chunk-offset": "अग्राह्य चंक ऑफ़सेट",
        "img-auth-accessdenied": "अनुमति नहीं है",
        "img-auth-nopathinfo": "PATH_INFO मौजूद नहीं है।\nआपके सर्वर में इस जानकारी को भेजने के लिए जमाव नहीं है।\nयह सी॰जी॰आई-आधारित हो सकता है और img_auth को स्वीकार नहीं करता है।\nhttps://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization देखें।",
        "filehist-deleteall": "सभी हटाएँ",
        "filehist-deleteone": "हटाएँ",
        "filehist-revert": "पूर्ववत करें",
-       "filehist-current": "सदà¥\8dय",
+       "filehist-current": "वरà¥\8dतमान",
        "filehist-datetime": "दिनांक/समय",
        "filehist-thumb": "अंगूठाकार प्रारूप",
        "filehist-thumbtext": "$1 के संस्करण का अंगूठाकार प्रारूप।",
        "uploadnewversion-linktext": "इस फ़ाइल का नया अवतरण अपलोड करें",
        "shared-repo-from": "$1 से",
        "shared-repo": "एक साझे भंडार",
+       "shared-repo-name-wikimediacommons": "विकिमीडिया कॉमन्स",
        "upload-disallowed-here": "आप इस फ़ाइल को अधिलेखित नहीं कर सकते।",
        "filerevert": "$1 पूर्ववत करें",
        "filerevert-legend": "फ़ाइल पूर्ववत करें",
        "filerevert-intro": "आप '''[[Media:$1|$1]]''' के [$4 $2 को $3 बजे के अवतरण] को पूर्ववत कर रहे हैं।",
        "filerevert-comment": "कारण:",
-       "filerevert-defaultcomment": "$1 को $2 बजे के अवतरण को पूर्ववत किया",
+       "filerevert-defaultcomment": "$2, $1 ($3) के अवतरण को पूर्ववत किया",
        "filerevert-submit": "पूर्ववत करें",
        "filerevert-success": "'''[[Media:$1|$1]]''' को [$4 $2 को $3 बजे के अवतरण] को पूर्ववत कर दिया गया है।",
        "filerevert-badversion": "दिये हुए समय से मेल खाने वाला इस फ़ाइल का पुराना अवतरण नहीं है।",
        "protectedpages-performer": "सुरक्षित करने वाला सदस्य",
        "protectedpages-params": "सुरक्षा प्राचल",
        "protectedpages-reason": "कारण",
+       "protectedpages-submit": "पृष्ठों को दिखाओ",
        "protectedpages-unknown-timestamp": "अज्ञात",
        "protectedpages-unknown-performer": "अज्ञात सदस्य",
        "protectedtitles": "सुरक्षित शीर्षक",
        "protectedtitles-summary": "यह पृष्ठ उन पृष्ठ शीर्षकों की सूची देता है जिन्हें अभी बनाने से सुरक्षित किया गया है। सुरक्षित मौजूदा पृष्ठों की सूची देखने के लिए [[{{#special:ProtectedPages}}|{{int:protectedpages}}]] देखें।",
        "protectedtitlesempty": "इन नियमों द्वारा कोई भी शीर्षक सुरक्षित नहीं हैं।",
+       "protectedtitles-submit": "शीर्षकों को दिखाओ",
        "listusers": "सदस्यसूची",
        "listusers-editsonly": "केवल संपादन कर चुके सदस्य दिखाएँ",
        "listusers-creationsort": "निर्माण तिथि के आधार पर क्रमांकन करें",
        "nopagetext": "आपके द्वारा लक्षित पृष्ठ मौजूद नहीं है।",
        "pager-newer-n": "{{PLURAL:$1|नया|नये}} $1",
        "pager-older-n": "{{PLURAL:$1|पुराना|पुराने}} $1",
-       "suppress": "à¤\93वरसाà¤\87à¤\9f",
+       "suppress": "à¤\9bà¥\81पाना",
        "querypage-disabled": "प्रदर्शन कारणों से यह विशेष पृष्ठ अक्षम किया गया है।",
-       "apihelp": "ए पी आई सहाएता",
+       "apihelp": "एपीआई सहायता",
        "apihelp-no-such-module": "मॉड्यूल \"$1\" नहीं मिला",
        "apisandbox": "ए॰पी॰आइ प्रयोगस्थल",
+       "apisandbox-jsonly": "एपीआई प्रयोगपृष्ठ का उपयोग करने हेतु जावास्क्रिप्ट अनिवार्य है।",
        "apisandbox-api-disabled": "इस स्थल पर ए०पी०आई० सक्षम नहीं हैं।",
-       "apisandbox-intro": "याद रखिए कि, हालांकि यह प्रयोगपृष्ठ है, इस पृष्ठ पर किए गए आपके काम इस विकि में बदलाव ला सकते हैं।",
+       "apisandbox-intro": "इस पृष्ठ का उपयोग <strong>मीडियाविकि वेब एपीआई</strong> के लिए करें। इसके उपयप्ग हेतु देखें: [[mw:API:Main page|एपीआई प्रलेखन]] उदाहरण: [//www.mediawiki.org/wiki/API#A_simple_example मुख्यपृष्ठ के सामग्री हेतु]",
+       "apisandbox-fullscreen": "विस्तार करें",
+       "apisandbox-fullscreen-tooltip": "ब्राउज़र को पूरी तरह भरने हेतु विस्तार करें।",
        "apisandbox-unfullscreen": "पृष्ठ दिखाएँ",
+       "apisandbox-unfullscreen-tooltip": "प्रयोगपृष्ठ हिस्से को छोटा करें, जिससे मीडियाविकि के संचरण कड़ी उपलब्ध हो जाएगा।",
        "apisandbox-submit": "अनुरोध करें",
        "apisandbox-reset": "स्पष्ट",
        "apisandbox-retry": "दुबारा प्रयास करें",
-       "apisandbox-examples": "Example",
+       "apisandbox-loading": "एपीआई मॉड्यूल के द्वारा जानकारी लोड कर रहा \"$1\"...",
+       "apisandbox-load-error": "एपीआई मॉड्यूल के जानकारी लोड करते समय त्रुटि हुई \"$1\": $2",
+       "apisandbox-no-parameters": "इस एपीआई मॉड्यूल का कोई प्राचल नहीं है।",
+       "apisandbox-helpurls": "सहायता कड़ी",
+       "apisandbox-examples": "उदाहरण",
+       "apisandbox-dynamic-parameters": "अन्य प्राचल",
+       "apisandbox-dynamic-parameters-add-label": "प्राचल जोड़ें:",
+       "apisandbox-dynamic-parameters-add-placeholder": "प्राचल नाम",
+       "apisandbox-dynamic-error-exists": "प्राचल नाम \"$1\" पहले से मौजूद है।",
+       "apisandbox-deprecated-parameters": "प्राचल पुराना हो चुका है",
+       "apisandbox-fetch-token": "टोकन स्वतः भरें",
+       "apisandbox-submit-invalid-fields-title": "कुछ जगह अमान्य है",
+       "apisandbox-submit-invalid-fields-message": "कृपया चिन्हित जगह को ठीक कर दुबारा प्रयास करें।",
        "apisandbox-results": "परिणाम",
+       "apisandbox-sending-request": "एपीआई अनुरोध भेज रहा...",
+       "apisandbox-loading-results": "एपीआई परिणाम ले रहा...",
+       "apisandbox-results-error": "एपीआई के समय कोई त्रुटि हुई: $1",
        "apisandbox-request-url-label": "अनुरोध URL:",
-       "apisandbox-request-time": "अनुरोध समय: $1",
+       "apisandbox-request-time": "अनुरोध समय: {{PLURAL:$1|$1 मि}}",
+       "apisandbox-results-fixtoken": "टोकन सही करें और दोबारा भेजें।",
+       "apisandbox-results-fixtoken-fail": "टोकन \"$1\" डालने में विफल",
+       "apisandbox-alert-page": "इस पृष्ठ के जगह अमान्य है।",
+       "apisandbox-alert-field": "जगह में डाला गया जानकारी अमान्य है।",
        "booksources": "पुस्तकों के स्रोत",
        "booksources-search-legend": "पुस्तकों के स्रोत खोजें",
        "booksources-isbn": "आइ॰एस॰बी॰एन:",
        "booksources-text": "नीचे पुरानी और नई पुस्तकें बेचने वाली वेबसाइटों के एड्रेस हैं, जिसमें आपको आप द्वारा खोजी जाने वाली पुस्तक के बारे में अधिक जानकारी मिल सकती है:",
        "booksources-invalid-isbn": "यह आइ॰एस॰बी॰एन सही नहीं लग रहा है; मूल स्रोत से नकल करने में हुई त्रुटि के लिए जाँचें।",
        "specialloguserlabel": "कर्ता:",
-       "speciallogtitlelabel": "प्रयोजन (शीर्षक अथवा सदस्यनाम):",
+       "speciallogtitlelabel": "प्रयोजन (शीर्षक अथवा {{ns:सदस्यनाम}}:सदस्य नाम):",
        "log": "लॉग",
        "logeventslist-submit": "दिखाएँ",
        "all-logs-page": "सभी सार्वजनिक लॉग",
        "log-edit-tags": "चुने गए लॉग प्रविक्तियों एक सम्पादन टैग",
        "checkbox-select": "चुनें: $1",
        "checkbox-all": "सभी",
+       "checkbox-none": "कोई नहीं",
+       "checkbox-invert": "बदलें",
        "allpages": "सभी पृष्ठ",
        "nextpage": "अगला पृष्ठ ($1)",
        "prevpage": "पिछला पृष्ठ ($1)",
        "listgrouprights-namespaceprotection-header": "नामस्थान की बंदिशें",
        "listgrouprights-namespaceprotection-namespace": "नामस्थान",
        "listgrouprights-namespaceprotection-restrictedto": "उपयोगकर्ता को सम्पादन करने में सक्षम करने वाले अधिकार",
+       "listgrants": "प्रदान",
+       "listgrants-summary": "यह प्रदान की गई सूची है। सदस्य अपने खाते को अनुपयोग के द्वारा उपयोग कर सकते हैं, लेकिन केवल कुछ सीमित अधिकार तक ही। यह अधिकार सदस्य द्वारा दिया गया अधिकार तक ही सीमित रहता है। यहाँ [[{{MediaWiki:Listgrouprights-helppage}}|अन्य जानकारी]] भी है, जो एक अधिकार के बारे में बताता है। \\",
+       "listgrants-grant": "अधिकार",
+       "listgrants-rights": "अधिकार",
        "trackingcategories": "चिह्नित श्रेणियाँ",
        "trackingcategories-summary": "इस पृष्ठ पर उन जोड़ने वाली श्रेणियों की सूची मिलती है जो स्वतः रूप से मीडियाविकि सॉफ़्टवेयर द्वारा बनते हैं। उनके नाम सम्बंधित प्रणालि सन्देश को बदलने से {{ns:8}} नामस्थान में बदले जा सकते हैं।",
        "trackingcategories-msg": "चिह्नित श्रेणी",
        "defemailsubject": "{{SITENAME}} ई-मेल \"$1\" सदस्य से",
        "usermaildisabled": "सदस्य ई-मेल अक्षम किया गया",
        "usermaildisabledtext": "आप इस विकि पर ई-मेल अन्य सदस्यों को ई-मेल नहीं भेज सकते हैं",
-       "noemailtitle": "à¤\95à¥\8bà¤\88 à¤\88-मà¥\87ल à¤\8fडà¥\8dरà¥\87स नहीं",
+       "noemailtitle": "à¤\95à¥\8bà¤\88 à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ नहीं",
        "noemailtext": "इस सदस्य ने वैध ई-मेल पता नहीं दिया है।",
        "nowikiemailtext": "इस सदस्य ने अन्य सदस्यों से ई-मेल न प्राप्त करने का फ़ैसला लिया हुआ है।",
        "emailnotarget": "प्राप्तकर्ता के लिए अस्तित्वहीन या अमान्य सदस्यनाम।",
        "emailtarget": "प्राप्तकर्ता का सदस्यनाम भरें",
        "emailusername": "सदस्यनाम:",
-       "emailusernamesubmit": "à¤\9cमा à¤\95रें",
+       "emailusernamesubmit": "भà¥\87à¤\9cें",
        "email-legend": "किसी और {{SITENAME}} सदस्य को ई-मेल भेजें",
        "emailfrom": "प्रेषक:",
        "emailto": "प्राप्तकर्ता:",
        "emailccsubject": "आपके ई-मेल की प्रति जो $1 को भेजा गया: $2",
        "emailsent": "ई-मेल भेज दिया गया है।",
        "emailsenttext": "आपका ई-मेल संदेश भेज दिया गया है।",
-       "emailuserfooter": "इस ई-मेल को $1 द्वारा $2 को भेजा गया था जिसके लिए \"{{int:emailuser}}\" कार्य को {{SITENAME}} पर प्रयोग में लाया गया था।",
+       "emailuserfooter": "इस ई-मेल को $1 {{GENDER:$1|द्वारा}} {{GENDER:$2|$2}} को भेजा गया था जिसके लिए \"{{int:emailuser}}\" कार्य को {{SITENAME}} पर प्रयोग में लाया गया था।",
        "usermessage-summary": "प्रणाली सन्देश छोड़ रहा है।",
        "usermessage-editor": "सिस्टम दूत",
        "watchlist": "ध्यानसूची",
        "watchlistanontext": "अपनी ध्यानसूची में मौजूद पृष्ठ देखने या फिर संपादित करने के लिये कॄपया लॉग इन करें।",
        "watchnologin": "लॉग इन नहीं किया है",
        "addwatch": "ध्यानसूची में जोड़ें",
-       "addedwatchtext": "à¤\86पà¤\95à¥\80 [[Special:Watchlist|धà¥\8dयानसà¥\82à¤\9aà¥\80]] à¤®à¥\87à¤\82 \"[[:$1]]\" à¤ªà¥\83षà¥\8dठ à¤\9cà¥\8bड़ à¤¦à¤¿à¤¯à¤¾ à¤\97या à¤¹à¥\88।\nभविषà¥\8dय à¤®à¥\87à¤\82 à¤\87स à¤ªà¥\83षà¥\8dठ à¤¤à¤¥à¤¾ à¤\87सà¤\95à¥\87 à¤µà¤¾à¤°à¥\8dता à¤ªà¥\83षà¥\8dठ à¤®à¥\87à¤\82 à¤¹à¥\8bनà¥\87 à¤µà¤¾à¤²à¥\87 à¤¬à¤¦à¤²à¤¾à¤µ à¤\86पà¤\95à¥\80 à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤¦à¤¿à¤\96à¥\87à¤\82à¤\97à¥\87।",
+       "addedwatchtext": "à¤\86पà¤\95à¥\80 [[Special:Watchlist|धà¥\8dयानसà¥\82à¤\9aà¥\80]] à¤®à¥\87à¤\82 \"[[:$1]]\" à¤\94र à¤\87सà¤\95à¥\87 à¤\9aरà¥\8dà¤\9aा à¤ªà¥\83षà¥\8dठ à¤\9cà¥\8bड़ à¤¦à¤¿à¤\8f à¤\97à¤\8f à¤¹à¥\88à¤\82।",
        "addedwatchtext-short": "पृष्ठ \"$1\" को आपकी ध्यानसूची से जोड़ा गया है।",
        "removewatch": "ध्यानसूची से हटाएँ",
        "removedwatchtext": "\"[[:$1]]\" नामक पृष्ठ को आपकी [[Special:Watchlist|ध्यानसूची]] से हटा दिया गया है।",
        "wlshowhideanons": "अनाम प्रयोक्ता",
        "wlshowhidepatr": "परीक्षित सम्पादन",
        "wlshowhidemine": "मेरा संपादन",
+       "wlshowhidecategorization": "पृष्ठ श्रेणीकरण",
        "watchlist-options": "ध्यानसूची विकल्प",
        "watching": "ध्यान दे रहे हैं...",
        "unwatching": "ध्यान हटा रहे हैं...",
        "deletepage": "पृष्ठ हटाएँ",
        "confirm": "सुनिश्चित करें",
        "excontent": "पाठ था: '$1'",
-       "excontentauthor": "पाठ था: '$1' (और सिर्फ '[[Special:Contributions/$2|$2]]' का योगदान था।)",
+       "excontentauthor": "पाठ था: '$1' (और सिर्फ '[[Special:Contributions/$2|$2]]' का योगदान था। ([[User talk:$2|वार्ता]])",
        "exbeforeblank": "खाली करने से पहले पाठ था: '$1'",
        "delete-confirm": "\"$1\" को हटाएँ",
        "delete-legend": "हटाएँ",
        "changecontentmodel-title-label": "पृष्ठ शीर्षक",
        "changecontentmodel-model-label": "नयि सामग्री का नमूना",
        "changecontentmodel-reason-label": "कारण:",
+       "changecontentmodel-submit": "परिवर्तन",
        "changecontentmodel-success-title": "सामगरि का नामुने मे बदलाव हुुुाा हेेे",
        "changecontentmodel-success-text": "[[:$1]] के सामग्री का प्रकार परिवर्तित हुआ।",
        "changecontentmodel-cannot-convert": "[[:$1]] की सामग्री का प्रकार $2 में नहीं बदल सकता है।",
        "changecontentmodel-nodirectediting": "$1 सामग्री सीधे सम्पादन समर्थित नहीं करता है",
        "log-name-contentmodel": "सामाग्री परिवर्तन लॉग",
        "log-description-contentmodel": "आयोजन जो इस पृष्ठ के सामग्री से मिलते जुलते हैं",
+       "logentry-contentmodel-new": "$1 ने  $3 पृष्ठ का {{GENDER:$2|निर्माण}} किया बिना मूल सामग्री प्रारूप के \"$5\"",
        "logentry-contentmodel-change": "$1 ने $3 पृष्ठ का सामग्री \"$4\" से \"$5\" {{GENDER:$2|परिवर्तित किया}}",
        "logentry-contentmodel-change-revertlink": "पूर्ववत करें",
        "logentry-contentmodel-change-revert": "पूर्ववत करें",
        "contribsub2": "{{GENDER:$3|$1}} ($2) के लिये",
        "contributions-userdoesnotexist": "उपयोगकर्ता खाता  \"$1\" पंजीकृत नहीं है।",
        "nocontribs": "इन कसौटियों से मिलनेवाले बदलाव मिले नहीं।",
-       "uctop": "(मà¥\8cà¤\9cà¥\82दा)",
+       "uctop": "(वरà¥\8dतमान)",
        "month": "इस महिनेसे (और पुरानें):",
        "year": "इस सालसे (और पुराने):",
        "sp-contributions-newbies": "सिर्फ़ नये सदस्यों के योगदान दर्शायें",
        "sp-contributions-blocked-notice": "यह सदस्य फ़िलहाल अवरोधित हैं। सदंर्भ के लिए ताज़ातरीन अवरोध चिट्ठा प्रविष्टि नीचे है:",
        "sp-contributions-blocked-notice-anon": "यह आईपी पता अभी अवरोधित है। \nनवीनतम अवरोध अभिलेख प्रविष्टि सन्दर्भ के लिए नीचे दी गई है:",
        "sp-contributions-search": "योगदान के लिये खोज",
-       "sp-contributions-username": "à¤\86à¤\88पà¥\80 à¤\8fडà¥\8dरà¥\87स या सदस्यनाम:",
+       "sp-contributions-username": "à¤\86à¤\88पà¥\80 à¤ªà¤¤à¤¾ या सदस्यनाम:",
        "sp-contributions-toponly": "केवल उन सम्पादनों को दिखाएँ जो नवीनतम संशोधन हैं",
        "sp-contributions-newonly": "केवल वे सम्पादन दिखाएँ जिनसे पृष्ठ निर्मित हुए हों",
        "sp-contributions-submit": "खोजें",
        "whatlinkshere-hidelinks": "$1 कड़ियाँ",
        "whatlinkshere-hideimages": "$1 फ़ाइल लिंक",
        "whatlinkshere-filters": "छन्ने",
+       "whatlinkshere-submit": "जायें",
        "autoblockid": "स्वतः अवरोध #$1",
        "block": "उपयोक्ता को अवरोधित करें।",
        "unblock": "उपयोक्ता पर अवरोधण हटाएँ",
        "ipb-unblock": "सदस्य अथवा आईपी एड्रेस को अनब्लॉक करें",
        "ipb-blocklist": "सद्य ब्लॉक देखें",
        "ipb-blocklist-contribs": "{{GENDER:$1|$1}} के लिए योगदान",
+       "ipb-blocklist-duration-left": "$1 बाकी",
        "unblockip": "सदस्य को अनब्लॉक करें",
        "unblockiptext": "पहले ब्लॉक किये हुए आईपी एड्रेस या सदस्यनाम को अनब्लॉक करने के लिये नीचे दिया गया फार्म भरें।",
        "ipusubmit": "यह अवरोध हटाएँ",
        "block-log-flags-hiddenname": "सदस्य नाम छिपा हुआ",
        "range_block_disabled": "प्रबंधकोंको अब रेंज ब्लॉक करने की अनुमति नहीं हैं।",
        "ipb_expiry_invalid": "अवैध समाप्ति कालावधी।",
+       "ipb_expiry_old": "समाप्ती समय बीत चुका है।",
        "ipb_expiry_temp": "छुपायें हुए सदस्यनाम ब्लॉक्स हमेशा के लिये होने चाहिये।",
        "ipb_hide_invalid": "इस खाते को छिपा नहीं पाए; इस से {{PLURAL:$1|एक सम्पादन किया गया है|$1 सम्पादन किये गये हैं}}।",
        "ipb_already_blocked": "\"$1\" को पहलेसे ब्लॉक हैं",
        "cant-move-to-user-page": "आपको किसी पन्नो को सदस्य पृष्ठ पर ले जाने की अनुमति नहीं है (सिवाय सदस्य उप पृष्ठ के)",
        "cant-move-category-page": "आपको श्रेणी प्रष्ठों को स्थानांतरित करने की अनुमति नहीं है।",
        "cant-move-to-category-page": "आपको किसी पृष्ठ को श्रेणी पृष्ठ पर स्थानांतरित करने की अनुमति नहीं है।",
-       "newtitle": "नयà¥\87 à¤¶à¥\80रà¥\8dषà¤\95 à¤\95à¥\80 à¤\93र:",
+       "newtitle": "नया à¤¶à¥\80रà¥\8dषà¤\95:",
        "move-watch": "ध्यान रखें",
        "movepagebtn": "नाम बदलें",
        "pagemovedsub": "नाम बदल दिया गया है",
        "export-download": "फ़ाईलके रुपमें सेव करें",
        "export-templates": "टेम्प्लेटस भी जोडें",
        "export-pagelinks": "जिन पन्नों के हवाले यहाँ हैं, उन्हें भी इस गहराई तक शामिल करें:",
+       "export-manual": "स्वयं से पृष्ठ जोड़ें:",
        "allmessages": "व्यवस्था संदेश",
        "allmessagesname": "नाम",
        "allmessagesdefault": "डिफॉल्ट पाठ",
        "thumbnail_gd-library": "अवैध जीडी लाइब्रेरी जमाव: कार्यसमूह $1 मौजूद नहीं है",
        "thumbnail_image-missing": "लगता है संचिका नामौजूद है: $1",
        "thumbnail_image-failure-limit": "हाल के समय में इस थंबनेल को दूसरा रूप देने के कई असफल प्रयास हुए हैं ($1 या उससे अधिक) । कृपया फिर से प्रयास कुछ समय बाद कीजिए।",
-       "import": "पà¥\83षà¥\8dठ à¤\87मà¥\8dपà¥\8bरà¥\8dà¤\9f करें",
-       "importinterwiki": "किसी और विकि से आयात करे",
+       "import": "पà¥\83षà¥\8dठ à¤\86यात करें",
+       "importinterwiki": "किसी और विकि से आयात करे",
        "import-interwiki-text": "आयात करने के लिये एक विकि और एक पृष्ठ चुनें।\nअवतरण दिनांक और संपादक नाम ज्यों-के-त्यों रखे जाएँगे।\nअन्य विकि से सभी आयात [[Special:Log/import|आयात लॉग]] में डाली जाती हैं।",
        "import-interwiki-sourcewiki": "स्रोत विकि:",
        "import-interwiki-sourcepage": "स्रोत पृष्ठ:",
        "import-logentry-upload-detail": "$1 अवतरण आयात {{PLURAL:$1|किया गया|किये गए}}",
        "import-logentry-interwiki-detail": "$2 से $1 अवतरण आयात {{PLURAL:$1|किया गया|किये गए}}",
        "javascripttest": "जावास्क्रिप्ट परीक्षण",
-       "javascripttest-pagetext-noframework": "यह पृष्ठ जावास्क्रिप्ट परीक्षण चलाने के लिए है।",
-       "javascripttest-pagetext-unknownframework": "अज्ञात परीक्षण ढाँचा \"$1\"",
        "javascripttest-pagetext-unknownaction": "अज्ञात क्रिया \"$1\" ।",
-       "javascripttest-pagetext-frameworks": "कृपया निम्न परीक्षण ढाँचों में से एक चुनें: $1",
-       "javascripttest-pagetext-skins": "परीक्षण करने के लिए त्वचा चुनें:",
        "javascripttest-qunit-intro": "mediawiki.org पर [$1 परीक्षण के प्रलेखन] देखें।",
        "tooltip-pt-userpage": "{{GENDER:|आपका प्रयोक्ता}} पृष्ठ",
        "tooltip-pt-anonuserpage": "आप जिस आईपी से बदलाव कर रहें हैं उसका सदस्य पान",
        "tooltip-pt-preferences": "{{GENDER:|आपकी}} वरीयताएँ",
        "tooltip-pt-watchlist": "आपने ध्यान दिये हुए पन्नोंकी सूची",
        "tooltip-pt-mycontris": "आपके योगदानों की सूची",
+       "tooltip-pt-anoncontribs": "इस आईपी पते से संपादन की सूची",
        "tooltip-pt-login": "आपको सत्रारम्भ करने के लिए प्रोत्साहित किया जाता है; लेकिन यह अनिवार्य नहीं है",
-       "tooltip-pt-logout": "सतà¥\8dराà¤\82त",
+       "tooltip-pt-logout": "पà¥\8dरसà¥\8dथान",
        "tooltip-pt-createaccount": "हमारा सुझाव है की आप खाता बनाएँ और लॉगिन करें, परन्तु यह अनिवार्य नहीं है",
        "tooltip-ca-talk": "सामग्री पृष्ठ के बारे में वार्तालाप",
        "tooltip-ca-edit": "यह पृष्ठ संपादित करें",
        "tooltip-t-recentchangeslinked": "यहाँ जुड़े हुए सभी पन्नों में हुए हाल के बदलाव",
        "tooltip-feed-rss": "इस पृष्ठ की आरएसएस फ़ीड",
        "tooltip-feed-atom": "इस पृष्ठ की अणु फ़ीड",
-       "tooltip-t-contributions": "इस सदस्य के योगदान की सूची",
-       "tooltip-t-emailuser": "इस सदस्य को इमेल भेजें",
+       "tooltip-t-contributions": "{{GENDER:$1|इस सदस्य}} के योगदाओं की सूची",
+       "tooltip-t-emailuser": "{{GENDER:$1|इस सदस्य}} को इमेल भेजें",
        "tooltip-t-info": "इस पृष्ठ के बारे में अधिक जानकारी",
        "tooltip-t-upload": "फ़ाइल अपलोड करें",
        "tooltip-t-specialpages": "सभी विशेष पृष्ठों की सूची",
        "tooltip-preferences-save": "वरीयताएं सहेजें",
        "tooltip-summary": "एक संक्षिप्त सारांश दर्ज करें",
        "common.css": "/* यहां रखी css सभी त्वचाओंपर असर करेगी */",
+       "print.css": "/* CSS यहाँ डालने से यह प्रिंट निकालते समय ही प्रभावी होगा। */",
+       "noscript.css": "/* CSS यहाँ डालने से यह केवल जावास्क्रिप्ट निष्क्रिय सदस्यो पर ही प्रभावी होगा। */",
+       "group-autoconfirmed.css": "/* CSS यहाँ डालने से यह केवल स्वतः स्थापित सदस्यो पर ही प्रभावी होगा। */",
+       "group-user.css": "/* CSS यहाँ डालने से यह केवल पंजीकृत सदस्यो पर ही प्रभावी होगा। */",
+       "group-bot.css": "/* CSS यहाँ डालने से यह केवल बॉट सदस्यो पर ही प्रभावी होगा। */",
+       "group-sysop.css": "/* CSS यहाँ डालने से यह केवल प्रबन्धकों पर ही प्रभावी होगा। */",
+       "group-bureaucrat.css": "/* CSS यहाँ डालने से यह केवल प्रशासकों सदस्यो पर ही प्रभावी होगा। */",
        "common.js": "/* यहां लिखी गई जावास्क्रीप्ट सभी सदस्योंके लिये इस्तेमाल में लाई जायेगी। */",
+       "group-autoconfirmed.js": "/* जावास्क्रिप्ट यहाँ डालने से यह केवल स्वतः स्थापित सदस्यो पर ही प्रभावी होगा। */",
+       "group-user.js": "/* जावास्क्रिप्ट यहाँ डालने से यह केवल पंजीकृत सदस्यो पर ही प्रभावी होगा। */",
+       "group-bot.js": "/* जावास्क्रिप्ट यहाँ डालने से यह केवल बॉट सदस्यो पर ही प्रभावी होगा। */",
+       "group-sysop.js": "/* जावास्क्रिप्ट यहाँ डालने से यह केवल प्रबन्धकों पर ही प्रभावी होगा। */",
+       "group-bureaucrat.js": "/* जावास्क्रिप्ट यहाँ डालने से यह केवल प्रशासकों पर ही प्रभावी होगा। */",
        "anonymous": "{{SITENAME}} के {{PLURAL:$1||}} बेनामी सदस्य",
        "siteuser": "विकिपीडिया सदस्य  $1",
        "anonuser": "{{SITENAME}} अज्ञात उपयोगकर्ता $1",
        "lastmodifiedatby": "इस पृष्ठ का आखिरी बदलाव $3 ने $2, $1 पर किया।",
        "othercontribs": "$1 के कार्य के अनुसार।",
        "others": "अन्य",
-       "siteusers": "{{SITENAME}} {{PLURAL:$2|सदस्य|सदस्य}} $1",
+       "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|सदस्य}}|सदस्य}} $1",
        "anonusers": "{{SITENAME}} अनाम {{PLURAL:$2|सदस्य|सदस्य}} $1",
        "creditspage": "पान श्रेय नामावली",
        "nocredits": "इस पृष्ठ के लिये क्रेडिट जानकारी नहीं है।",
        "pageinfo-category-files": "फ़ाइलों की संख्या",
        "markaspatrolleddiff": "जाँचा हुआ चिन्हित करें",
        "markaspatrolledtext": "इस पृष्ठ को जाँचा हुआ चिन्हित करें",
+       "markaspatrolledtext-file": "इस फ़ाइल संस्करण को जांचा हुआ चिन्हित करें",
        "markedaspatrolled": "जाँचा हुआ चिन्हित किया",
        "markedaspatrolledtext": "[[:$1]] का चयनित अवतरण जाँचा हुआ चिन्हित किया गया।",
        "rcpatroldisabled": "हाल में हुए बदलावों का परीक्षण अक्षम है",
        "newimages-legend": "छननी",
        "newimages-label": "संचिका नाम (या उसका अंश):",
        "newimages-showbots": "बॉट के अपलोड दिखाइये",
+       "newimages-hidepatrolled": "जाँचा हुआ अपलोड छुपाएँ",
        "noimages": "देखने के लिए कुछ नहीं है।",
        "ilsubmit": "खोजें",
        "bydate": "तिथि अनुसार",
        "metadata-expand": "विस्तृत जानकारियां दिखाएं",
        "metadata-collapse": "विस्तृत जानकारियां छिपाएं",
        "metadata-fields": "जब मेटाडाटा तालिका को लघुरूप किया जाएगा तो इस सन्देश में सूचीबद्ध इएक्सआयएफ मेटाडाटा जानकारियां छवि प्रदर्शित होते समय सम्मिलित की जाएंगी।\nअन्य डिफ़ॉल्ट रूप से छिपी रहेंगी।\n* make \n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
-       "exif-imagewidth": "चौडाई",
+       "exif-imagewidth": "à¤\9aà¥\8cड़ाà¤\88",
        "exif-imagelength": "ऊँचाई",
        "exif-bitspersample": "प्रति घटक बीट्स",
        "exif-compression": "कम्प्रेशन योजना",
        "exif-compression-4": "CCITT ग्रुप 4 फ़ैक्स एनकोडिंग",
        "exif-copyrighted-true": "कॉपीराईट",
        "exif-copyrighted-false": "कॉपीराइट स्थिति अनिर्दिष्ट",
+       "exif-photometricinterpretation-0": "काला और सफेद (सफेद 0 है)",
+       "exif-photometricinterpretation-1": "काला और सफेद (काला 0 है)",
        "exif-unknowndate": "अज्ञात तारीख",
        "exif-orientation-1": "सामान्य",
        "exif-orientation-2": "हॉरिज़ॉन्टली बदला",
        "confirmrecreate": "सदस्य [[User:$1|$1]] ([[User talk:$1|वार्ता]]) ने आपके द्वारा संपादन शुरू होने के बाद यह पृष्ठ निम्नलिखित कारण देकर हटाया हैं:\n: ''$2''\nक्या आप इसे फिरसे बनाना चाहतें हैं, इसकी निश्चिती करें।",
        "confirmrecreate-noreason": "जब आपने इस पृष्ठ का सम्पादन शुरू किया था, उसके बाद से सदस्य [[User:$1|$1]] ([[User talk:$1|talk]]) ने इसे हटा दिया है।  कृपया पुष्टि करें कि आप इस पृष्ठ को पुनः बनाना चाहते हैं।",
        "recreate": "फिरसे बनायें",
+       "unit-pixel": "px",
        "confirm_purge_button": "ओके",
        "confirm-purge-top": "क्या आप यह पृष्ठ का कैश ख़ाली करने चाहिए?",
        "confirm-purge-bottom": "किसी पृष्ठ को मिटाने से संचिका साफ़ हो जाती है और इस वजह से ताज़ातरीन संस्करण प्रकट हो जाता है।",
        "iranian-calendar-m10": "डे",
        "iranian-calendar-m11": "बाहमान",
        "iranian-calendar-m12": "एसफण्ड (Esfand)",
+       "hijri-calendar-m1": "मुहर्रम",
+       "hijri-calendar-m2": "सफर",
        "hebrew-calendar-m1": "तिश्रेई (Tishrei)",
        "hebrew-calendar-m2": "शेस्वान (Cheshvan)",
        "hebrew-calendar-m3": "किस्लेव (Kislev)",
        "version-libraries-description": "विवरण",
        "version-libraries-authors": "लेखक",
        "redirect": "अनुप्रेषित करें फ़ाइल, उपयोगकर्ता, या संशोधन पहचान के आधार पर",
-       "redirect-legend": "फ़ाइल अथवा पृष्ठ को पुनर्प्रेषण",
        "redirect-summary": "यह विशेष पृष्ठ फ़ाइलनाम प्रदान करने पर फ़ाइल नाम को, पृष्ठ आइ॰दी अथवा अवतरण आइ॰दी देने पर पृष्ठ को, और सदस्य आइ॰दी देने पर सदस्य पृष्ठ को पुनर्प्रेषित करता है। उदाहरण: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], या [[{{#Special:Redirect}}/user/101]]।",
        "redirect-submit": "जायें",
        "redirect-lookup": "ढूँढें:",
        "redirect-page": "पृष्ठ आइ॰डी",
        "redirect-revision": "पृष्ठ अवतरण संख्या",
        "redirect-file": "फ़ाइल नाम",
+       "redirect-logid": "प्रवेश आईडी",
        "redirect-not-exists": "यह मान प्राप्त नहीं हुआ",
        "fileduplicatesearch": "फ़ाईल द्विरावृत्ति खोजें",
        "fileduplicatesearch-summary": "हैश वैल्यू के अनुसार फ़ाईल की द्विरावृत्ति खोजें।",
        "tags-deactivate": "निष्क्रिय करें",
        "tags-hitcount": "$1 {{PLURAL:$1|बदलाव|बदलाव}}",
        "tags-manage-no-permission": "आपको बदलाव टैग के प्रबंधन की अनुमति नहीं है।",
+       "tags-manage-blocked": "आप प्रतिबंधित रहते समय टैग में कोई जोड़ना या हटाने का कार्य नहीं कर सकते हैं।",
        "tags-create-heading": "नया टैग बनाएँ",
        "tags-create-explanation": "पुनः निर्धारित रूप से, नवनिर्मित टैग उपयोगकर्ताओं और बॉट के लिए मौजूद रहेंगे।",
        "tags-create-tag-name": "चिप्पी का नाम",
        "tags-deactivate-not-allowed": "टैग \"$1\" को असक्रिय करना सम्भव नहीं है।",
        "tags-deactivate-submit": "निष्क्रिय करें",
        "tags-apply-no-permission": "आपको अनुमति नहीं है कि बदलाव टैगों को अपने बदलावों से जोड़ें।",
+       "tags-apply-blocked": "आप प्रतिबंधित रहते समय टैग में कोई बदलाव नहीं कर सकते हैं।",
        "tags-apply-not-allowed-one": "टैग \"$1\" मानवीय रूप से जोड़े जाने की अनुमति नहीं है।",
        "tags-apply-not-allowed-multi": "निम्न लिखित {{PLURAL:$2|टैग की अनुमति नहीं है|टैगों की अनुमति नहीं है}} कि उसे मानवीय रूप से प्रयोग में लाया जाए: $1",
        "tags-update-no-permission": "आपको व्यक्तिगत संशोधनों या लॉग प्रविष्टियों से बदलाव टैग जोड़ने या उन्हें हटाने की अनुमति नहीं है।",
+       "tags-update-blocked": "आप प्रतिबंधित रहते समय टैग में कोई जोड़ना या हटाने का कार्य नहीं कर सकते हैं।",
        "tags-update-add-not-allowed-one": "टैग \"\"$1\" को मानवीय रूप से जोड़ा नहीं जा सकता",
        "tags-update-add-not-allowed-multi": "निम्न लिखित {{PLURAL:$2|टैग|या टैगों का समूह}} मानवीय रूप से जोड़ा नहीं जा सकता है: $1",
        "tags-update-remove-not-allowed-one": "टैग \"$1\" को हटाए जाने की अनुमति नहीं है।",
        "tags-edit-revision-legend": "टैगों को {{PLURAL:$1|इस संशोधन|सभी $1 संशोधनों}} से जोड़िये या हटाइये।",
        "tags-edit-logentry-legend": "टैगों को {{PLURAL:$1|इस लॉग प्रविष्टि|सभी $1 लॉग प्रविष्टियों}} से जोड़िए या हटाइये।",
        "tags-edit-existing-tags": "मौजूद टैग",
-       "tags-edit-existing-tags-none": "\"कुछ भी नहीं\"",
+       "tags-edit-existing-tags-none": "<em>कुछ नहीं</em>",
        "tags-edit-new-tags": "नए टैग",
        "tags-edit-add": "इन टैगों को जोड़िए:",
        "tags-edit-remove": "इन टैगों को हटाएँ",
        "tags-edit-reason": "कारण:",
        "tags-edit-revision-submit": "बदलाव जोड़िए {{PLURAL:$1|इस अवतरण|$1 अवतरण}}",
        "tags-edit-logentry-submit": "बदलाव जोड़िए {{PLURAL:$1|इस लौग प्रवक्ति|$1 लॉग प्रवक्तियाँ}}",
-       "tags-edit-success": "बदलाव à¤¸à¤«à¤²à¤¤à¤¾ à¤ªà¥\82रà¥\8dवà¤\95 à¤\9cà¥\8bड़à¥\87 à¤\9cा à¤\9aà¥\81à¤\95à¥\87 à¤¹à¥\88à¤\82।",
+       "tags-edit-success": "बदलाव à¤¸à¤«à¤²à¤¤à¤¾ à¤²à¤¾à¤\97à¥\82 à¤¹à¥\81à¤\88।",
        "tags-edit-failure": "बदलाव नहीं जोडे जा सके हैं: $1",
        "tags-edit-nooldid-title": "अवैध लक्ष्य का संशोधन",
        "tags-edit-nooldid-text": "या तो आपने किसी लक्षित संशोधन का विवरण नहीं दिया है जहाँ इस कार्य को सम्पन्न करना है, या विवरण किया गया संशोधन है ही नहीं।",
        "logentry-suppress-block": "$1 {{GENDER:$2|प्रतिबंधित}} {{GENDER:$4|$3}} जिसमें समय समाप्ति की अवधि है $5 $6",
        "logentry-suppress-reblock": "$1 {{GENDER:$2|बदल दिया गया}} प्रतिबंध सेटिंग {{GENDER:$4|$3}} के लिए जिसमें समय समाप्ति की अवधि है $5 $6",
        "logentry-import-upload": "$1 {{GENDER:$2|आयात किया गया}} $3 फ़ाइल अपलोड के माध्यम से",
+       "logentry-import-upload-details": "$1 ने फ़ाइल अपलोड द्वारा $3 को {{GENDER:$2|आयात}} किया ($4 {{PLURAL:$4|अवतरण|अवतरण}})",
        "logentry-import-interwiki": "$1 {{GENDER:$2|आयात किया गया}} $3 किसी और विकि से",
+       "logentry-import-interwiki-details": "$1 ने $5 से $3 को {{GENDER:$2|आयात}} किया ($4 {{PLURAL:$4|अवतरण|अवतरण}})",
        "logentry-merge-merge": "$1 {{GENDER:$2|विलय किया गया}} $3 को $4 में (संशोधन $5 तक)",
        "logentry-move-move": "$1 ने $3 पृष्ठ $4 पर {{GENDER:$2|स्थानांतरित}} किया",
        "logentry-move-move-noredirect": "$1 ने $3 पर पुनर्निर्देश छोड़े बिना उसे $4 पर {{GENDER:$2|स्थानांतरित}} किया",
        "feedback-adding": "पृष्ठ पर प्रतिक्रिया जोड़ना ...",
        "feedback-back": "पीछे जाएँ",
        "feedback-bugcheck": "शानदार! जांच ले कहीं ये [ $1 known bugs] पहले से ही न हो ।",
-       "feedback-bugnew": "मà¥\88à¤\82 à¤\9cाà¤\81à¤\9a à¤\95à¥\80या। एक नया बग रिपोर्ट करें",
+       "feedback-bugnew": "मà¥\88à¤\82 à¤\9cाà¤\81à¤\9a à¤\95िया, एक नया बग रिपोर्ट करें",
        "feedback-bugornote": "यदि आप किसी तकनीकी परेशानी को विस्तार से समझाने के लिये तैयार हैं तो कृपया [$1 बग फ़ाइल करें]।\nयदि नहीं, तो आप नीचे दिये सरल फ़ॉर्म का प्रयोग कर सकते हैं। आपकी टिप्पणी आपके सदस्य नाम और आपके ब्राउज़र के नाम के सहित \"[$3 $2]\" पृष्ठ में जोड़ दी जाएगी।",
        "feedback-cancel": "रद्द करें",
        "feedback-close": "हो गया",
        "api-error-unknownerror": "अज्ञात त्रुटि: \" $1 \"",
        "api-error-uploaddisabled": "इस विकि पर अपलोड अक्षम है.",
        "api-error-verification-error": "यह फ़ाइल दूषित हो सकती है, या गलत एक्सटेंशन है।",
+       "api-error-was-deleted": "इस नाम का फ़ाइल पहले अपलोड हुआ था और हट भी गया था।",
        "duration-seconds": "$1 {{PLURAL:$1|सॅकेंड}}",
        "duration-minutes": "$1 {{PLURAL:$1|मिनट}}",
        "duration-hours": "$1 {{PLURAL:$1|घंटा|घंटे}}",
        "expand_templates_preview": "झलक",
        "expand_templates_preview_fail_html": "<strong>अगर यह वैध पूर्ववावलोकन प्रयास है, तो फिर से प्रयास कीजिए।</strong>\nअगर इससे काम न बने तो [[Special:UserLogout|लॉग आउट होकर]] फिर से लॉग इन हो जाइये।",
        "expand_templates_preview_fail_html_anon": "<em>चूँकि {{SITENAME}} सीधे-साधे रूप से एचटीएमएल-सक्षम है और आप लॉग्ड इन नहीं है, पूर्वावलोकन छिपा हुआ है ताकि सम्भावित जावास्क्रिप्ट हमले को रोका सके।</em>\n\n<strong>अगर यह वैध पूर्वावलोकन प्रयास है तो कृपया [[Special:UserLogin|लॉग इन करके]] फिर से प्रयास कीजिए।</strong>",
-       "pagelanguage": "पृष्ठ भाषा चुनाव",
+       "expand_templates_input_missing": "आपको कम से कम कुछ पाठ्य प्रदान करने पड़ेंगे।",
+       "pagelanguage": "पृष्ठ भाषा बदलें",
        "pagelang-name": "पृष्ठ",
        "pagelang-language": "भाषा",
        "pagelang-use-default": "डिफ़ॉल्ट भाषा का प्रयोग करें",
        "pagelang-select-lang": "भाषा चुनें",
+       "pagelang-submit": "भेजें",
        "right-pagelang": "पृष्ठ भाषा बदलें",
        "action-pagelang": "पृष्ठ भाषा बदलने",
-       "log-name-pagelang": "पà¥\83षà¥\8dठ à¤­à¤¾à¤·à¤¾ à¤¬à¤¦à¤²à¤¾à¤µ à¤²à¥\89à¤\97",
+       "log-name-pagelang": "भाषा बदलाव लॉग",
        "log-description-pagelang": "यह पृष्ठ भाषाओं में परिवर्तन का लॉग है।",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|बदल दिया गया}} पृष्ठ भाषा को $3 के लिए $4 से $5 ।",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|बदल दिया गया}} पृष्ठ भाषा को $3 के लिए $4 से $5।",
        "default-skin-not-found": "ओह! आपकी विकि का पूर्व निर्धारित चमड़ा जैसा कि <code dir=\"ltr\">$wgDefaultSkin</code> में बताया गया है<code>$1</code>, उपलब्ध नहीं है।\n\nआपका इन्स्टालेशन इन चमड़ो को सम्मिलित करता है {{PLURAL:$4|चमड़ा|चमड़े}}। देखिए [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: चमड़ो का सम्मित करना] ताकि आपको जानकारी मिले कि कैसे {{PLURAL:$4|उसे|उनको सम्मिलित किया जाए और निर्धारित को तय करें}}.\n\n$2\n\n; अगर आपने अभी मीडियाविकि इन्स्टाल किया है:\n: आपने शायद गिट से इन्स्टाल किया है, या सीधे स्रोत कोड से किया है जिसके लिए कोई और तरीक़े का प्रयोग किया है। यह तो आशा के अनुरूप है। कोशिश कीजिए कि कुछ चमड़े [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's अमीडिया-विकि के चमड़े वाली डाइरेक्ट्री से डाउन्लोड करें], जिसके लिए आप:\n:* डाउनलोड कीजिए [https://www.mediawiki.org/wiki/Download तारबॉल इन्स्टालर], जो कई चमड़ों और विस्तारों में मौजूद है। आप चमड़ों का कोड <code>skins/</code> उसकी डाइरेक्ट्री से कॉपी-पेस्ट कर सकते हैं। \n:* डाउनलोड कीजिए व्यक्तिगत चमड़े के तारबॉल [https://www.mediawiki.org/wiki/Special:SkinDistributor मीडिया विकि] से।\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins गिट का प्रयोग करके डाउलोड कर सकते हैं].\n: ऐसा करने के दौरान आपकी गिट-रिपॉज़िटरी को कुछ नहीं होना चाहिए यदि आप विकासकर्ता हो। \n; अगर आपने मीडियाविकि को अभी अपग्रेड किया है:\n: मीडियाविकि 1.24 और इसके नवीन रूप स्वतः रूप से चमड़ों को सक्षम नहीं करते (देखिए [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: चमड़ो की स्वतः खोज]). आप निम्न लिखित को पेस्ट कर सकते हैं: {{PLURAL:$5|लाइन|लाइनें}}  <code>LocalSettings.php</code> में ताकि {{PLURAL:$5|वह|सभी}} सक्षम हों जैसा कि इन्स्टाल किए गए {{PLURAL:$5|चमड़े|चमड़ों}} का मामला है:\n\n<pre dir=\"ltr\">$3</pre>\n\n; अगर आपने अभी बदलाव किए हैं<code>LocalSettings.php</code>:\n: डबल-क्लिक करें चमड़े नामों  के आगे ताकि आपको विभिन्न प्रकारों के विकल्प मिलें।",
        "default-skin-not-found-no-skins": "ओह! आपकी विकि का पूर्व निर्धारित चमड़ा जैसा कि <code dir=\"ltr\">$wgDefaultSkin</code> में बताया गया है<code>$1</code>, उपलब्ध नहीं है। \n\nआपके पास कोई इन्स्टाल किया गया चमड़ा नहीं है। \n\n; अगर आपने अभी मीडियाविकि इन्स्टाल किया है या उसका उद्यतन किया है:\n: आपने शायद गिट से इन्स्टाल किया है, या सीधे स्रोत कोड से किया है जिसके लिए कोई और तरीक़े का प्रयोग किया है। यह तो आशा के अनुरूप है। कोशिश कीजिए कि कुछ चमड़े [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's मीडिया-विकि के चमड़े वाली डाइरेक्ट्री से डाउन्लोड करें], जिसके लिए आप:\n:* डाउनलोड कीजिए [https://www.mediawiki.org/wiki/Download तारबॉल इन्स्टालर], जो कई चमड़ों और विस्तारों में मौजूद है। आप चमड़ों का कोड <code>skins/</code> उसकी डाइरेक्ट्री से कॉपी-पेस्ट कर सकते हैं। \n:* डाउनलोड कीजिए व्यक्तिगत चमड़े के तारबॉल [https://www.mediawiki.org/wiki/Special:SkinDistributor मीडिया विकि] से।\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins गिट का प्रयोग करके डाउलोड कर सकते हैं].\n: ऐसा करने के दौरान आपकी गिट-रिपॉज़िटरी को कुछ नहीं होना चाहिए यदि आप विकासकर्ता हो।",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (सक्षम)",
        "mediastatistics": "मीडिया के आंकड़े",
        "mediastatistics-summary": "अपलोड किए गए फ़ाइल प्रकारों के आंकड़े। इसमें केवल नवीनतम फ़ाइल के अवतरण शामिल हैं। पुराने या हटाए गए फ़ाइलों के अवतरणों को अलग रखा गया है। \n\nThis only includes the most recent version of a file. Old or deleted versions of files are excluded.",
        "mediastatistics-nbytes": "{{PLURAL:$1|$1 बाइट|$1 बाइट्स}} ($2; $3%)",
+       "mediastatistics-bytespertype": "इस अनुभाग का कुल फ़ाइल आकार : {{PLURAL:$1|$1 बाइट|$1 बाइट्स}} ($2; $3%)",
+       "mediastatistics-allbytes": "सभी फ़ाइल का कुल फ़ाइल आकार : {{PLURAL:$1|$1 बाइट|$1 बाइट्स}} ($2)",
        "mediastatistics-table-mimetype": "माइम प्रकार",
        "mediastatistics-table-extensions": "सम्भवतः विस्तार",
        "mediastatistics-table-count": "फ़ाइलों की संख्या",
        "mediastatistics-header-text": "पाठ",
        "mediastatistics-header-executable": "निष्पादन योग्य",
        "mediastatistics-header-archive": "संकुचित प्रारूप",
+       "mediastatistics-header-total": "सभी फ़ाइल",
        "json-warn-trailing-comma": "$1 पीछे रह रहा {{PLURAL:$1|कॉमा को| कॉमाओं को}} जे०एस०ओ०एन० से हटाया गया",
        "json-error-unknown": "जे०एस०ओ०एन० में एक समस्या थी। त्रुटि: $1",
        "json-error-depth": "स्टैक की अधिकतम गहराई बढ़ चुकी है।",
        "special-characters-group-ipa": "आइपीए",
        "special-characters-group-symbols": "प्रतीक",
        "special-characters-group-greek": "ग्रीक",
+       "special-characters-group-greekextended": "ग्रीक विस्तृत",
        "special-characters-group-cyrillic": "सिरिलिक",
        "special-characters-group-arabic": "अरबी",
        "special-characters-group-arabicextended": "अरबी विस्तारित",
        "special-characters-group-persian": "फार्सी",
        "special-characters-group-hebrew": "हिब्रू",
-       "special-characters-group-bangla": "बाà¤\82à¤\97à¥\8dला",
+       "special-characters-group-bangla": "बà¤\82à¤\97ालà¥\80",
        "special-characters-group-tamil": "तमिल",
        "special-characters-group-telugu": "तेलूगू",
        "special-characters-group-sinhala": "सिंहल",
        "special-characters-title-emdash": "एम डैश",
        "special-characters-title-minus": "ऋण चिह्न",
        "mw-widgets-dateinput-no-date": "कुछ चयनित नहीं",
+       "mw-widgets-dateinput-placeholder-day": "DD-MM-YYYY",
        "mw-widgets-titleinput-description-new-page": "पृष्ठ अभी मौजूद नहीं है",
        "mw-widgets-titleinput-description-redirect": "$1 को अनुप्रेषित",
        "api-error-blacklisted": "कृपया कोई दूसरा विवरणात्मक शीर्षक चुनें।",
-       "randomrootpage": "अविशिष्ट मूल पृष्ठ"
+       "sessionmanager-tie": "एक साथ कई अनुरोध को नहीं मिला सकता: $1",
+       "sessionprovider-generic": "$1 सत्र",
+       "sessionprovider-mediawiki-session-cookiesessionprovider": "कुकी-आधारित सत्र",
+       "sessionprovider-nocookies": "हो सकता है कि कुकी निष्क्रिय है। कृपया देखें कि और सक्रिय करें।",
+       "randomrootpage": "अविशिष्ट मूल पृष्ठ",
+       "log-action-filter-block": "प्रतिबंध के प्रकार:",
+       "log-action-filter-delete": "हटाने के प्रकार:",
+       "log-action-filter-patrol": "परीक्षण के प्रकार:",
+       "log-action-filter-protect": "सुरक्षा के प्रकार:",
+       "log-action-filter-upload": "अपलोड के प्रकार:",
+       "log-action-filter-all": "सभी",
+       "log-action-filter-block-block": "अवरोध",
+       "log-action-filter-block-reblock": "अवरोध परिवर्तन",
+       "log-action-filter-block-unblock": "अवरोधरहित",
+       "log-action-filter-delete-delete": "पृष्ठ हटाना",
+       "log-action-filter-delete-restore": "पृष्ठ न हटाना",
+       "log-action-filter-delete-event": "पृष्ठ हटाने का लॉग",
+       "log-action-filter-delete-revision": "अवतरण हटाना",
+       "log-action-filter-patrol-patrol": "अपने से परीक्षण",
+       "log-action-filter-patrol-autopatrol": "स्वतः पुनरीक्षण",
+       "log-action-filter-protect-protect": "सुरक्षा",
+       "log-action-filter-protect-modify": "सुरक्षा परिवर्तन",
+       "log-action-filter-protect-unprotect": "असुरक्षा",
+       "log-action-filter-upload-upload": "नया अपलोड",
+       "log-action-filter-upload-overwrite": "फिर से अपलोड"
 }
index 8b46fb2..36bd896 100644 (file)
@@ -43,7 +43,8 @@
                        "Matma Rex",
                        "JulesWinnfield-hu",
                        "Bencoke",
-                       "Máté"
+                       "Máté",
+                       "Wolf Rex"
                ]
        },
        "tog-underline": "Hivatkozások aláhúzása:",
        "noemail": "„$1” e-mail címe nincs megadva.",
        "noemailcreate": "Meg kell adnod egy valós e-mail címet",
        "passwordsent": "Az új jelszót elküldtük „$1” e-mail címére.\nLépj be a levélben található adatokkal.",
-       "blocked-mailpassword": "Az IP-címedet blokkoltuk, azaz eltiltottunk a szerkesztéstől, ezért a visszaélések elkerülése érdekében a jelszó-visszaállítás funkciót nem használhatod.",
+       "blocked-mailpassword": "Az IP-címed blokkoltuk. A visszaélések megelőzése érdekében a jelszó-visszaállítás funkció nem használható erről az IP-címről.",
        "eauthentsent": "Egy ellenőrző e-mailt küldtünk a megadott címre. Mielőtt más leveleket kaphatnál, igazolnod kell az e-mailben írt utasításoknak megfelelően, hogy valóban a tiéd a megadott cím.",
        "throttled-mailpassword": "Már elküldtünk egy jelszóemlékeztetőt az utóbbi {{PLURAL:$1|egy|$1}} órában.\nA visszaélések elkerülése végett {{PLURAL:$1|egy|$1}} óránként csak egy jelszó-emlékeztetőt küldünk.",
        "mailerror": "Hiba történt az e-mail küldése közben: $1",
        "newpassword": "Új jelszó:",
        "retypenew": "Új jelszó ismét:",
        "resetpass_submit": "Add meg a jelszót és jelentkezz be",
-       "changepassword-success": "A jelszavad megváltoztatása sikeresen befejeződött!",
+       "changepassword-success": "A jelszavad megváltozott!",
        "changepassword-throttled": "Túl sok hibás bejelentkezés.\nVárj $1, mielőtt újra próbálkozol.",
        "botpasswords": "Botjelszavak",
        "botpasswords-summary": "A <em>botjelszavak</em> lehetővé teszik egy felhasználói fiókhoz való hozzáférést az API-n keresztül a fiók fő bejelentkezési adatainak megadása nélkül. A botjelszóval történő bejelentkezéskor a felhasználói jogok korlátozottak lehetnek.\n\nHa nem tudod, hogy miért szeretnél ilyet, valószínűleg nem kell csinálnod. Soha senkinek nem szabadna megkérnie téged, hogy generálj neki egyet, hogy odaadhasd neki.",
        "newarticle": "(Új)",
        "newarticletext": "Egy olyan lapra mutató hivatkozást követtél, ami még nem létezik.\nA lap létrehozásához csak gépeld be a szövegét a lenti szövegdobozba. Ha kész vagy, az „Előnézet megtekintése” gombbal ellenőrizheted, hogy úgy fog-e kinézni, ahogy szeretnéd, és a „Lap mentése” gombbal tudod elmenteni. (További információkat a [$1 súgólapon] találsz).\nHa tévedésből jutottál ide, kattints a böngésződ '''vissza''' vagy '''back''' gombjára.",
        "anontalkpagetext": "----''Ez egy olyan anonim szerkesztő vitalapja, aki még nem regisztrált, vagy csak nem jelentkezett be.\nEzért az IP-címét használjuk az azonosítására.\nUgyanazon az IP-címen számos szerkesztő osztozhat az idők folyamán.\nHa úgy látod, hogy az üzenetek, amiket ide kapsz, nem neked szólnak, [[Special:UserLogin/signup|regisztrálj]] vagy ha már regisztráltál, [[Special:UserLogin|jelentkezz be]], hogy ne keverjenek össze másokkal.''",
-       "noarticletext": "Ez a lap jelenleg nem tartalmaz szöveget.\n[[Special:Search/{{PAGENAME}}|Rákereshetsz erre a címszóra]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} megtekintheted a kapcsolódó naplókat],\nvagy [{{fullurl:{{FULLPAGENAME}}|action=edit}} szerkesztheted a lapot].</span>",
+       "noarticletext": "Ez a lap jelenleg nem tartalmaz szöveget.\n[[Special:Search/{{PAGENAME}}|Rákereshetsz erre a címszóra]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} megtekintheted a kapcsolódó naplókat],\nvagy [{{fullurl:{{FULLPAGENAME}}|action=edit}} létrehozhatod a lapot].</span>",
        "noarticletext-nopermission": "Ez a lap jelenleg nem tartalmaz szöveget.\n[[Special:Search/{{PAGENAME}}|Rákereshetsz a lap címére]] más lapok tartalmában, vagy <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} megtekintheted a kapcsolódó naplófájlokat]</span>.",
        "missing-revision": "A(z) \"{{FULLPAGENAME}}\" nevű oldal #$1 változata nem létezik.\n\nEzt általában egy elavult, törölt oldalra mutató laptörténeti hivatkozás használata okozza. Részletek a [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} törlési naplóban] találhatóak.",
        "userpage-userdoesnotexist": "Nincs „<nowiki>$1</nowiki>” nevű regisztrált felhasználónk.\nNézd meg, hogy valóban ezt a lapot szeretnéd-e létrehozni vagy szerkeszteni.",
        "mergehistory-fail-bad-timestamp": "Érvénytelen időbélyeg.",
        "mergehistory-fail-invalid-source": "Érvénytelen forráslap.",
        "mergehistory-fail-invalid-dest": "Érvénytelen céllap.",
+       "mergehistory-fail-permission": "Nincsen jogod a laptörténetek egyesítéséhez.",
        "mergehistory-fail-self-merge": "A forrás- és céllap megegyezik.",
        "mergehistory-fail-toobig": "Nem lehetséges a laptörténetek egyesítése, mivel több mint $1 {{PLURAL:$1|változást}} kellene áthelyezni.",
        "mergehistory-no-source": "Nem létezik forráslap $1 néven.",
        "recentchangeslinked-page": "Lap neve:",
        "recentchangeslinked-to": "Inkább az erre linkelő lapok változtatásait mutasd",
        "recentchanges-page-added-to-category": "[[:$1]] hozzáadva a kategóriához",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] és {{PLURAL:$2|egy oldal|$2 oldal}} hozzáadva a kategóriához",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] és [[Special:WhatLinksHere/$1|{{PLURAL:$2|egy oldal|$2 oldal}}]] hozzáadva a kategóriához",
        "recentchanges-page-removed-from-category": "[[:$1]] eltávolítva a kategóriából",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] és {{PLURAL:$2|egy oldal|$2 oldal}} eltávolítva a kategóriából",
        "upload": "Fájl feltöltése",
        "apisandbox-jsonly": "Az API-homokozó használatához JavaScriptre van szükség.",
        "apisandbox-api-disabled": "API le van tiltva ezen az oldalon.",
        "apisandbox-intro": "Ezen az oldalon kísérletezhetsz a <strong>MediaWiki web service API</strong>-val.\nA használattal kapcsolatos további részletek az [[mw:API:Main page|API-dokumentációnál]] találhatók. Példa: [//www.mediawiki.org/wiki/API#A_simple_example olvasd el a főoldal tartalomjegyzékét]. További példákért válassz egy tevékenységet!\n\nFigyelj rá, hogy bár ez csak egy „homokozó”, ettől még az általad végzett műveletek módosíthatják a wikit!",
+       "apisandbox-unfullscreen": "Lap mutatása",
        "apisandbox-submit": "Kérés végrehajtása",
        "apisandbox-reset": "Törlés",
        "apisandbox-retry": "Újra",
        "changecontentmodel-title-label": "Lapcím",
        "changecontentmodel-model-label": "Új tartalommodell",
        "changecontentmodel-reason-label": "Indoklás:",
+       "changecontentmodel-submit": "Változtatás",
        "changecontentmodel-success-title": "A tartalommodell megváltozott",
        "changecontentmodel-success-text": "A(z) [[:$1]] lap tartalommodellje sikeresen megváltoztatva.",
        "changecontentmodel-cannot-convert": "A(z) [[:$1]] lap nem alakítható át $2 típusúvá.",
        "ipb-unblock": "Felhasználónév vagy IP-cím blokkolásának feloldása",
        "ipb-blocklist": "Létező blokkok megtekintése",
        "ipb-blocklist-contribs": "$1 közreműködései",
+       "ipb-blocklist-duration-left": "$1 van hátra",
        "unblockip": "Blokk feloldása",
        "unblockiptext": "Itt tudod visszaadni egy blokkolt felhasználónévnek vagy IP-nek a szerkesztési jogosultságot.",
        "ipusubmit": "Blokk eltávolítása",
        "import-logentry-upload-detail": "$1 változat importálva",
        "import-logentry-interwiki-detail": "$1 változat innen: $2",
        "javascripttest": "JavaScript tesztelés",
-       "javascripttest-pagetext-noframework": "Ez az oldal JavaStript tesztek futtatására van fenntartva.",
-       "javascripttest-pagetext-unknownframework": "Ismeretlen teszt keretrendszer: $1.",
        "javascripttest-pagetext-unknownaction": "Ismeretlen akció: $1",
-       "javascripttest-pagetext-frameworks": "Kérlek válaszd valamelyik teszt keretrendszert az alábbiak közül: $1",
-       "javascripttest-pagetext-skins": "Válassz egy megjelenítő felületet, amin a tesztet futtatod:",
        "javascripttest-qunit-intro": "Lásd a [$1 tesztelési dokumentációt]  a mediawiki.org helyen.",
        "tooltip-pt-userpage": "A szerkesztőlapod",
        "tooltip-pt-anonuserpage": "Az általad használt IP-címhez tartozó felhasználói lap",
        "version-libraries-description": "Leírás",
        "version-libraries-authors": "Szerzők",
        "redirect": "Átirányítás fájl, szerkesztő, oldal vagy oldalváltozat alapján",
-       "redirect-legend": "Átirányítás egy fájlra vagy lapra",
        "redirect-summary": "Ez a speciális lap átirányít egy fájlra (megadott fájlnévvel), lapra (megadott lapváltozat- vagy lapazonosító számmal) vagy felhasználóra (felhasználó azonosítószáma alapján). Használat: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] vagy [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Mehet",
        "redirect-lookup": "Keresés:",
        "sessionprovider-generic": "$1-munkamenetek",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sütialapú munkamenetek",
        "sessionprovider-nocookies": "A sütik le lehetnek tiltva. Engedélyezd a sütiket, és próbáld meg újra!",
-       "randomrootpage": "Véletlen lap a gyökérből"
+       "randomrootpage": "Véletlen lap a gyökérből",
+       "log-action-filter-all": "Mind",
+       "log-action-filter-block-block": "Blokk",
+       "log-action-filter-block-reblock": "Blokk módosítása",
+       "log-action-filter-block-unblock": "Blokk feloldása"
 }
index 4240fbb..39436f8 100644 (file)
        "category-article-count-limited": "Այս կատեգորիան պարունակում է հետևյալ {{PLURAL:$1|էջը|$1 էջերը}}։",
        "category-file-count": "{{PLURAL:$2|Այս կատեգորիան պարունակում է միայն հետևյալ նիշքը։|Ստորև {{PLURAL:$1|բերված է այս կատեգորիայի $1 նիշքը|բերված է այս կատեգորիայի $1 նիշք}}՝ $2-ից։}}",
        "category-file-count-limited": "Այս կատեգորիան պարունակում է հետևյալ {{PLURAL:$1|նիշքը|$1 նիշքերը}}։",
-       "listingcontinuesabbrev": "շարունակ.",
+       "listingcontinuesabbrev": "շարունակելի",
        "index-category": "Ինդեքսավորված էջեր",
        "noindex-category": "Չինդեքսավորված էջեր",
        "broken-file-category": "Կոտրված ֆայլի հղումով էջեր",
        "preview": "Նախադիտում",
        "showpreview": "Նախադիտել",
        "showdiff": "Կատարված փոփոխությունները",
-       "blankarticle": "<strong>Զգուշացում:</strong> Էջը, որը Դուք ստեղծում եք, դատարկ է:\nԵթե նորից սեղմեք «\"{{int:savearticle}}\"» կոճակը, էջը կստեղծվի առանց որևէ բովանդակության:",
+       "blankarticle": "<strong>Զգուշացում:</strong> Էջը, որը Դուք ստեղծում եք, դատարկ է:\nԵթե նորից սեղմեք «{{int:savearticle}}» կոճակը, էջը կստեղծվի առանց որևէ բովանդակության:",
        "anoneditwarning": "<strong>Ուշադրություն,</strong> Դուք չեք մտել համակարգ։ Ցանկացած խմբագրման դեպքում Ձեր IP հասցեն կդառնա բոլորին տեսանելի։ Եթե Դուք <strong>[$1 մուտք գործեք]</strong> կամ <strong>[$2 ստեղծեք մասնակցային հաշիվ]</strong>, Ձեր կատարած խմբագրումները կկապվեն Ձեր մասնակցային անվան հետ, ինչպես նաև կունենաք այլ առավելություններ։",
        "anonpreviewwarning": "<em>Դուք չեք մտել համակարգ։\nՀիշելով Ձեր կատարած խմբագրումը, այն կպահանվի Ձեր IP հասցեի հետ միասին այս էջի խմբագրումների պատմության մեջ։</em>",
        "missingsummary": "'''Հիշեցում.''' Դուք չեք տվել խմբագրման ամփոփում։ «Հիշել» կոճակի կրկնակի մատնահարման դեպքում փոփոխությունները կհիշվեն առանց ամփոփման։",
        "emaillink": "ուղարկել էլ. նամակ",
        "autoblocker": "Դուք ավտոմատիկ արգելափակվել եք «$1» մասնակցի հետ ձեր IP-հասցեի համընկնելու պատճառով։ Նրա արգելափակման պատճառն է՝ «$2»։",
        "blocklogpage": "Արգելափակման տեղեկամատյան",
-       "blocklogentry": "արգելափակվել է  [[$1]]. արգելափակման ժամկետն է՝  $2 $3",
-       "reblock-logentry": "փոխեց [[$1]] արգելափակումը ժամկետը դարձնելով $2 $3",
+       "blocklogentry": "[[$1]] արգելափակվել է $2 տևողությամբ $3",
+       "reblock-logentry": "փոխեց [[$1]]ի արգելափակումը՝ դարձնելով $2 տևողությամբ $3",
        "blocklogtext": "Սա մասնակիցների արգելափակման և արգելափակումից հանման տեղեկամատյանն է։\nԱվտոմատ կերպով արգելափակված IP-հասցեներն այստեղ ընդգրկված չեն։\nՏես [[Special:BlockList|այս պահին ակտիվ արգելափակումների ցանկը]]։",
        "unblocklogentry": "արգելափակումից հանված է $1",
        "block-log-flags-anononly": "միայն անանուն մասնակիցներ",
index 737edaa..c33e046 100644 (file)
        "october-date": "$1 de octobre",
        "november-date": "$1 de novembre",
        "december-date": "$1 de decembre",
+       "period-am": "AM",
+       "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categoria|Categorias}}",
        "category_header": "Articulos in le categoria \"$1\"",
        "subcategories": "Subcategorias",
        "virus-scanfailed": "scannamento fallite (codice $1)",
        "virus-unknownscanner": "antivirus non cognoscite:",
        "logouttext": "'''Tu ha claudite le session.'''\n\nNota que alcun paginas pote continuar a apparer como si tu esserea ancora authenticate. Pro remediar isto, tu pote vacuar le cache de tu navigator.",
+       "cannotlogoutnow-title": "Impossibile clauder session ora",
+       "cannotlogoutnow-text": "Non es possibile clauder le session usante $1.",
        "welcomeuser": "Benvenite, $1!",
        "welcomecreation-msg": "Tu conto ha essite create.\nNon oblida personalisar tu [[Special:Preferences|preferentias in {{SITENAME}}]].",
        "yourname": "Nomine de usator:",
        "remembermypassword": "Memorar mi contrasigno in iste navigator (pro un maximo de $1 {{PLURAL:$1|die|dies}})",
        "userlogin-remembermypassword": "Mantener mi session aperte",
        "userlogin-signwithsecure": "Usar un connexion secur",
+       "cannotloginnow-title": "Impossibile aperir session ora",
+       "cannotloginnow-text": "Non es possibile aperir un session usante $1.",
        "yourdomainname": "Tu dominio:",
        "password-change-forbidden": "Non es possibile cambiar le contrasigno in iste wiki.",
        "externaldberror": "O il occurreva un error in le base de datos de authentication, o tu non ha le autorisation de actualisar tu conto externe.",
        "nocookieslogin": "{{SITENAME}} usa ''cookies'' pro mantener le sessiones del usatores.\nTu ha disactivate le functionalitate del ''cookies''.\nPer favor activa lo e reprova.",
        "nocookiesfornew": "Le conto de usator non esseva create, proque nos non poteva confirmar su origine.\nVerifica que tu ha activate le \"cookies\", recarga iste pagina e reproba.",
        "noname": "Tu non specificava un nomine de usator valide.",
-       "loginsuccesstitle": "Session aperite con successo",
+       "loginsuccesstitle": "Session aperite",
        "loginsuccess": "'''Tu es ora authenticate in {{SITENAME}} como \"$1\".'''",
        "nosuchuser": "Non existe un usator con le nomine \"$1\".\nIn le nomines de usator se distingue inter majusculas e minusculas.\nVerifica le orthographia, o [[Special:UserLogin/signup|crea un nove conto]].",
        "nosuchusershort": "Non existe un usator con le nomine \"$1\".\nVerifica le orthographia.",
        "noemail": "Il non ha un adresse de e-mail registrate pro le usator \"$1\".",
        "noemailcreate": "Es necessari fornir un adresse de e-mail valide",
        "passwordsent": "Un nove contrasigno ha essite inviate al adresse de e-mail registrate pro \"$1\".\nPer favor aperi session de novo post reciper lo.",
-       "blocked-mailpassword": "Tu adresse IP es blocate de facer modificationes, e pro impedir le abuso, le uso del function pro recuperar contrasignos es equalmente blocate.",
+       "blocked-mailpassword": "Tu adresse IP es blocate pro modification. Pro evitar abusos, il non es permittite recuperar contrasignos ab iste adresse IP.",
        "eauthentsent": "Un message de confirmation ha essite inviate al adresse de e-mail specificate.\nPro permitter que le systema invia altere messages a iste adresse, tu debe sequer le instructiones in iste message pro confirmar que le adresse es realmente tue.",
        "throttled-mailpassword": "Un message pro le reinitialisation del contrasigno ha jam essite inviate intra le ultime {{PLURAL:$1|hora|$1 horas}}.\nPro prevenir le abuso, solmente un message pro le reinitialisation del contrasigno essera inviate per {{PLURAL:$1|hora|$1 horas}}.",
        "mailerror": "Error de inviar e-mail: $1",
        "createaccount-title": "Creation de un conto pro {{SITENAME}}",
        "createaccount-text": "Un persona ha create un conto in tu adresse de e-mail a {{SITENAME}} ($4) denominate \"$2\", con le contrasigno \"$3\".\nTu deberea aperir un session e cambiar tu contrasigno ora.\n\nTu pote ignorar iste message si iste conto ha essite create in error.",
        "login-throttled": "Tu ha facite troppo de tentativas de aperir session.\nPer favor attende $1 ante de probar lo novemente.",
-       "login-abort-generic": "Apertura de session non succedite - Abortate",
+       "login-abort-generic": "Apertura de session fallite - Abortate",
        "login-migrated-generic": "Tu conto ha essite migrate, e tu nomine de usator non plus existe in iste wiki.",
        "loginlanguagelabel": "Lingua: $1",
        "suspicious-userlogout": "Le requesta de clauder le session ha essite refusate proque illo pare haber essite inviate per un navigator o proxy de cache defectuose.",
        "resetpass_submit": "Definir contrasigno e aperir un session",
        "changepassword-success": "Tu contrasigno ha essite cambiate!",
        "changepassword-throttled": "Tu ha recentemente facite troppo de tentativas de aperir session.\nPer favor attende $1 ante de probar lo novemente.",
+       "botpasswords": "Contrasignos de robot",
+       "botpasswords-summary": "Le <em>contrasignos de robot</em> permitte acceder a un conto de usator via API sin usar le credentiales de authentication principal del conto. Le derectos de usator concedite per un contrasigno de robot pote esser limitate.\n\nSi tu non sape proque tu volerea facer isto, tu probabilemente non debe facer lo. Nemo deberea jammais demandar te a crear un tal contrasigno e dar lo a ille.",
+       "botpasswords-disabled": "Le contrasignos de robot es disactivate.",
+       "botpasswords-no-central-id": "Pro usar le contrasignos de robot, tu debe aperir session per medio de un conto centralisate.",
+       "botpasswords-existing": "Contrasignos de robot existente",
+       "botpasswords-createnew": "Crear un nove contrasigno de robot",
+       "botpasswords-editexisting": "Modificar un contrasigno de robot existente",
+       "botpasswords-label-appid": "Nomine del robot:",
+       "botpasswords-label-create": "Crear",
+       "botpasswords-label-update": "Actualisar",
+       "botpasswords-label-cancel": "Cancellar",
+       "botpasswords-label-delete": "Deler",
+       "botpasswords-label-resetpassword": "Reinitialisar le contrasigno",
+       "botpasswords-label-grants": "Concessiones applicabile:",
+       "botpasswords-help-grants": "Cata concession da accesso al derectos de usator listate que un conto de usator jam ha. Vide le [[Special:ListGrants|tabula de concessiones]] pro plus information.",
+       "botpasswords-label-restrictions": "Restrictiones de uso:",
+       "botpasswords-label-grants-column": "Concedite",
+       "botpasswords-bad-appid": "Le nomine del robot \"$1\" non es valide.",
+       "botpasswords-insert-failed": "Le addition del nomine de robot \"$1\" ha fallite. Esque illo ha jam essite addite?",
+       "botpasswords-update-failed": "Le actualisation del nomine de robot \"$1\" ha fallite. Esque illo ha essite delite?",
+       "botpasswords-created-title": "Contrasigno de robot create",
+       "botpasswords-created-body": "Le contrasigno pro le robot \"$1\" del usator \"$2\" ha essite create.",
+       "botpasswords-updated-title": "Contrasigno de robot actualisate",
+       "botpasswords-updated-body": "Le contrasigno pro le robot \"$1\" del usator \"$2\" ha essite actualisate.",
+       "botpasswords-deleted-title": "Contrasigno de robot delite",
+       "botpasswords-deleted-body": "Le contrasigno pro le robot \"$1\" del usator \"$2\" ha essite delite.",
+       "botpasswords-newpassword": "Le nove contrasigno pro aperir session con <strong>$1</strong> es <strong>$2</strong>. <em>Per favor, conserva isto pro uso futur.</em>",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider non es disponibile.",
+       "botpasswords-restriction-failed": "Session impedite per restrictiones de contrasigno de robot.",
+       "botpasswords-invalid-name": "Iste nomine de usator non contine le separator pro contrasigno de robot (\"$1\").",
+       "botpasswords-not-exist": "Le usator \"$1\" non ha un contrasigno de robot del nomine \"$2\".",
        "resetpass_forbidden": "Le contrasignos non pote esser cambiate",
        "resetpass-no-info": "Tu debe aperir un session pro poter acceder directemente a iste pagina.",
        "resetpass-submit-loggedin": "Cambiar contrasigno",
        "passwordreset-emailtext-ip": "Un persona (probabilemente tu, ab le adresse IP $1) requestava le reinitialisation de tu\ncontrasigno de {{SITENAME}} ($4). Le {{PLURAL:$3|conto|contos}} de usator sequente es\nassociate con iste adresse de e-mail:\n\n$2\n\nIste {{PLURAL:$3|contrasigno|contrasignos}} temporari expirara post {{PLURAL:$5|un die|$5 dies}}.\nTu deberea ora aperir session e eliger un nove contrasigno. Si un altere persona faceva iste\nrequesta, o si tu te ha rememorate tu contrasigno original e non plus\nvole cambiar lo, tu pote ignorar iste message e continuar a usar le ancian\ncontrasigno.",
        "passwordreset-emailtext-user": "Le usator $1 in {{SITENAME}} requestava un reinitialisation de tu contrasigno in {{SITENAME}}\n($4). Le {{PLURAL:$3|conto|contos}} de usator sequente es associate con iste adresse de e-mail:\n\n$2\n\nIste {{PLURAL:$3|contrasigno|contrasignos}} temporari expirara post {{PLURAL:$5|un die|$5 dies}}.\nTu deberea ora aperir session e eliger un nove contrasigno. Si un altere persona faceva iste\nrequesta, o si tu te ha rememorate tu contrasigno original e non plus\nvole cambiar lo, tu pote ignorar iste message e continuar a usar le ancian\ncontrasigno.",
        "passwordreset-emailelement": "Nomine de usator: \n$1\n\nContrasigno temporari: \n$2",
-       "passwordreset-emailsentemail": "Si iste es un adresse de e-mail registrate pro tu conto, alora un message de e-mail pro le reinitialisation del contrasigno essera inviate.",
-       "passwordreset-emailsentusername": "Si il ha un correspondente adresse de e-mail registrate, alora un e-mail pro reinitialisar le contrasigno essera inviate.",
+       "passwordreset-emailsentemail": "Si iste adresse es associate a tu conto, alora un e-mail pro reinitialisar le contrasigno essera inviate.",
+       "passwordreset-emailsentusername": "Si il ha un adresse de e-mail associate a iste conto, alora un e-mail pro reinitialisar le contrasigno essera inviate.",
        "passwordreset-emailsent-capture": "Un message de e-mail pro le reinitialisation del contrasigno ha essite inviate; iste message es monstrate hic infra.",
        "passwordreset-emailerror-capture": "Un e-mail pro le reinitialisation del contrasigno ha essite generate; iste message es monstrate hic infra, ma le invio al {{GENDER:$2|usator}} ha fallite: $1",
        "changeemail": "Cambiar o remover adresse de e-mail",
        "newarticle": "(Nove)",
        "newarticletext": "Tu ha sequite un ligamine verso un pagina que non existe ancora.\nPro crear iste pagina, comencia a scriber in le quadro infra (consulta le [$1 pagina de adjuta] pro plus informationes).\nSi tu ha arrivate a iste pagina per error, clicca le button '''Retornar''' de tu navigator.",
        "anontalkpagetext": "---- ''Isto es le pagina de discussion pro un usator anonyme qui non ha ancora create un conto, o qui non lo usa. Consequentemente nos debe usar le adresse IP numeric pro identificar le/la.\nUn tal adresse IP pote esser usate in commun per varie personas.\nSi tu es un usator anonyme e pensa que commentos irrelevante ha essite dirigite a te, per favor [[Special:UserLogin/signup|crea un conto]] o [[Special:UserLogin|aperi un session]] pro evitar futur confusiones con altere usatores anonyme.''",
-       "noarticletext": "Al momento il non ha texto in iste pagina.\nTu pote [[Special:Search/{{PAGENAME}}|cercar le titulo de iste pagina]] in altere paginas,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cercar in le registros pertinente],\no [{{fullurl:{{FULLPAGENAME}}|action=edit}} modificar iste pagina]</span>.",
+       "noarticletext": "Al momento il non ha texto in iste pagina.\nTu pote [[Special:Search/{{PAGENAME}}|cercar le titulo de iste pagina]] in altere paginas,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cercar in le registros pertinente],\no [{{fullurl:{{FULLPAGENAME}}|action=edit}} crear iste pagina]</span>.",
        "noarticletext-nopermission": "In iste momento il non ha texto in iste pagina.\nTu pote [[Special:Search/{{PAGENAME}}|cercar le titulo de iste pagina]] in altere paginas,\no <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cercar in le registros pertinente], ma tu non ha le permission de crear iste pagina.</span>",
        "missing-revision": "Le version №$1 del pagina nominate \"{{FULLPAGENAME}}\" non existe.\n\nIsto es generalmente causate per sequer un ligamine de historia obsolete a un pagina que ha essite delite.\nDetalios se trova in le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de deletiones].",
        "userpage-userdoesnotexist": "Le conto de usator \"<nowiki>$1</nowiki>\" non es registrate. Per favor verifica que tu vole crear/modificar iste pagina.",
        "previewnote": "'''Isto es solmente un previsualisation.'''\nLe modificationes non ha ancora essite publicate!",
        "continue-editing": "Saltar al quadro de modification",
        "previewconflict": "Iste previsualisation reflecte le apparentia final del texto in le area de modification superior\nsi tu opta pro publicar lo.",
-       "session_fail_preview": "'''Nos non poteva processar tu modification proque nos perdeva le datos del session.\nPer favor reprova.\nSi illo ancora non va, prova [[Special:UserLogout|clauder tu session]] e aperir un nove session.'''",
-       "session_fail_preview_html": "'''Nos non poteva processar tu modification proque nos perdeva le datos del session.'''\n\n''Post que HTML crude es active in {{SITENAME}}, le previsualisation es celate como precaution contra attaccos via JavaScript.''\n\n'''Si isto es un tentativa de modification legitime, per favor reprova lo.\nSi illo ancora non va, prova [[Special:UserLogout|clauder tu session]] e aperir un nove session.'''",
+       "session_fail_preview": "Oh guai! Iste modification ha essite impedite per un perdita de datos del session.\n\nEs possibile que tu session ha essite claudite. <strong>Per favor, verifica que tu session es ancora aperte e tenta lo de novo</strong>.\nSi le problema persiste, proba a [[Special:UserLogout|clauder session]] e aperir un nove session, verificante que tu navigator accepta le cookies ab iste sito.",
+       "session_fail_preview_html": "Oh guai! Iste modification ha essite impedite per un perdita de datos del session.\n\n<em>Post que HTML crude es active in {{SITENAME}}, le previsualisation es celate como precaution contra attaccos via JavaScript.</em>\n\n<strong>Si iste tentativa de modification es legitime, per favor, tenta lo de novo.</strong>\nSi le problema persiste, proba a [[Special:UserLogout|clauder session]] e aperir un nove session, verificante que tu navigator accepta le cookies ab iste sito.",
        "token_suffix_mismatch": "'''Tu modification ha essite refusate proque tu cliente corrumpeva le characteres de punctuation in le indicio de modification.\nIste refusa es pro evitar le corruption del texto del pagina.\nIsto pote occurrer quando tu usa un servicio problematic de ''proxy'' anonyme a base de web.'''",
        "edit_form_incomplete": "'''Certe partes del formulario de modification non attingeva le servitor; re-verifica que tu modificationes es intacte e reproba.'''",
        "editing": "Modification de $1",
        "revdelete-unsuppress": "Eliminar restrictiones super versiones restaurate",
        "revdelete-log": "Motivo:",
        "revdelete-submit": "Applicar al {{PLURAL:$1|version|versiones}} seligite",
-       "revdelete-success": "'''Le visibilitate del version ha essite actualisate con successo.'''",
+       "revdelete-success": "Le visibilitate del version ha essite actualisate.",
        "revdelete-failure": "'''Le visibilitate del version non poteva esser actualisate:'''\n$1",
-       "logdelete-success": "'''Le visibilitate del registro ha essite definite con successo.'''",
+       "logdelete-success": "Le visibilitate del registro ha essite definite.",
        "logdelete-failure": "'''Le visibilitate del registro non poteva esser cambiate:'''\n$1",
        "revdel-restore": "Cambiar visibilitate",
        "pagehist": "Historia del pagina",
        "mergehistory-empty": "Nulle versiones pote esser fusionate.",
        "mergehistory-done": "$3 {{PLURAL:$3|version|versiones}} de $1 fusionate in [[:$2]] con successo.",
        "mergehistory-fail": "Impossibile executar le fusion del historia. Per favor reverifica le parametros del pagina e del tempore.",
+       "mergehistory-fail-bad-timestamp": "Data e hora non valide.",
+       "mergehistory-fail-invalid-source": "Pagina de origine non valide.",
+       "mergehistory-fail-invalid-dest": "Pagina de destination non valide.",
+       "mergehistory-fail-no-change": "Nulle version de historia ha essite fusionate. Per favor, reverifica le parametros de pagina e de tempore.",
+       "mergehistory-fail-permission": "Permissiones insufficiente pro fusionar le historia.",
+       "mergehistory-fail-self-merge": "Le paginas de origine e de destination es identic.",
+       "mergehistory-fail-timestamps-overlap": "Le versiones de origine se superpone o seque le versiones de destination.",
        "mergehistory-fail-toobig": "Le historias de versiones non pote esser fusionate con plus de $1 {{PLURAL:$1|version|versiones}} a displaciar.",
        "mergehistory-no-source": "Le pagina de origine $1 non existe.",
        "mergehistory-no-destination": "Le pagina de destination $1 non existe.",
        "userrights": "Gestion de derectos de usator",
        "userrights-lookup-user": "Gerer gruppos de usatores",
        "userrights-user-editname": "Entra un nomine de usator:",
-       "editusergroup": "Modificar gruppos de usatores",
+       "editusergroup": "Modificar gruppos de {{GENDER:$1|usator}}",
        "editinguser": "Cambia le derectos del {{GENDER:$1|usator}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modificar gruppos de usatores",
-       "saveusergroups": "Salveguardar gruppos de usatores",
+       "saveusergroups": "Salveguardar gruppos de {{GENDER:$1|usator}}",
        "userrights-groupsmember": "Membro de:",
        "userrights-groupsmember-auto": "Membro implicite de:",
        "userrights-groups-help": "Tu pote alterar le gruppos del quales iste usator es membro:\n* Un quadrato marcate significa que le usator es membro del gruppo in question.\n* Un non marcate significa que ille non es membro de illo.\n* Un * indica que tu non potera eliminar le gruppo quando tu lo ha addite, o vice versa.",
        "userrights-changeable-col": "Gruppos que tu pote modificar",
        "userrights-unchangeable-col": "Gruppos que tu non pote modificar",
        "userrights-conflict": "Conflicto inter cambiamentos de derectos de usator! Per favor revide e confirma tu cambiamentos.",
-       "userrights-removed-self": "Tu ha removite con successo tu proprie derectos. In consequentia, tu non plus pote acceder a iste pagina.",
+       "userrights-removed-self": "Tu ha removite tu proprie derectos. In consequentia, tu non plus pote acceder a iste pagina.",
        "group": "Gruppo:",
        "group-user": "Usatores",
        "group-autoconfirmed": "Usatores autoconfirmate",
        "right-createpage": "Crear paginas (non discussion)",
        "right-createtalk": "Crear paginas de discussion",
        "right-createaccount": "Crear nove contos de usator",
+       "right-autocreateaccount": "Aperir session automaticamente con un conto de usator externe",
        "right-minoredit": "Marcar modificationes como minor",
        "right-move": "Renominar paginas",
        "right-move-subpages": "Renominar paginas con lor subpaginas",
        "right-managechangetags": "Crear e deler [[Special:Tags|etiquettas]] in le base de datos",
        "right-applychangetags": "Applicar [[Special:Tags|etiquettas]] al proprie modificationes",
        "right-changetags": "Adder e remover qualcunque [[Special:Tags|etiquettas]] sur individual versiones e entratas de registro",
-       "grant-generic": "gruppo de derectos \"$1\"",
+       "grant-generic": "Gruppo de derectos \"$1\"",
+       "grant-group-page-interaction": "Interager con paginas",
+       "grant-group-file-interaction": "Interager con multimedia",
+       "grant-group-watchlist-interaction": "Interager con tu observatorio",
+       "grant-group-email": "Inviar e-mail",
+       "grant-group-high-volume": "Exequer actiones in massa",
+       "grant-group-customization": "Personalisation e perferentias",
        "grant-group-administration": "Exequer actiones administrative",
+       "grant-group-other": "Activitates diverse",
        "grant-blockusers": "Blocar e disblocar usatores",
+       "grant-createaccount": "Crear contos",
        "grant-createeditmovepage": "Crear, modificar e renominar paginas",
        "grant-delete": "Deler paginas, versiones e entratas de registro",
-       "grant-editinterface": "Modificar le spatio de nomines MediaWiki e le CSS/JS de usatores",
-       "grant-editmycssjs": "Modificar le CSS/JS del proprie usator",
-       "grant-editmywatchlist": "Modificar le proprie observatorio",
+       "grant-editinterface": "Modificar le spatio de nomines MediaWiki e le CSS/JavaScript de usatores",
+       "grant-editmycssjs": "Modificar le CSS/JavaScript del proprie usator",
+       "grant-editmyoptions": "Modificar tu preferentias de usator",
+       "grant-editmywatchlist": "Modificar tu observatorio",
        "grant-editpage": "Modificar paginas existente",
        "grant-editprotected": "Modificar paginas protegite",
        "grant-highvolume": "Modification in massa",
        "grant-oversight": "Celar usatores e supprimer versiones",
-       "grant-patrol": "Patruliar cambiamentos in paginas",
+       "grant-patrol": "Patruliar cambiamentos a paginas",
        "grant-protect": "Proteger e disproteger paginas",
-       "grant-rollback": "Revocar cambiamentos in paginas",
+       "grant-rollback": "Revocar cambiamentos a paginas",
        "grant-sendemail": "Inviar e-mail a altere usatores",
        "grant-uploadeditmovefile": "Actualisar, reimplaciar e renominar files",
        "grant-uploadfile": "Incargar nove files",
-       "grant-viewdeleted": "Vider information delite",
+       "grant-basic": "Derectos de base",
+       "grant-viewdeleted": "Vider files e paginas delite",
        "grant-viewmywatchlist": "Vider le proprie observatorio",
        "newuserlogpage": "Registro de creation de usatores",
        "newuserlogpagetext": "Isto es un registro de creation de usatores.",
        "action-createpage": "crear paginas",
        "action-createtalk": "crear paginas de discussion",
        "action-createaccount": "crear iste conto de usator",
+       "action-autocreateaccount": "crear automaticamente iste conto de usator externe",
        "action-history": "vider le historia de iste pagina",
        "action-minoredit": "marcar iste modification como minor",
        "action-move": "renominar iste pagina",
        "recentchangeslinked-page": "Nomine del pagina:",
        "recentchangeslinked-to": "Monstrar modificationes in paginas con ligamines al pagina specificate",
        "recentchanges-page-added-to-category": "[[:$1]] addite al categoria",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] e {{PLURAL:$2|un pagina|$2 paginas}} addite al categoria",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|un pagina|$2 paginas}}]] addite al categoria",
        "recentchanges-page-removed-from-category": "[[:$1]] removite del categoria",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e {{PLURAL:$2|un pagina|$2 paginas}} removite del categoria",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|un pagina|$2 paginas}}]] removite del categoria",
        "autochange-username": "Cambiamento automatic de MediaWiki",
        "upload": "Incargar file",
        "uploadbtn": "Incargar file",
        "uploaded-script-svg": "Un elemento de script \"$1\" se trova in le file SVG incargate.",
        "uploaded-hostile-svg": "Certe codice CSS insecur se trova in le elemento de stilo del file SVG incargate.",
        "uploaded-event-handler-on-svg": "Fixar attributos de gestion de eventos <code>$1=\"$2\"</code> non es permittite in files SVG.",
-       "uploaded-href-unsafe-target-svg": "Un href a un objectivo non secur <code>&lt;$1 $2=\"$3\"&gt;</code> se trova in le file SVG incargate.",
+       "uploaded-href-attribute-svg": "Le attributos href in files SVG pote solmente ligar a adresses http:// o https://, ma un adresse <code>&lt;$1 $2=\"$3\"&gt;</code> ha essite trovate.",
+       "uploaded-href-unsafe-target-svg": "Un href a datos non secur: le URI <code>&lt;$1 $2=\"$3\"&gt;</code> se trova in le file SVG incargate.",
        "uploaded-animate-svg": "Un etiqueta \"animate\" que poterea cambiar le href, usante le attributo \"from\" <code>&lt;$1 $2=\"$3\"&gt;</code>, se trova in le file SVG incargate.",
        "uploaded-setting-event-handler-svg": "Fixar le attributos de gestion de eventos non es permittite, ma le codice <code>&lt;$1 $2=\"$3\"&gt;</code> se trova in le file SVG incargate.",
        "uploaded-setting-href-svg": "Usar le etiquetta \"set\" pro adder le attributo \"href\" al elemento genitor non es permittite.",
        "upload-too-many-redirects": "Le URL contineva troppo de redirectiones",
        "upload-http-error": "Un error HTTP occurreva: $1",
        "upload-copy-upload-invalid-domain": "Le incargamento de copias non es disponibile ab iste dominio.",
+       "upload-foreign-cant-upload": "Iste wiki non es configurate pro incargar files al repositorio de files externe demandate.",
        "upload-dialog-title": "Incargar file",
        "upload-dialog-button-cancel": "Cancellar",
        "upload-dialog-button-done": "Facite",
        "upload-dialog-button-upload": "Incargar",
        "upload-form-label-infoform-title": "Detalios",
        "upload-form-label-infoform-name": "Nomine",
+       "upload-form-label-infoform-name-tooltip": "Un titulo descriptive e unic pro le file, que servira de nomine de file. Tu pote usar linguage simple con spatios. Non includer le extension del nomine del file.",
        "upload-form-label-infoform-description": "Description",
+       "upload-form-label-infoform-description-tooltip": "Describe brevemente tote le aspectos notabile de iste obra. Pro un photo, mentiona le cosas principal que es representate, le occasion o le loco.",
        "upload-form-label-usage-title": "Uso",
        "upload-form-label-usage-filename": "Nomine del file",
        "foreign-structured-upload-form-label-own-work": "Iste es mi proprie obra",
        "backend-fail-read": "Non poteva leger le file $1",
        "backend-fail-create": "Non poteva crear le file $1.",
        "backend-fail-maxsize": "Impossibile scriber le file $1 perque illo es plus grande que {{PLURAL:$2|un byte|$2 bytes}}.",
-       "backend-fail-readonly": "Le systema de immagazinage \"$1\" es actualmente in lectura sol. Le sequente motivo esseva specificate: \"$2\"",
+       "backend-fail-readonly": "Le systema de immagazinage \"$1\" es actualmente in lectura sol. Le ration indicate es: \"$2\"",
        "backend-fail-synced": "Le file \"$1\" es in un stato inconsistente inter le systemas interne de immagazinage",
        "backend-fail-connect": "Impossibile connecter al systema de immagazinage \"$1\".",
        "backend-fail-internal": "Un error incognite occurreva in le systema de immagazinage \"$1\".",
        "uploadstash-summary": "Iste pagina forni accesso al files que ha essite incargate (o que es in le processo de incargamento) ma non es ancora publicate in le wiki. Iste files es solmente visibile pro le usator qui los incargava.",
        "uploadstash-clear": "Rader le pila de files incargate",
        "uploadstash-nofiles": "Il non ha files in le pila.",
-       "uploadstash-badtoken": "Le execution de iste action non succedeva, forsan proque le datos del session expirava. Tenta lo de novo.",
-       "uploadstash-errclear": "Le radimento del files non succedeva.",
+       "uploadstash-badtoken": "Le execution de iste action ha fallite, forsan perque le datos del session ha expirate. Tenta lo de novo.",
+       "uploadstash-errclear": "Le radimento del files ha fallite.",
        "uploadstash-refresh": "Refrescar le lista de files",
+       "uploadstash-thumbnail": "vider miniatura",
        "invalid-chunk-offset": "Position de segmento invalide",
        "img-auth-accessdenied": "Accesso refusate",
        "img-auth-nopathinfo": "PATH_INFO manca.\nLe servitor non ha essite configurate pro passar iste information.\nIllo pote esser basate super CGI e non pote supportar img_auth.\nVide https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "mostrevisions": "Paginas le plus modificate",
        "prefixindex": "Tote le paginas con prefixo",
        "prefixindex-namespace": "Tote le paginas con prefixo (spatio de nomines $1)",
+       "prefixindex-submit": "Monstrar",
        "prefixindex-strip": "Remover prefixo in lista",
        "shortpages": "Paginas curte",
        "longpages": "Paginas longe",
        "protectedpages-performer": "Protegite per",
        "protectedpages-params": "Parametros de protection",
        "protectedpages-reason": "Motivo",
+       "protectedpages-submit": "Monstrar paginas",
        "protectedpages-unknown-timestamp": "Incognite",
        "protectedpages-unknown-performer": "Usator incognite",
        "protectedtitles": "Titulos protegite",
        "protectedtitles-summary": "Iste pagina lista titulos actualmente protegite contra creation. Pro un lista de paginas existente que ha essite protegite, vide [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Nulle titulos es actualmente protegite con iste parametros.",
+       "protectedtitles-submit": "Monstrar titulos",
        "listusers": "Lista de usatores",
        "listusers-editsonly": "Monstrar solmente usatores con modificationes",
        "listusers-creationsort": "Ordinar per data de creation",
        "usereditcount": "$1 {{PLURAL:$1|modification|modificationes}}",
        "usercreated": "{{GENDER:$3|Create}} le $1 a $2",
        "newpages": "Nove paginas",
+       "newpages-submit": "Monstrar",
        "newpages-username": "Nomine de usator:",
        "ancientpages": "Paginas le plus ancian",
        "move": "Renominar",
        "apihelp": "Adjuta con le API",
        "apihelp-no-such-module": "Modulo \"$1\" non trovate.",
        "apisandbox": "Cassa de sablo pro API",
+       "apisandbox-jsonly": "JavaScript es necessari pro usar le cassa a sablo del API.",
        "apisandbox-api-disabled": "Le API ha essite disactivate in iste sito.",
-       "apisandbox-intro": "Usa iste pagina pro experimentar con le '''API de servicio web de MediaWiki'''.\nConsulta [//www.mediawiki.org/wiki/API:Main_page le documentation del API] pro ulterior detalios concernente le uso del API. Per exemplo: [//www.mediawiki.org/wiki/API#A_simple_example obtener le contento de un Pagina principal]. Selige un action pro vider altere exemplos.",
+       "apisandbox-intro": "Usa iste pagina pro experimentar con le <strong>API de servicio web de MediaWiki</strong>.\nConsulta [[mw:API:Main page|le documentation del API]] pro ulterior detalios concernente le uso del API. Per exemplo: [//www.mediawiki.org/wiki/API#A_simple_example obtener le contento de un Pagina principal]. Selige un action pro vider altere exemplos.\n\nAttention: Ben que isto es un cassa a sablo, le actiones que tu exeque in iste pagina pote modificar tote le wiki.",
+       "apisandbox-fullscreen": "Expander pannello",
+       "apisandbox-fullscreen-tooltip": "Expander le pannello del cassa a sablo pro impler le fenestra del navigator.",
+       "apisandbox-unfullscreen": "Monstrar pagina",
+       "apisandbox-unfullscreen-tooltip": "Reducer le pannello del cassa a sablo de sorta que le ligamines de navigation de MediaWiki es disponibile.",
        "apisandbox-submit": "Facer requesta",
        "apisandbox-reset": "Rader",
-       "apisandbox-examples": "Exemplo",
-       "apisandbox-results": "Resultato",
+       "apisandbox-retry": "Reprobar",
+       "apisandbox-loading": "Carga information pro le modulo API \"$1\"...",
+       "apisandbox-load-error": "Un error ha occurrite durante le cargamento del information pro le modulo API \"$1\": $2",
+       "apisandbox-no-parameters": "Iste modulo API non ha parametros.",
+       "apisandbox-helpurls": "Ligamines de adjuta",
+       "apisandbox-examples": "Exemplos",
+       "apisandbox-dynamic-parameters": "Parametros additional",
+       "apisandbox-dynamic-parameters-add-label": "Adder parametro:",
+       "apisandbox-dynamic-parameters-add-placeholder": "Nomine del parametro",
+       "apisandbox-dynamic-error-exists": "Un parametro con le nomine \"$1\" jam existe.",
+       "apisandbox-deprecated-parameters": "Parametros obsolescente",
+       "apisandbox-fetch-token": "Auto-reimpler le indicio",
+       "apisandbox-submit-invalid-fields-title": "Alcun campos non es valide",
+       "apisandbox-submit-invalid-fields-message": "Per favor, corrige le campos marcate e reproba.",
+       "apisandbox-results": "Resultatos",
+       "apisandbox-sending-request": "Invia requesta API...",
+       "apisandbox-loading-results": "Recipe resultatos API...",
+       "apisandbox-results-error": "Un error ha occurrite durante le cargamento del responsa al consulta API: $1.",
        "apisandbox-request-url-label": "URL de requesta:",
-       "apisandbox-request-time": "Duration del requesta: $1",
+       "apisandbox-request-time": "Duration del requesta: {{PLURAL:$1|$1 ms}}",
+       "apisandbox-results-fixtoken": "Corrige le indicio e reinvia",
+       "apisandbox-results-fixtoken-fail": "Impossibile recuperar indicio \"$1\".",
+       "apisandbox-alert-page": "Certe campos in iste pagina non es valide.",
+       "apisandbox-alert-field": "Le valor de iste campo non es valide.",
        "booksources": "Fontes de libros",
        "booksources-search-legend": "Cercar fontes de libros",
        "booksources-search": "Cercar",
        "specialloguserlabel": "Executor:",
        "speciallogtitlelabel": "Objectivo (titulo o {{ns:user}}:nomine de usator):",
        "log": "Registros",
+       "logeventslist-submit": "Monstrar",
        "all-logs-page": "Tote le registros public",
        "alllogstext": "Presentation combinate de tote le registros disponibile de {{SITENAME}}.\nPro restringer le presentation, selige un typo de registro, le nomine de usator (sensibile al majusculas e minusculas), o le pagina in question (etiam sensibile al majusculas e minusculas).",
        "logempty": "Le registro contine nihil pro iste pagina.",
        "log-title-wildcard": "Cercar titulos que comencia con iste texto",
        "showhideselectedlogentries": "Monstrar/celar le entratas de registro seligite",
        "log-edit-tags": "Modificar le etiquettas del entratas de registro seligite",
+       "checkbox-select": "Seliger: $1",
+       "checkbox-all": "Totes",
+       "checkbox-none": "Nulle",
+       "checkbox-invert": "Inverter",
        "allpages": "Tote le paginas",
        "nextpage": "Sequente pagina ($1)",
        "prevpage": "Precedente pagina ($1)",
        "cachedspecial-viewing-cached-ts": "Tu vide un version in cache de iste pagina, que pote non esser completemente actual.",
        "cachedspecial-refresh-now": "Vider le plus recente.",
        "categories": "Categorias",
+       "categories-submit": "Monstrar",
        "categoriespagetext": "Le sequente {{PLURAL:$1|categoria|categorias}} contine paginas o multimedia.\nLe [[Special:UnusedCategories|categorias non usate]] non se monstra hic.\nVide etiam le [[Special:WantedCategories|categorias desirate]].",
        "categoriesfrom": "Monstrar categorias a partir de:",
        "special-categories-sort-count": "ordinar per numero",
        "activeusers-hidebots": "Celar bots",
        "activeusers-hidesysops": "Celar administratores",
        "activeusers-noresult": "Nulle usator trovate.",
+       "activeusers-submit": "Monstrar usatores active",
        "listgrouprights": "Derectos del gruppos de usatores",
        "listgrouprights-summary": "Lo sequente es un lista de gruppos de usatores definite in iste wiki, con lor derectos de accesso associate.\nIl pote haber [[{{MediaWiki:Listgrouprights-helppage}}|informationes additional]] super derectos individual.",
        "listgrouprights-key": "Legenda:\n* <span class=\"listgrouprights-granted\">Derecto concedite</span>\n* <span class=\"listgrouprights-revoked\">Derecto revocate</span>",
        "listgrouprights-namespaceprotection-header": "Restrictiones de spatio de nomines",
        "listgrouprights-namespaceprotection-namespace": "Spatio de nomines",
        "listgrouprights-namespaceprotection-restrictedto": "Derecto(s) que permitte al usator de modificar",
+       "listgrants": "Concessiones",
+       "listgrants-summary": "Lo sequente es un lista de concessiones con lor accesso associate a derectos de usator. Le usatores pote autorisar applicationes a usar lor conto, ma con permissiones limitate secundo le concessiones que le usator ha date al application. Nonobstante, un application agente in nomine de un usator non pote vermente usar derectos que le usator non ha.\nIl ha possibilemente [[{{MediaWiki:Listgrouprights-helppage}}|informationes supplementari]] sur derectos individual.",
+       "listgrants-grant": "Conceder",
+       "listgrants-rights": "Derectos",
        "trackingcategories": "Categorias de sequimento",
        "trackingcategories-summary": "Iste pagina lista le categorias de sequimento que es automaticamente plenate per le software MediaWiki. Lor nomines pote esser cambiate alterante le correspondente messages de systema in le spatio de nomines \"{{ns:8}}\".",
        "trackingcategories-msg": "Categoria de sequimento",
        "wlnote": "Ecce le ultime {{PLURAL:$1|modification|<strong>$1</strong> modificationes}} durante le ultime {{PLURAL:$2|hora|<strong>$2</strong> horas}}, a partir del $3 a $4.",
        "wlshowlast": "Monstrar le ultime $1 horas $2 dies",
        "watchlist-hide": "Celar",
+       "watchlist-submit": "Monstrar",
        "wlshowtime": "Periodo de tempore a monstrar:",
        "wlshowhideminor": "modificationes minor",
        "wlshowhidebots": "robots",
        "wlshowhideanons": "usatores anonyme",
        "wlshowhidepatr": "modificationes patruliate",
        "wlshowhidemine": "mi modificationes",
+       "wlshowhidecategorization": "categorisation de paginas",
        "watchlist-options": "Optiones del observatorio",
        "watching": "Observation in curso...",
        "unwatching": "Disobservation in curso...",
        "delete-confirm": "Deler \"$1\"",
        "delete-legend": "Deler",
        "historywarning": "<strong>Attention:</strong> Le pagina que tu vole deler ha un historia de circa $1 {{PLURAL:$1|version|versiones}}:",
+       "historyaction-submit": "Monstrar",
        "confirmdeletetext": "Tu va deler un pagina con tote su historia.\nPer 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 politicas]].",
        "actioncomplete": "Action complete",
        "actionfailed": "Action fallite",
        "delete-toobig": "Iste pagina ha un grande historia de modificationes con plus de $1 {{PLURAL:$1|version|versiones}}.\nLe deletion de tal paginas ha essite restringite pro impedir le disruption accidental de {{SITENAME}}.",
        "delete-warning-toobig": "Iste pagina ha un grande historia de modificationes con plus de $1 {{PLURAL:$1|version|versiones}}.\nLe deletion de illo pote disrumper le operationes del base de datos de {{SITENAME}};\nprocede con caution.",
        "deleteprotected": "Tu non pote deler iste pagina perque illo ha essite protegite.",
-       "deleting-backlinks-warning": "'''Attention:''' Il ha [[Special:WhatLinksHere/{{FULLPAGENAME}}|altere paginas]] que liga a o transclude le pagina que tu es sur le puncto de deler.",
+       "deleting-backlinks-warning": "<strong>Attention:</strong> Il ha [[Special:WhatLinksHere/{{FULLPAGENAME}}|altere paginas]] que liga a o transclude le pagina que tu es sur le puncto de deler.",
        "rollback": "Revocar modificationes",
        "rollbacklink": "revocar",
        "rollbacklinkcount": "revocar $1 {{PLURAL:$1|modification|modificationes}}",
        "changecontentmodel-title-label": "Titulo del pagina",
        "changecontentmodel-model-label": "Nove modello de contento",
        "changecontentmodel-reason-label": "Motivo:",
+       "changecontentmodel-submit": "Cambiar",
        "changecontentmodel-success-title": "Le modello de contento ha essite cambiate",
        "changecontentmodel-success-text": "Le typo de contento de [[:$1]] ha essite cambiate.",
        "changecontentmodel-cannot-convert": "Le contento de [[:$1]] non pote esser convertite a un typo de $2.",
        "changecontentmodel-nodirectediting": "Le modello de contento $1 non supporta le modification directe",
        "log-name-contentmodel": "Registro de cambiamentos de modello de contento",
        "log-description-contentmodel": "Eventos relative al modellos de contento de un pagina",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|creava}} le pagina $3 con le modello de contento non predefinite \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|cambiava}} le modello de contento del pagina $3 de \"$4\" a \"$5\"",
        "logentry-contentmodel-change-revertlink": "reverter",
        "logentry-contentmodel-change-revert": "reversion",
        "whatlinkshere-hidelinks": "$1 ligamines",
        "whatlinkshere-hideimages": "$1 le ligamines a files",
        "whatlinkshere-filters": "Filtros",
+       "whatlinkshere-submit": "Va",
        "autoblockid": "Auto-blocada №$1",
        "block": "Blocar usator",
        "unblock": "Disblocar usator",
        "blockip": "Blocar {{GENDER:$1|usator}}",
        "blockip-legend": "Blocar usator",
-       "blockiptext": "Usa le formulario infra pro blocar le accesso de scriptura\na partir de un adresse IP specific.\nIsto debe esser facite solmente pro impedir vandalismo, e de\naccordo con le [[{{MediaWiki:Policy-url}}|politica de {{SITENAME}}]].\nScribe un motivo specific infra (per exemplo, citante paginas\nspecific que ha essite vandalisate).",
+       "blockiptext": "Usa le formulario infra pro blocar le accesso de scriptura\na partir de un adresse IP specific.\nIsto debe esser facite solmente pro impedir vandalismo, e de\naccordo con le [[{{MediaWiki:Policy-url}}|politica de {{SITENAME}}]].\nScribe un motivo specific infra (per exemplo, citante paginas\nspecific que ha essite vandalisate).\nTu pote blocar intervallos de adresses IP con le syntaxe [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR]; le intervallo le plus grande permittite es /$1 pro IPv4 e /$2 pro IPv6.",
        "ipaddressorusername": "Adresse IP o nomine de usator:",
        "ipbexpiry": "Expiration:",
        "ipbreason": "Motivo:",
        "ipb-unblock": "Disblocar un nomine de usator o un adresse IP",
        "ipb-blocklist": "Vider blocadas existente",
        "ipb-blocklist-contribs": "Contributiones de {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 restante",
        "unblockip": "Disblocar adresse IP",
        "unblockiptext": "Usa le formulario infra pro restaurar le accesso de scriptura\na un adresse IP blocate previemente.",
        "ipusubmit": "Cancellar iste blocada",
        "block-log-flags-hiddenname": "nomine de usator celate",
        "range_block_disabled": "Le capacitate del administratores a blocar intervallos de adresses IP es disactivate.",
        "ipb_expiry_invalid": "Tempore de expiration invalide.",
+       "ipb_expiry_old": "Le hora de expiration es in le passato.",
        "ipb_expiry_temp": "Le blocadas de nomines de usator celate debe esser permanente.",
        "ipb_hide_invalid": "Impossibile supprimer iste conto; illo ha plus de {{PLURAL:$1|un modification|$1 modificationes}}.",
        "ipb_already_blocked": "\"$1\" es ja blocate",
        "lockedbyandtime": "(per $1 le $2 a $3)",
        "move-page": "Renominar $1",
        "move-page-legend": "Renominar pagina",
-       "movepagetext": "Per medio del formulario hic infra tu pote renominar un pagina, transferente tote su historia al nove nomine.\nLe ancian titulo devenira un pagina de redirection verso le nove titulo.\nTu pote actualisar automaticamente le redirectiones que puncta verso le titulo original.\nSi tu prefere non facer isto, non oblida de reparar omne redirectiones [[Special:DoubleRedirects|duple]] o [[Special:BrokenRedirects|rupte]].\nTu ha le responsabilitate de assecurar que le ligamines continua a punctar verso le paginas correcte.\n\nNota que le pagina '''non''' essera renominate si existe jam un pagina sub le nove titulo, excepte si iste es un redirection sin historia de modificationes passate.\nIsto te lassa le possibilitate de restaurar le titulo original de un pagina si tu ha committite un error, sin permitter te de supplantar un pagina existente.\n\n'''Attention!'''\nIsto pote esser un cambio drastic e inexpectate pro un pagina popular;\nper favor assecura te de haber comprendite le consequentias de isto ante de continuar.",
-       "movepagetext-noredirectfixer": "Per medio del formulario infra tu pote renominar un pagina, transferente tote su historia al nove nomine.\nLe ancian titulo devenira un pagina de redirection verso le nove titulo.\nNon oblida de reparar omne redirectiones [[Special:DoubleRedirects|duple]] o [[Special:BrokenRedirects|rupte]].\nTu ha le responsabilitate de assecurar que le ligamines continua a punctar verso le paginas correcte.\n\nNota que le pagina '''non''' essera renominate si existe jam un pagina sub le nove titulo, excepte si iste es un redirection sin historia de modificationes passate.\nIsto te lassa le possibilitate de restaurar le titulo original de un pagina si tu ha committite un error, sin permitter te de supplantar un pagina existente.\n\n'''Attention!'''\nIsto pote esser un cambio drastic e inexpectate pro un pagina popular;\nper favor assecura te de haber comprendite le consequentias de isto ante de continuar.",
+       "movepagetext": "Per medio del formulario hic infra tu pote renominar un pagina, transferente tote su historia al nove nomine.\nLe ancian titulo devenira un pagina de redirection verso le nove titulo.\nTu pote actualisar automaticamente le redirectiones que puncta verso le titulo original.\nSi tu prefere non facer isto, non oblida de reparar omne redirectiones [[Special:DoubleRedirects|duple]] o [[Special:BrokenRedirects|rupte]].\nTu ha le responsabilitate de assecurar que le ligamines continua a punctar verso le paginas correcte.\n\nNota que le pagina <strong>non</strong> essera renominate si existe jam un pagina sub le nove titulo, excepte si iste es un redirection sin historia de modificationes passate.\nIsto te lassa le possibilitate de restaurar le titulo original de un pagina si tu ha committite un error, sin permitter te de supplantar un pagina existente.\n\n<strong>Attention:</strong>\nisto pote esser un cambio drastic e inexpectate pro un pagina popular;\nper favor assecura te de haber comprendite le consequentias de isto ante de continuar.",
+       "movepagetext-noredirectfixer": "Per medio del formulario infra tu pote renominar un pagina, transferente tote su historia al nove nomine.\nLe ancian titulo devenira un pagina de redirection verso le nove titulo.\nNon oblida de reparar omne redirectiones [[Special:DoubleRedirects|duple]] o [[Special:BrokenRedirects|rupte]].\nTu ha le responsabilitate de assecurar que le ligamines continua a punctar verso le paginas correcte.\n\nNota que le pagina <strong>non</strong> essera renominate si existe jam un pagina sub le nove titulo, excepte si iste es un redirection sin historia de modificationes passate.\nIsto te lassa le possibilitate de restaurar le titulo original de un pagina si tu ha committite un error, sin permitter te de supplantar un pagina existente.\n\n<strong>Attention:</strong>\nisto pote esser un cambio drastic e inexpectate pro un pagina popular;\nper favor assecura te de haber comprendite le consequentias de isto ante de continuar.",
        "movepagetalktext": "Si tu marca iste quadrato, le pagina de discussion associate essera automaticamente renominate al nove titulo, a minus que un pagina de discussion non vacue ja existe sub le nove nomine.\n\nIn tal caso, tu debera renominar o fusionar le pagina manualmente si desirate.",
        "moveuserpage-warning": "'''Attention:''' Tu es super le puncto de renominar un pagina de usator. Nota ben que solmente le pagina, e ''non'' le usator, essera renominate.",
        "movecategorypage-warning": "<strong>Attention:</strong> Tu es sur le puncto de renominar un pagina de categoria. Nota ben que solmente le pagina essera renominate e tote le paginas in le ancian categoria <em>non</em> essera recategorisate in le nove.",
        "movenosubpage": "Iste pagina non ha subpaginas.",
        "movereason": "Motivo:",
        "revertmove": "reverter",
-       "delete_and_move_text": "==Deletion requirite==\nLe pagina de destination \"[[:$1]]\" existe ja.\nEsque tu vole deler lo pro permitter le renomination?",
+       "delete_and_move_text": "Le pagina de destination \"[[:$1]]\" jam existe.\nVole tu deler lo pro permitter iste renomination?",
        "delete_and_move_confirm": "Si, deler le pagina",
        "delete_and_move_reason": "Delite pro permitter le renomination de \"[[$1]]\"",
        "selfmove": "Le titulos de origine e de destination es identic;\nnon pote renominar un pagina al mesme titulo.",
        "move-leave-redirect": "Lassar un redirection",
        "protectedpagemovewarning": "'''Attention:''' Iste pagina ha essite protegite de sorta que solmente usatores con privilegios de administrator pote renominar lo. Le ultime entrata del registro es fornite hic infra pro referentia:",
        "semiprotectedpagemovewarning": "'''Nota:''' Iste pagina ha essite protegite de sorta que solmente usatores registrate pote renominar lo. Le ultime entrata del registro es fornite hic infra pro referentia:",
-       "move-over-sharedrepo": "== File existe ==\n[[:$1]] existe in un repositorio partite. Si le file es renominate a iste titulo, illo supplantara le file partite.",
+       "move-over-sharedrepo": "[[:$1]] jam existe in un repositorio commun. Si le file es renominate a iste titulo, illo supplantara le file commun.",
        "file-exists-sharedrepo": "Le nomine de file seligite es ja in uso in un repositorio partite.\nPer favor selige un altere nomine.",
        "export": "Exportar paginas",
        "exporttext": "Tu pote exportar le texto e historia de modificationes de un pagina particular o collection de paginas, incapsulate in un poco de XML.\nIsto pote esser importate in un altere wiki que usa MediaWiki via le [[Special:Import|pagina pro importar]].\n\nPro exportar paginas, entra le titulos in le quadro de texto infra, un titulo per linea, e indica si tu vole haber le version currente con tote le versiones ancian, con le lineas de historia de paginas, o simplemente le version actual con le informationes super le ultime modification.\n\nIn le secunde caso tu pote etiam usar un ligamine, p.ex. [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] pro le pagina \"[[{{MediaWiki:Mainpage}}]]\".",
        "export-download": "Salveguardar como file",
        "export-templates": "Includer patronos",
        "export-pagelinks": "Includer paginas ligate a un profunditate de:",
+       "export-manual": "Adder paginas manualmente:",
        "allmessages": "Messages del systema",
        "allmessagesname": "Nomine",
        "allmessagesdefault": "Texto predefinite",
        "import-nonewrevisions": "Nulle version ha essite importate (totes esseva jam presente o ha essite saltate a causa de errores).",
        "xml-error-string": "$1 al linea $2, col $3 (byte $4): $5",
        "import-upload": "Incargar datos XML",
-       "import-token-mismatch": "Perdita del datos del session. Per favor reprova.",
+       "import-token-mismatch": "Perdita del datos del session.\n\nEs possibile que tu session ha essite claudite. <strong>Per favor, verifica que tu session es ancora aperte e tenta lo de novo</strong>.\nSi le problema persiste, proba a [[Special:UserLogout|clauder session]] e aperir un nove session, verificante que tu navigator accepta le cookies ab iste sito.",
        "import-invalid-interwiki": "Non pote importar ab le wiki specificate.",
        "import-error-edit": "Le pagina \"$1\" non ha essite importate perque tu non ha le permission de modificar lo.",
        "import-error-create": "Le pagina \"$1\" non ha essite importate perque tu non ha le permission de crear lo.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versiones}} importate",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versiones}} importate desde $2",
        "javascripttest": "Test de JavaScript",
-       "javascripttest-pagetext-noframework": "Iste pagina es reservate pro le execution de tests de JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Structura de test \"$1\" incognite.",
        "javascripttest-pagetext-unknownaction": "Action \"$1\" incognite.",
-       "javascripttest-pagetext-frameworks": "Per favor selige un del sequente structuras de test: $1",
-       "javascripttest-pagetext-skins": "Selige un apparentia con le qual executar le tests:",
        "javascripttest-qunit-intro": "Vide [$1 documentation de tests] sur mediawiki.org.",
-       "tooltip-pt-userpage": "Tu pagina de usator",
+       "tooltip-pt-userpage": "{{GENDER:|Tu}} pagina de usator",
        "tooltip-pt-anonuserpage": "Le pagina de usator pro le adresse IP desde le qual tu face modificationes",
-       "tooltip-pt-mytalk": "Tu pagina de discussion",
+       "tooltip-pt-mytalk": "{{GENDER:|Tu}} pagina de discussion",
        "tooltip-pt-anontalk": "Discussion super le modificationes facite desde iste adresse IP",
-       "tooltip-pt-preferences": "Mi preferentias",
+       "tooltip-pt-preferences": "{{GENDER:|Tu}} preferentias",
        "tooltip-pt-watchlist": "Le lista de paginas del quales tu seque le modificationes",
-       "tooltip-pt-mycontris": "Lista de tu contributiones",
+       "tooltip-pt-mycontris": "Lista de {{GENDER:|tu}} contributiones",
        "tooltip-pt-anoncontribs": "Un lista de modificationes facite per iste adresse IP",
        "tooltip-pt-login": "Nos recommenda que tu te authentica, ma non es obligatori.",
        "tooltip-pt-logout": "Clauder session",
        "tooltip-t-recentchangeslinked": "Modificationes recente in le paginas al quales iste pagina contine ligamines",
        "tooltip-feed-rss": "Syndication RSS pro iste pagina",
        "tooltip-feed-atom": "Syndication Atom pro iste pagina",
-       "tooltip-t-contributions": "Vider le lista de contributiones de iste usator",
-       "tooltip-t-emailuser": "Inviar un e-mail a iste usator",
+       "tooltip-t-contributions": "Un lista de contributiones de {{GENDER:$1|iste usator}}",
+       "tooltip-t-emailuser": "Inviar un e-mail a {{GENDER:$1|iste usator}}",
        "tooltip-t-info": "Plus information super iste pagina",
        "tooltip-t-upload": "Incargar files",
        "tooltip-t-specialpages": "Lista de tote le paginas special",
        "lastmodifiedatby": "Le modification le plus recente de iste pagina esseva facite le $1 a $2 per $3.",
        "othercontribs": "A base de contributiones per $1.",
        "others": "alteres",
-       "siteusers": "le {{PLURAL:$2|usator|usatores}} $1 de {{SITENAME}}",
+       "siteusers": "le {{PLURAL:$2|{{GENDER:$1|usator}}|usatores}} $1 de {{SITENAME}}",
        "anonusers": "le {{PLURAL:$2|usator|usatores}} anonyme $1 de {{SITENAME}}",
        "creditspage": "Autores del pagina",
        "nocredits": "Nulle information es disponibile super le autores de iste pagina.",
        "pageinfo-category-files": "Numero de files",
        "markaspatrolleddiff": "Marcar como patruliate",
        "markaspatrolledtext": "Marcar iste pagina como patruliate",
+       "markaspatrolledtext-file": "Marcar iste version del file como patruliate",
        "markedaspatrolled": "Marcate como patruliate",
        "markedaspatrolledtext": "Le version seligite de [[:$1]] ha essite marcate como patruliate.",
        "rcpatroldisabled": "Patrulia de modificationes recente disactivate",
        "newimages-legend": "Filtro",
        "newimages-label": "Nomine del file (o un parte de illo):",
        "newimages-showbots": "Monstrar files incargate per robots",
+       "newimages-hidepatrolled": "Celar le files incargate patruliate",
        "noimages": "Nihil a vider.",
        "ilsubmit": "Cercar",
        "bydate": "per data",
        "exif-compression-4": "CCITT Group 4 codification fax",
        "exif-copyrighted-true": "Sub copyright",
        "exif-copyrighted-false": "Stato de copyright non definite",
+       "exif-photometricinterpretation-1": "Nigre e blanc (0 pro nigre)",
        "exif-unknowndate": "Data incognite",
        "exif-orientation-1": "Normal",
        "exif-orientation-2": "Invertite horizontalmente",
        "scarytranscludefailed-httpstatus": "[Obtention de patrono fallite pro $1: HTTP $2]",
        "scarytranscludetoolong": "[URL es troppo longe]",
        "deletedwhileediting": "'''Attention:''' Iste pagina esseva delite post que tu comenciava a modificar lo!",
-       "confirmrecreate": "Le usator [[User:$1|$1]] ([[User talk:$1|discussion]]) ha delite iste pagina post que tu comenciava a modificar lo, dante le motivo:\n: ''$2''\nPer favor confirma que tu realmente vole recrear iste pagina.",
-       "confirmrecreate-noreason": "Le usator [[User:$1|$1]] ([[User talk:$1|discussion]]) ha delite iste pagina post que tu comenciava a modificar lo. Per favor confirma que tu realmente vole recrear iste pagina.",
+       "confirmrecreate": "Le usator [[User:$1|$1]] ([[User talk:$1|discussion]]) ha {{GENDER:$1|delite}} iste pagina post que tu comenciava a modificar lo, dante le motivo:\n: <em>$2</em>\nPer favor confirma que tu realmente vole recrear iste pagina.",
+       "confirmrecreate-noreason": "Le usator [[User:$1|$1]] ([[User talk:$1|discussion]]) ha {{GENDER:$1|delite}} iste pagina post que tu comenciava a modificar lo. Per favor confirma que tu realmente vole recrear iste pagina.",
        "recreate": "Recrear",
        "confirm_purge_button": "OK",
        "confirm-purge-top": "Rader le cache de iste pagina?",
        "watchlisttools-edit": "Vider e modificar le observatorio",
        "watchlisttools-raw": "Modificar observatorio crude",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussion]])",
+       "timezone-local": "Local",
        "duplicate-defaultsort": "Attention: Le clave de ordination predefinite \"$2\" supplanta le anterior clave de ordination predefinite \"$1\".",
        "duplicate-displaytitle": "<strong>Attention:</strong> Le titulo a monstrar \"$2\" supplanta le ancian titulo a monstrar \"$1\".",
        "invalid-indicator-name": "<strong>Error:</strong> Le attributo <code>name</code> del indicatores del stato del pagina non pote esser vacue.",
        "version-libraries-license": "Licentia",
        "version-libraries-description": "Description",
        "version-libraries-authors": "Autores",
-       "redirect": "Rediriger per nomine de file, ID de usator, ID de pagina o ID de version",
-       "redirect-legend": "Rediriger a un file o pagina",
+       "redirect": "Rediriger per ID de file, usator, pagina, version o registro",
        "redirect-summary": "Iste pagina special redirige a un file (si es date le nomine de un file), a un pagina (si es date un ID de version o ID de pagina) o a un pagina de usator (si es date un ID de usator numeric). Usage: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] o [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Va",
        "redirect-lookup": "Cercar:",
        "tags-edit-reason": "Motivo:",
        "tags-edit-revision-submit": "Applicar cambiamentos a {{PLURAL:$1|iste version|$1 versiones}}",
        "tags-edit-logentry-submit": "Applicar cambiamentos a {{PLURAL:$1|iste entrata|$1 entratas}} de registro",
-       "tags-edit-success": "Le cambiamentos ha essite applicate con successo.",
+       "tags-edit-success": "Le cambiamentos ha essite applicate.",
        "tags-edit-failure": "Le cambiamentos non ha potite esser applicate:\n$1",
        "tags-edit-nooldid-title": "Le version de destination es invalide",
        "tags-edit-nooldid-text": "O tu non ha specificate un version de destination sur le qual exequer iste function, o le version specificate non existe.",
index be3b009..c710172 100644 (file)
@@ -44,7 +44,8 @@
                        "Matma Rex",
                        "WongKentir",
                        "Rachmat.Wahidi",
-                       "Arief"
+                       "Arief",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Garis bawahi pranala:",
        "recentchangeslinked-page": "Nama halaman:",
        "recentchangeslinked-to": "Perlihatkan perubahan dari halaman-halaman yang terhubung dengan halaman yang disajikan",
        "recentchanges-page-added-to-category": "[[:$1]] ditambahkan pada kategori",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] dan {{PLURAL:$2|satu halaman|$2 halaman-halaman}} lagi halaman ditambahkan pada kategori",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] dan [[Special:WhatLinksHere/$1|{{PLURAL:$2|satu halaman|$2 halaman-halaman}}]] lagi halaman ditambahkan pada kategori",
        "recentchanges-page-removed-from-category": "[[:$1]] dihapus dari kategori",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] dan {{PLURAL:$2|satu halaman|$2 halaman-halaman}} lagi halaman dihapus dari kategori",
        "autochange-username": "Perubahan otomatis MediaWiki",
index 6512608..c39fece 100644 (file)
@@ -8,7 +8,8 @@
                        "Urhixidur",
                        "לערי ריינהארט",
                        "아라",
-                       "Macofe"
+                       "Macofe",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Pinag-ugisan ti silpo:",
        "nocookieslogin": "Ti {{SITENAME}} ket agus-usar kadagiti galietas tapno maiserrek dagiti agar-aramat.\nNabaldado dagiti galietam.\nPangngaasi a pakabaelam ida ken padasem manen ti sumrek.",
        "nocookiesfornew": "Ti pakabilangan ti agar-aramat ket saan a napartuat, saanmi a mapasingkedan ti taudanna.\nSiguraduem a napakabaelan dagita galietam, ikarga manen daytoy a panid ken padasen manen.",
        "noname": "Saanmo a nainaganan ti umisu a nagan ti agar-aramat.",
-       "loginsuccesstitle": "Balligi ti panagserrek",
+       "loginsuccesstitle": "Nakastrek",
        "loginsuccess": "<strong>Nakastrekkan iti {{SITENAME}} a kas ni \"$1\".</strong>",
        "nosuchuser": "Awan ti agar-aramat nga agnagan iti \"$1\". \n\nDagiti nagan ti agar-aramat ket sensitibo ti kadakkel ti letra.\n\nKitaem ti panangiletram, wenno [[Special:UserLogin/signup|agpartuat iti baro a pakabilangan]].",
        "nosuchusershort": "Awan ti agar-aramat nga agnagan iti \"$1\".\nKitaem ti panangiletram.",
        "newpassword": "Baro a kontrasenias:",
        "retypenew": "Imakinilya manen ti baro a kontrasenias:",
        "resetpass_submit": "Isaad ti kontrasenias ken sumrek",
-       "changepassword-success": "Balligi a nasukatan ti kontraseniasmo!",
+       "changepassword-success": "Nasukatanen ti kontraseniasmo!",
        "changepassword-throttled": "Nakaaramidka kadagiti adu unay a nabiit a panangipadas ti panagserrek.\nPangngaasi nga aguray iti $1 sakbay a padasen manen.",
        "botpasswords": "Dagiti kontrasenias ti bot",
        "botpasswords-summary": "<em>Dagiti kontrasenias ti bot</em> ket mangpalubos a maserrekan ti pakabilangan ti agar-aramat babaen ti API a saan nga agusar kadagiti nangruna a kredensial ti pakabilangan. Dagiti magun-od a karbengan ti agar-aramat no nakastrek iti kontrasenias ti bot ket mabalin a nagawidan.\n\nNo saanmo nga ammo no apay a kayatmo nga aramiden daytoy, mabalin a saanmo koma nga aramiden daytoy. Awan koma ti mangdamag kaniam iti agpataud iti maysa kadagitoy ken itedmo kaniada.",
        "botpasswords-insert-failed": "Napaay iti pananginayon ti nagan ti bot iti \"$1\". Nainayon kadi idin?",
        "botpasswords-update-failed": "Napaay iti panagpabaro ti nagan ti bot iti \"$1\". Naikkat kadi idin?",
        "botpasswords-created-title": "Napartuat ti kontrasenias ti bot",
-       "botpasswords-created-body": "Balligi ti pannakapartuat ti kontrasenias ti bot iti \"$1\".",
+       "botpasswords-created-body": "Napartuat ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni agar-aramat \"$2\".",
        "botpasswords-updated-title": "Napabaro ti kontrasenias ti bot",
-       "botpasswords-updated-body": "Balligi ti pannakapabaro ti kontrasenias ti bot iti \"$1\".",
+       "botpasswords-updated-body": "Napabaro ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni agar-aramat \"$2\".",
        "botpasswords-deleted-title": "Naikkat ti kontrasenias ti bot",
-       "botpasswords-deleted-body": "Naikkat ti kontrasenias ti bot iti \"$1\".",
+       "botpasswords-deleted-body": "Naikkat ti kontrasenias ti bot para iti nagan ti bot iti \"$1\" ni agar-aramat \"$2\".",
        "botpasswords-newpassword": "Ti baro a kontrasenias iti panagserrek iti <strong>$1</strong> ket <strong>$2</strong>. <em>Pangngaasi nga irekord daytoy para iti masakbayan a reperensia.</em>",
        "botpasswords-no-provider": "Saan a magun-od ti BotPasswordsSessionProvider.",
        "botpasswords-restriction-failed": "Ti panangigawid ti kontrasenias ti bot ket nangpawil iti daytoy a panagserrek.",
        "resetpass-no-info": "Masapul a nakastrekka tapno dagus a makapanka iti daytoy a panid.",
        "resetpass-submit-loggedin": "Sukatan ti kontrasenias",
        "resetpass-submit-cancel": "Ukasen",
-       "resetpass-wrong-oldpass": "Imbalido ti temporario wenno agdama a kontrasenias.\nMabalin a nagballigi ti panagsukatmo ti kontrasenias wenno nagkiddaw ti baro a temporario a kontrasenias.",
+       "resetpass-wrong-oldpass": "Imbalido ti temporario wenno agdama a kontrasenias.\nMabalin a nasukatamon ti kontrasenias wenno nagkiddaw ti baro a temporario a kontrasenias.",
        "resetpass-recycled": "Pangngaasi nga isaad manen ti kontrasenias iti sabali ngem ti agdama a kontraseniasmo.",
        "resetpass-temp-emailed": "Simrekka a nagusar ti temporario a naipatulod a kodigo.\nTapno malpas ti panagserrek, nasken a mangisaadka ti baro a kontrasenias ditoy:",
        "resetpass-temp-password": "Temporario a kontrasenias:",
        "revdelete-unsuppress": "Ikkaten dagiti panangigawid kadagiti naipulang a rebision",
        "revdelete-log": "Rason:",
        "revdelete-submit": "Ipakat {{PLURAL:$1|ti napili a rebision|dagiti napili a rebision}}",
-       "revdelete-success": "Balligi ti panagpabaro ti panagkita ti rebision.",
+       "revdelete-success": "Napabaro ti panagkita ti rebision.",
        "revdelete-failure": "Saan a napabaro ti panagkita ti rebision.\n$1",
-       "logdelete-success": "Balligi ti pannakaisaad ti listaan ti panagkita.",
+       "logdelete-success": "Naisaad ti listaan ti panagkita.",
        "logdelete-failure": "Napaay ti pannakaisaad ti listaan ti panagkita:\n$1",
        "revdel-restore": "sukatan ti panagkita",
        "pagehist": "Pakasaritaan ti panid",
        "userrights-changeable-col": "Dagiti grupo a mabalinmo a baliwan",
        "userrights-unchangeable-col": "Dagiti grupo a dimo mabalin a baliwan",
        "userrights-conflict": "Suppiat dagiti panagbaliw kadagiti karbengan ti agar-aramat! Pangngaasi nga irepasom ken pasingkedam dagiti sinuksukatam.",
-       "userrights-removed-self": "Nagballigika a nagikkat kadagiti bukodmo a karbengan. Iti kastoyen, saankan a mabalin a mangserrek iti daytoy a panid.",
+       "userrights-removed-self": "Inikkatmo kadagiti bukodmo a karbengan. Iti kastoyen, saankan a mabalin a mangserrek iti daytoy a panid.",
        "group": "Grupo:",
        "group-user": "Dagiti agar-aramat",
        "group-autoconfirmed": "Dagiti automatiko a napasingkedan nga agar-aramat",
        "recentchangeslinked-page": "Nagan ti panid:",
        "recentchangeslinked-to": "Ipakita dagiti sinukatan kadagiti panid nga imbes a naisilpo iti naited a panid",
        "recentchanges-page-added-to-category": "nainayon ti [[:$1]] iti kategoria",
-       "recentchanges-page-added-to-category-bundled": "nainayon ti [[:$1]] ken {{PLURAL:$2|maysa a panid|$2 a pampanid}} iti kategoria",
+       "recentchanges-page-added-to-category-bundled": "nainayon ti [[:$1]] ken [[Special:WhatLinksHere/$1|{{PLURAL:$2|maysa a panid|$2 a pampanid}}]] iti kategoria",
        "recentchanges-page-removed-from-category": "naikkat ti [[:$1]] manipud iti kategoria",
        "recentchanges-page-removed-from-category-bundled": "Naikkat ti [[:$1]] ken {{PLURAL:$2|maysa a panid|$2 a pampanid}} manipud iti kategoria",
        "autochange-username": "Automatiko a panagbaliw iti MediaWiki",
        "uploadstash-summary": "Daytoy a panid ket mangited ti panagserrek kadagiti papeles a naikarga wenno mangrugrugi iti proseso a maikarga, ngem saan pay a naipablaak iti wiki. Dagitoy a papeles ket saan a makita ti sinoman ngem ti laeng agar-aramat a nagikarga kaniada.",
        "uploadstash-clear": "Dalusan dagiti na-stash a papeles",
        "uploadstash-nofiles": "Awan ti na-stash a papelesmo.",
-       "uploadstash-badtoken": "Ti panag-tungpal dayta nga aramid ket napaay, ngamin ta dagiti talekmo ti panagurnos ket nagpason. Padasen manen.",
-       "uploadstash-errclear": "Ti panagdalus kadagiti papeles ket napaay.",
+       "uploadstash-badtoken": "Napaay ti panagtungpal dayta nga aramid. Mabalin a ti talekmo nga agurnos ket nagpason. Pangngaasi a padasen manen.",
+       "uploadstash-errclear": "Napaay ti panagdalus kadagiti papeles.",
        "uploadstash-refresh": "Pasadiwaen dagiti listaan ti papeles",
        "invalid-chunk-offset": "Imbalido a pirgis ti timbengan",
        "img-auth-accessdenied": "Nalibak ti iseserrek",
        "changecontentmodel-title-label": "Titulo ti panid",
        "changecontentmodel-model-label": "Baro a modelo ti linaon",
        "changecontentmodel-reason-label": "Rason:",
+       "changecontentmodel-submit": "Baliwan",
        "changecontentmodel-success-title": "Nabaliwan ti modelo ti linaon",
        "changecontentmodel-success-text": "Nabaliwanen ti kita ti linaon ti [[:$1]].",
        "changecontentmodel-cannot-convert": "Ti linaon iti [[:$1]] ket saan a mabaliwan iti kita ti $2.",
        "tooltip-feed-rss": "RSS a pakan para iti daytoy a panid",
        "tooltip-feed-atom": "Atom a pakan para iti daytoy a panid",
        "tooltip-t-contributions": "Ti listaan dagiti kontribusion babaen {{GENDER:$1|daytoy nga agar-aramat}}",
-       "tooltip-t-emailuser": "Patulodan ti esurat daytoy nga agar-aramat",
+       "tooltip-t-emailuser": "Patulodan ti esurat {{GENDER:$1|daytoy nga agar-aramat}}",
        "tooltip-t-info": "Adu pay a pakaammo a maipanggep iti daytoy a panid",
        "tooltip-t-upload": "Agikarga kadagiti papeles",
        "tooltip-t-specialpages": "Listaan ti amin nga espesial a pampanid",
        "lastmodifiedatby": "Daytoy a panid ket naudi a nabaliwan idi $2, $1 babaen ni $3.",
        "othercontribs": "Naibasar iti obra ni $1.",
        "others": "dadduma pay",
-       "siteusers": "{{SITENAME}}  {{PLURAL:$2|agar-aramat|dagiti agar-aramat}}  $1",
+       "siteusers": "{{PLURAL:$2|{{GENDER:$1|ni agar-aramat}}|da agar-aramat}} $1 ti {{SITENAME}}",
        "anonusers": "{{SITENAME}} di ammo {{PLURAL:$2|nga agar-aramat|a digiti agar-aramat}} $1",
        "creditspage": "Dagiti pammadayaw ti panid",
        "nocredits": "Awan dagiti pakaammo ti pammadayaw a magun-od para iti daytoy a panid.",
        "scarytranscludefailed-httpstatus": "[Napaay ti panagala ti plantilia para iti $1: HTTP $2]",
        "scarytranscludetoolong": "[Atiddog unay ti URL]",
        "deletedwhileediting": "<strong>Ballaag:</strong> Naikkaten daytoy a panid kalpasan idi rinugiam ti agurnos!",
-       "confirmrecreate": "Ti ([[User talk:$1|patungtungan]]) ti agar-aramat [[User:$1|$1]] ket inikkatna daytoy a panid kalpasan ti panagrugim nga agurnos nga adda rason:\n: ''$2''\nPangngaasi a pasingkedam nga agpayso a kayatmo a partuten manen daytoy a panid.",
-       "confirmrecreate-noreason": "Ti ([[User talk:$1|patungtungan]]) ti agar-aramat [[User:$1|$1]] ket inikkat na daytoy a panid idi kalkalpas mo a magirugi ti agurnos. Pangngaasi ta pasingkedam a kayatmo nga aramiden manen daytoy a panid.",
+       "confirmrecreate": "{{GENDER:$1|Inikkat}} ni agar-aramat [[User:$1|$1]] ([[User talk:$1|tungtungan]])  daytoy a panid kalpasan idi nangrugika nga agurnos iti rason a:\n: <em>$2</em>\nPangngaasi a pasingkedan no agpayso a kayatmo a partuaten manen daytoy a panid",
+       "confirmrecreate-noreason": "{{GENDER:$1|Inikkat}} ni agar-aramat [[User:$1|$1]] ([[User talk:$1|tungtungan]]) daytoy a panid kalpasan idi nangrugika nga agurnos. Pangngaasi a pasingkedan no agpayso a kayatmo a partuaten manen daytoy a panid.",
        "recreate": "Partuaten manen",
        "confirm_purge_button": "Sige",
        "confirm-purge-top": "Dalusan ti cache daytoy a panid?",
        "tags-delete-not-allowed": "Dagiti etiketa nga inpalawag babaen ti maysa a pagpaatiddog ket saan a maikkat malaksid no naisangayan nga ipalubos ti pagpaatiddog.",
        "tags-delete-not-found": "Awan ti etiketa ti \"$1\".",
        "tags-delete-too-many-uses": "Ti etiketa ti \"$1\" ket naipakat iti ad-adu ngem $2 {{PLURAL:$2|a rebision|kadagiti rebision}}, a ti kaibuksillanna ket saan a mabalin a maikkat.",
-       "tags-delete-warnings-after-delete": "Ti etiketa ti \"$1\" ket balligi a naikkat, ngem nakita {{PLURAL:$2|ti sumaganad a ballag|dagiti sumaganad a balaag}}:",
+       "tags-delete-warnings-after-delete": "Ti etiketa ti \"$1\" ket naikkat, ngem nakita {{PLURAL:$2|ti sumaganad a ballaag|dagiti sumaganad a ballaag}}:",
        "tags-activate-title": "Patarayen ti etiketa",
        "tags-activate-question": "Isagsaganamon a patarayen ti etiketa ti \"$1\".",
        "tags-activate-reason": "Rason:",
        "tags-edit-revision-legend": "Aginayon wenno agikkat kadagiti etiketa manipud {{PLURAL:$1|ti daytoy a rebision|kadagiti amin a $1 a rebision}}",
        "tags-edit-logentry-legend": "Aginayon wenno agikkat kadagiti etiketa manipud {{PLURAL:$1|ti daytoy a listaan ti naikabil|kadagiti amin a $1 a listaan ti naikabkabil}}",
        "tags-edit-existing-tags": "Dagiti adda nga etiketa:",
-       "tags-edit-existing-tags-none": "''Awan''",
+       "tags-edit-existing-tags-none": "<em>Awan</em>",
        "tags-edit-new-tags": "Dagiti baro nga etiketa:",
        "tags-edit-add": "Inayon dagitoy nga etiketa:",
        "tags-edit-remove": "Ikkaten dagitoy nga etiketa:",
        "tags-edit-reason": "Rason:",
        "tags-edit-revision-submit": "Ipakat dagiti binaliwan {{PLURAL:$1|iti daytoy a rebision|kadagiti $1 a rebision}}",
        "tags-edit-logentry-submit": "Ipakat dagiti panagbaliw {{PLURAL:$1|iti daytoy a listaan ti naikabil|kadagiti $1 a listaan ti naikabkabil}}",
-       "tags-edit-success": "Balligi a naipakat dagiti binaliwan.",
+       "tags-edit-success": "Naipakat dagiti binaliwan.",
        "tags-edit-failure": "Saan a maipakat dagiti binaliwan:\n$1",
        "tags-edit-nooldid-title": "Imbalido a rebision ti puntaan",
        "tags-edit-nooldid-text": "Saanka a nanginagan ti ania man a rebision a puntaan a pagaramidan daytoy nga annong, wenno awan ti nainaganan a rebision.",
index 2241d06..24aaf0f 100644 (file)
@@ -57,6 +57,8 @@
        "editfont-style": "Нийсдара меттига чу йола зарба б|армат:",
        "editfont-default": "Браузерен гӀирса чура шрифт",
        "editfont-monospace": "Башхалон зарба",
+       "editfont-sansserif": "Белгало йоаца шрифт",
+       "editfont-serif": "Белгало йола шрифт",
        "sunday": "К|иранди",
        "monday": "Оршот",
        "tuesday": "Шинара",
        "thu": "Ер",
        "fri": "П|аь",
        "sat": "Шоа",
-       "january": "Ð\9dажгамÑ\81Ñ\85ой",
-       "february": "Саькур",
-       "march": "Муттхьол",
-       "april": "Тушоли",
-       "may_long": "Ð\91екаÑ\80г",
-       "june": "Ð\90Ñ\8cÑ\82инг",
-       "july": "Ð\9a|имаÑ\80Ñ\81",
-       "august": "Мангал",
-       "september": "Ð\9cоажол",
-       "october": "Тов",
-       "november": "Лайчил",
-       "december": "Чантар",
+       "january": "Ð\90гIой Ð±Ñ\83Ñ\82Ñ\82",
+       "february": "Саь-кур бутт",
+       "march": "Мутт-хьал бутт",
+       "april": "Тушоли бутт",
+       "may_long": "Села Ð±Ñ\83Ñ\82Ñ\82",
+       "june": "ЭÑ\82инга Ð±Ñ\83Ñ\82Ñ\82",
+       "july": "Ð\91аÑ\8cÑ\86амеа\\Ð\9cеа Ð±Ñ\83Ñ\82Ñ\82",
+       "august": "Мяцхали бутт",
+       "september": "Тов\\Ð\9cиÑ\85ий Ð±Ñ\83Ñ\82Ñ\82",
+       "october": "Ð\90Ñ\80даÑ\80ий\\Ð\90Ñ\8cÑ\80Ñ\85Iий Ð±Ñ\83Ñ\82Ñ\82",
+       "november": "Лай чилла бутт",
+       "december": "Чан-тар бутт",
        "january-gen": "Нажгамсхой бетт",
        "february-gen": "Саькур бетт",
        "march-gen": "Муттхьол бетт",
        "april-gen": "Тушоли бетт",
-       "may-gen": "Ð\91екаÑ\80г бетт",
-       "june-gen": "Ð\90Ñ\8cÑ\82инг бетт",
-       "july-gen": "Ð\9a|имаÑ\80Ñ\81 бетт",
-       "august-gen": "Ð\9cангал бетт",
-       "september-gen": "Ð\9cоажол бетт",
-       "october-gen": "Тов бетт",
-       "november-gen": "Лайчил бетт",
+       "may-gen": "Села бетт",
+       "june-gen": "ЭÑ\82инга бетт",
+       "july-gen": "Ð\91аÑ\8cÑ\86амеа\\Ð\9cеа бетт",
+       "august-gen": "Ð\9cеÑ\86Ñ\85али бетт",
+       "september-gen": "Тов\\Ð\9cиÑ\85ий бетт",
+       "october-gen": "Ð\90Ñ\80даÑ\80ий\\Ð\90Ñ\8cÑ\80Ñ\85Iий бетт",
+       "november-gen": "Лай чилла бетт",
        "december-gen": "Чантар бетт",
-       "jan": "Ð\9dажг.",
-       "feb": "Саьк.",
-       "mar": "Мутт.",
-       "apr": "Tуш.",
-       "may": "Ð\91ек.",
-       "jun": "Ð\90Ñ\8cÑ\82.",
-       "jul": "Ð\9a|им.",
-       "aug": "Манг.",
-       "sep": "Ð\9cоаж.",
-       "oct": "Тов.",
-       "nov": "Лайч.",
-       "dec": "Чант.",
+       "jan": "Ð\90гIой",
+       "feb": "Саь-кур",
+       "mar": "Мутт-хьал",
+       "apr": "Tушоли",
+       "may": "Села",
+       "jun": "Ð\9cангал\\ЭÑ\82инга",
+       "jul": "Ð\91аÑ\8cÑ\86амеа\\Ð\9cеа",
+       "aug": "Мяцхали",
+       "sep": "Тов\\Ð\9cиÑ\85ий",
+       "oct": "Ð\90Ñ\80даÑ\80ий\\Ð\90Ñ\8cÑ\80Ñ\85Iий",
+       "nov": "Лай чилла",
+       "dec": "Чан-тар",
        "january-date": "Нажгамсхой $1",
        "february-date": "Саькур $1",
        "march-date": "Муттхьол $1",
        "april-date": "Тушоли $1",
-       "may-date": "Ð\91екаÑ\80г $1",
+       "may-date": "Села Ð±Ñ\83Ñ\82Ñ\82 $1",
        "june-date": "Аьтинг $1",
        "july-date": "К|имарс $1",
        "august-date": "Мангал $1",
        "september-date": "Моажол $1",
        "october-date": "Тов $1",
-       "november-date": "Лайчил $1",
+       "november-date": "Лай чилла бутт $1",
        "december-date": "Чантар $1",
-       "pagecategories": "{{PLURAL:$1|1=Катаг|Катагаш}}",
+       "period-am": "ДЦ",
+       "period-pm": "ДТ",
+       "pagecategories": "{{PLURAL:$1|1=Категори|Категореш}}",
        "category_header": "\"$1\" Катага чура оаг|онаш",
        "subcategories": "Чуракатагаш",
-       "category-media-header": "\"$1\" Ð\9aаÑ\82ага Ñ\87Ñ\83Ñ\80а Ð¿Ð°Ñ\8cлаш",
+       "category-media-header": "\"$1\" Ð\9aаÑ\82егоÑ\80и Ñ\87Ñ\83Ñ\80а Ñ\84айлаш",
        "category-empty": "''Укх катага чу цхьаккха оаг|онаш е паьлаш яц.''",
        "hidden-categories": "{{PLURAL:$1|1=Къайла катаг|Къайла катагаш}}",
        "hidden-category-category": "Къайла катагаш",
        "category-subcat-count-limited": "Укх катагa чу {{PLURAL:$1|1=$1 к|алкатаг|$1 к|алкатагаш}}.",
        "category-article-count": "{{PLURAL:$2|Укх катага цхьа оаг|ув мара чулоацац.|{{PLURAL:$1|1=$1 оаг|ув хьахекха я|$1 оаг|oнаш хьахекха я}} укх катага $2 йолачарeх.}}",
        "category-article-count-limited": "Укх катага чу {{PLURAL:$1|1=$1 оаг|ув|$1 оаг|oнаш}}.",
-       "category-file-count": "{{PLURAL:$2|Укх катаг чу цхьа лурдар мара дац.|{{PLURAL:$1|1=$1 лурдар хьахьекха я|$1 лурдараш хьахьекха я}} укх катагa $2 долачаьрeх.}}",
+       "category-file-count": "{{PLURAL:$2|Укх катагори чу цаI мара файл дац.|{{PLURAL:$1|1=$1 файл хьахьокхаш я|$1 файл хьахьокхаш я}} укх категори $2 долачарeх.}}",
        "category-file-count-limited": "Укх катага чу {{PLURAL:$1|1=$1 лурдар|$1 лурдараш}}.",
        "listingcontinuesabbrev": "д|ахо",
        "index-category": "Д|ахьожама оаг|онаш",
        "morenotlisted": "Ер |ояздар хьалдиззанз да.",
        "mypage": "Oаг|ув",
        "mytalk": "Дувцам",
-       "anontalk": "УкÑ\85 IP-меÑ\82Ñ\82ига Ð´Ñ\83вÑ\86ам",
-       "navigation": "Наькъатохкарг",
-       "and": "&#32;кÑ\85Ñ\8b",
+       "anontalk": "Ð\94Ñ\83вÑ\86аÑ\80",
+       "navigation": "Навигаци",
+       "and": "&#32;а",
        "qbfind": "Лахар",
        "qbbrowse": "Б|аргтасса",
        "qbedit": "Хувца",
        "faq": "КТХ",
        "faqpage": "Project:КТХ",
        "actions": "Х|амдараш",
-       "namespaces": "Ц|ерий аренаш",
-       "variants": "Ð\94еÑ\88кепаш",
-       "navigation-heading": "Наькъагойтара хоржаг|ирс",
+       "namespaces": "ЦIерий мотташ",
+       "variants": "Ð\9aеÌ\81паш",
+       "navigation-heading": "Навигацен меню",
        "errorpagetitle": "Г|алат",
        "returnto": "цу $1 оаг|он т|а юхаг|о",
-       "tagline": "Кечал укхазара я {{SITENAME}}",
-       "help": "Ð\9aÑ\83Ñ\86Ñ\82оÑ\85кам",
+       "tagline": "Кечал укхазара: {{grammar:genitive|{{SITENAME}}}}",
+       "help": "Ð\93Ó\80о",
        "search": "Лахаp",
-       "searchbutton": "Ð\9bаÑ\85аÑ\80",
+       "searchbutton": "Ð¥Ñ\8cалáÑ\85а",
        "go": "Дехьа г|о",
-       "searcharticle": "Дехьа г|о",
+       "searcharticle": "Дехьавала",
        "history": "Истори",
-       "history_short": "ТаÑ\80Ñ\85Ñ\8cаÑ\80",
+       "history_short": "Ð\98Ñ\81Ñ\82оÑ\80и",
        "updatedmarker": "Со ханача денца хувцамаш хиннaд",
-       "printableversion": "Ð\9aепаÑ\82оÑ\85аÑ\80а Ð½Ð¸Ð¹Ñ\81Ñ\85Ñ\8cал",
-       "permalink": "Даиман латташ йола хьожадерг",
+       "printableversion": "Ð\97аÑ\80ба Ñ\82оÑ\85аÑ\80а Ð²ÐµÑ\80Ñ\81и",
+       "permalink": "Даиман латташ йола хьожаярг",
        "print": "Кепатохар",
        "view": "Б|аргтассам",
        "view-foreign": "Мазаоаг|он чу $1 хьажа",
-       "edit": "Хувца",
+       "edit": "Нийсде",
+       "edit-local": "Хувца локальни йоазонца сурт оттадар",
        "create": "Хьаде",
+       "create-local": "ТIатоха локальни йоазонца сурт оттадар",
        "editthispage": "Ер оаг|ув хувца",
        "create-this-page": "Ep oаг|ув хьае",
        "delete": "Д|аяккха",
        "unprotectthispage": "Лорам хувца",
        "newpage": "Керда оагӀув",
        "talkpage": "Укх оаг|он т|а дувцам бе",
-       "talkpagelinktext": "дувцам",
+       "talkpagelinktext": "дувца оттадар",
        "specialpage": "Г|улакхадара оаг|ув",
-       "personaltools": "Са Ð³|ирсаш",
+       "personaltools": "Ð\94оакÑ\8aаÑ\88Ñ\85оÑ\87Ñ\83н Ð³Ó\80ирсаш",
        "articlepage": "Йоазон т|а б|аргтасса",
-       "talk": "Дувцам",
-       "views": "Ð\91Ó\80аÑ\80гÑ\82аÑ\81Ñ\81амаш",
+       "talk": "Дувца оттадар",
+       "views": "Ð¥Ñ\8cажаÑ\80аш",
        "toolbox": "ГӀирсаш",
        "userpage": "Доакъошхочун оаг|он т|а б|аргтасса",
        "projectpage": "Хьахьоадайтама оаг|oн т|а б|аргтасса",
        "imagepage": "Лурдара оаг|oн т|а б|аргтасса",
        "mediawikipage": "Xоаман оаг|ув хьахьокха",
        "templatepage": "Ч|абала оаг|oн т|а б|аргтасса",
-       "viewhelppage": "Ð\9aÑ\83Ñ\86Ñ\82оÑ\85кам Ð±ÐµÑ\85а",
+       "viewhelppage": "Ð\93Ó\80о Ñ\85Ñ\8cаÑ\8dÑ\86аÑ\80",
        "categorypage": "Катага оаг|oн т|а б|аргтасса",
        "viewtalkpage": "Дувцамага б|аргтасса",
        "otherlanguages": "Кхыча меттаех",
        "redirectedfrom": "($1 т|aра хьадейта да)",
        "redirectpagesub": "Д|а-хьа дайта оаг|ув",
-       "redirectto": "Ð\94|аÑ\85Ñ\8cожаде Ñ\83кÑ\85 Ñ\82|а:",
-       "lastmodifiedat": "Укх оаг|oн т|ехьара  хувцам: $2, $1.",
+       "redirectto": "ТIаÑ\85Ñ\8cожадаÑ\80 Ñ\83кÑ\85аза:",
+       "lastmodifiedat": "Укх оагIoн тIехьара хувцам: $2, $1.",
        "viewcount": "Укх оаг|oн т|а б|аргтассаб {{PLURAL:$1|цхьааца\n|$1 times}}. {{PLURAL:$1|1=цхьазза|$1за}}.",
        "protectedpage": "Лорама оаг|ув",
-       "jumpto": "УкÑ\85аза Ð´ÐµÑ\85Ñ\8cаг|о:",
-       "jumptonavigation": "наькъатоxкар",
-       "jumptosearch": "лaхаp",
+       "jumpto": "Ð\94еÑ\85Ñ\8cавала Ñ\83кÑ\85аза:",
+       "jumptonavigation": "навигаци",
+       "jumptosearch": "лахар",
        "pool-timeout": "ЧIегатохара сабаран ха чакхаяьннай",
        "pool-queuefull": "Хаттарий цӀа хьалдизад",
        "pool-errorunknown": "Довзаш доаца гӀалат",
        "poolcounter-usage-error": "Лелдара г|алат: $1",
-       "aboutsite": "Лоацам {{SITENAME}}",
+       "aboutsite": "{{grammar:genitive|{{SITENAME}}}} лаьца",
        "aboutpage": "Project:Лоацам",
        "copyright": "$1 чулоацамаца тIакхоачаш да.",
        "copyrightpage": "{{ns:project}}:Яздаьчунна бокъо",
        "currentevents": "ХӀанзара хоамаш",
        "currentevents-url": "Project:ХӀанзара хоамаш",
-       "disclaimers": "Ð\91окÑ\8aонаÑ\85 Ñ\8eÑ\85авалаp",
-       "disclaimerpage": "Project:Ð\91окÑ\8aонаÑ\85 Ñ\8eÑ\85авалаp",
-       "edithelp": "Ð¥Ñ\83вÑ\86ама ÐºÑ\83Ñ\86Ñ\82оÑ\85кам",
-       "helppage-top-gethelp": "Г|о",
+       "disclaimers": "Ð\91еÑ\85кÑ\82окÑ\85ам Ñ\85Ñ\8cаÑ\86аÑ\8dÑ\86аÑ\80",
+       "disclaimerpage": "Project:Ð\91еÑ\85кÑ\82окÑ\85ам Ñ\85Ñ\8cаÑ\86аÑ\8dÑ\86аÑ\80",
+       "edithelp": "Ð¥Ñ\83вÑ\86ама Ð³Ó\80о",
+       "helppage-top-gethelp": "ГӀо",
        "mainpage": "Кертера оагӀув",
        "mainpage-description": "Кертера оагӀув",
        "policy-url": "Project:Бокъонаш",
-       "portal": "Ð\93Ñ\83лламков",
-       "portal-url": "Project:Ð\93Ñ\83лламков",
-       "privacy": "Ð\9fаÑ\8cлбокÑ\8aо",
-       "privacypage": "Project:Ð\9fаÑ\8cлбокÑ\8aо",
+       "portal": "ЮкÑ\8aаÑ\80а ков",
+       "portal-url": "Project:ЮкÑ\8aаÑ\80а ков",
+       "privacy": "Ð\9aÑ\8aайлагIаÑ\80а Ñ\85Iамай Ð¿Ð¾Ð»Ð¸Ñ\82ика",
+       "privacypage": "Project:Ð\9aÑ\8aайлагIаÑ\80а Ñ\85Iамай Ð¿Ð¾Ð»Ð¸Ñ\82ика",
        "badaccess": "Чуваларa гӀалат",
        "badaccess-group0": "Оаш хьадийха дулархIам шун де йишяц.",
        "badaccess-groups": "Дахта кхоачашдар {{PLURAL:$2|1=тоабачара|тоабашкара}} $1 дакъалаьцархой мара де бокъо яц.",
        "versionrequired": "$1 MediaWiki доржам эша",
        "versionrequiredtext": "Укх оагӀув бeлха MediaWiki доржамаш эша $1. Хьажа [[Special:Version|version page]].",
        "ok": "ХӀаа",
-       "retrievedfrom": "\"$1\" ГӀувам",
+       "retrievedfrom": "Хьаст — «$1»",
        "youhavenewmessages": "Оаш $1 ($2) дӀайийцад",
        "youhavenewmessagesmulti": "Оаш $1чу керда хоамаш дӀайийцад",
-       "editsection": "хувца",
+       "editsection": "нийсде",
        "editold": "хувца",
        "viewsourceold": "xьайоагӀа къайлорг тӀа бӀаргтасса",
        "editlink": "хувца",
        "viewsourcelink": "xьайоагӀа къайлорг тӀа бӀаргтасса",
-       "editsectionhint": "Декъам хувца: $1",
+       "editsectionhint": "Дáкъа хувца: $1",
        "toc": "Чулоацам",
        "showtoc": "хьахьокха",
        "hidetoc": "къайладаккха",
        "restorelink": "{{PLURAL:$1|1=д|адaьккха хувцам|$1 д|адaьккха хувцамаш}}",
        "feedlinks": "Цу тайпара:",
        "site-rss-feed": "$1 RSS мугӀ",
-       "site-atom-feed": "$1 Atom мугӀ",
+       "site-atom-feed": "$1 — Atom-мугI",
        "page-rss-feed": "\"$1\" RSS мугӀ",
        "page-atom-feed": "«$1» — Atom-мугI",
        "red-link-title": "$1 (укх тайпара оагӀув яц)",
        "nstab-user": "Дакъалаьцархо",
        "nstab-media": "Медифаг",
        "nstab-special": "ГӀулакха оагӀув",
-       "nstab-project": "Ð¥Ñ\8cаÑ\85оадайÑ\82амах лаьца",
-       "nstab-image": "Ð\9fаÑ\8cл",
+       "nstab-project": "Ð\9fÑ\80оекÑ\82ах лаьца",
+       "nstab-image": "Файл",
        "nstab-mediawiki": "Хоам",
-       "nstab-template": "ЧIабал",
-       "nstab-help": "Ð\9aÑ\83Ñ\86Ñ\82оÑ\85кам",
+       "nstab-template": "Ð\9aеп",
+       "nstab-help": "Ð\93Ó\80о",
        "nstab-category": "Катаг",
        "mainpage-nstab": "Кертера оагӀув",
        "nosuchaction": "Цу тайпара дулархIам бац",
        "internalerror_info": "Чура гӀалат: $1",
        "cannotdelete-title": "ОагIув дIаяккха йиш яц \"$1\"",
        "badtitle": "Мегаш йоаца цӀи",
-       "badtitletext": "Ð\94еÑ\85аÑ\88 Ð´Ð¾Ð»Ð° Ð¾Ð°Ð³Ó\80Ñ\83вни Ñ\86Ó\80и, Ð½Ð¸Ð¹Ñ\81а Ñ\8fÑ\86, Ñ\8fÑ\8cÑ\81Ñ\81а Ñ\8f Ðµ Ð¼ÐµÑ\82Ñ\82аÑ\8eкÑ\8aаÑ\80а Ðµ Ð¼Ð°Ñ\81Ñ\81аÑ\8eкÑ\8aаÑ\80а Ñ\86Ó\80и Ñ\85аÑ\80Ñ\86аÑ\85Ñ\8c Ñ\8f. Ð¦Ó\80еÑ\80а Ñ\8eкÑ\8aе Ð¼ÐµÐ³Ð°Ñ\88 Ð´Ð¾Ð°Ñ\86а Ñ\85аÑ\80акÑ\8aаÑ\88 Ð½Ð¸Ð¹Ñ\81аденна Ñ\85ила Ð¼ÐµÐ³Ð°ш да.",
+       "badtitletext": "Ð\95заÑ\88 Ð¹Ð¾Ð»Ð° Ð¾Ð°Ð³Ó\80Ñ\83ва Ñ\86Ó\80и Ð½Ð¸Ð¹Ñ\81а Ñ\8fÑ\86, Ñ\8fÑ\8cÑ\81Ñ\81а Ñ\8f, Ðµ Ñ\85аÑ\80Ñ\86аÑ\85Ñ\8c Ñ\8f Ð¼ÐµÑ\82Ñ\82аÑ\8eкÑ\8aаÑ\80а Ñ\86Iи Ðµ Ð¸Ð½Ñ\82еÑ\80вики Ñ\86Ó\80и. Ð\98Ñ\88Ñ\82Ñ\82а, Ñ\86Ó\80еÑ\80а Ñ\8eкÑ\8aе Ð¾Ñ\82Ñ\82аде Ð¼ÐµÐ³Ð°Ñ\88 Ð´Ð¾Ð°Ñ\86а Ñ\85Ñ\8cаÑ\80акÑ\8aаÑ\88 Ð½Ð¸Ð¹Ñ\81аденна Ñ\85ила Ñ\82аÑ\80лÑ\83ш да.",
        "viewsource": "БIаргтассам",
        "actionthrottled": "Сихален овзамал",
        "protectedpagetext": "Ер оаг|ув къайла я хувцамаш дергдоацаш е кхы дола х|амдараш.",
        "virus-unknownscanner": "довзашдоаца мазаундохьалург:",
        "welcomeuser": "Маьрша доаг|алд, $1!",
        "yourname": "Дакъалаьцархочунна цӀи:",
+       "userlogin-yourname": "Доакъашхочунна цӀи",
+       "userlogin-yourname-ph": "Чуйоалае доакъашхочун цӀи",
+       "createacct-another-username-ph": "Чуйоалае доакъашхочун цӀи",
        "yourpassword": "КъайладIоагӀа:",
        "yourpasswordagain": "КъайладIоагӀа юха Ӏоязаде:",
        "remembermypassword": "(укх $1 {{PLURAL:$1|1=ден|деношкахь}}) мара са чувалара/чуялара дагалоаца дезаш дац",
        "notloggedin": "Оаш шоай цӀи хьааьннадац",
        "nologin": "Леламе дIаяздар дац? '''$1'''.",
        "nologinlink": "Леламе дIаяздар кхолла",
-       "createaccount": "Ð\9aеÑ\80да Ð´Ð°ÐºÑ\8aалаÑ\8cÑ\86аÑ\80Ñ\85о кхолла",
+       "createaccount": "УÑ\87Ñ\91Ñ\82а Ñ\8fздаÑ\80 кхолла",
        "gotaccount": "Укхаза дӀаязабенна дий шо? '''$1'''.",
        "gotaccountlink": "Чувала/яла",
        "userlogin-resetlink": "Чувала/яла цӀии дIоагӀаи дийцаденнадий?",
        "emailconfirmlink": "Доаржален хоамни хьожадорг дIачIоагIаде",
        "loginlanguagelabel": "Мотт: $1",
        "pt-login": "Чувала/яла",
-       "pt-createaccount": "Ð\94акÑ\8aалаÑ\8cÑ\86аÑ\80Ñ\85о кхолла",
+       "pt-createaccount": "УÑ\87Ñ\91Ñ\82а Ñ\8fздаÑ\80 кхолла",
        "changepassword": "КъайладIоaгIа дIахувцар",
        "oldpassword": "Къаьна къайладIоагӀа:",
        "newpassword": "Керда къайладIоагӀа:",
        "italic_sample": "Кулга яздам",
        "italic_tip": "Кулга яздам",
        "link_sample": "Ӏинка кортале",
-       "link_tip": "ЧураӀинк",
+       "link_tip": "Чура хьожаярг",
        "extlink_sample": "Ӏинка кортале http://www.example.com",
        "extlink_tip": "Арен Ӏинка (http:// тамагӀах дийца ма ле)",
        "headline_sample": "Кортален яздам",
        "nowiki_sample": "Укхаза кийчаде дезаш доаца яздам оттаде",
        "nowiki_tip": "Масса-бустамлорг теркамза дита",
        "image_tip": "Чуяьккха паьла",
-       "media_tip": "Ð\9fаÑ\8cла Ó\80инк",
+       "media_tip": "Файлан Ñ\82IаÑ\85Ñ\8cожаваÑ\80",
        "sig_tip": "Шун кулгаяздар а, хӀанзара ха а",
        "hr_tip": "Мухала мугӀ (могаш тайпара к|еззига хайраде)",
        "summary": "Хувцамий белгалдер",
        "loginreqpagetext": "Кхыйола оагӀувнашка хьожаргдолаш, оаш $1 де деза.",
        "accmailtitle": "КъайладIоагӀа дӀадахьийтад",
        "newarticle": "(Kерда)",
-       "newarticletext": "Шо йоаца оагӀув тӀа Ӏинкаца дехьадаьннад.\nИз хьае, кӀалхагӀа доала корачу яздам очуязаде (кхета хала дале [$1 новкъостала оагӀув тӀа] бӀаргтасса).\nЦаховш укхаза нийсадена дале, юхавала/яла яха тоӀобама тӀа пӀелга тоӀобе.",
+       "newarticletext": "Шо хьожаяргаца дехьадаьннад йоаца оагӀув тӀа.\nИз кхолларгьйолаш кӀалхагӀа доала корачу текст Iочуязаде (нагахьа кхетаде хала дале [$1 новкъосталан оагӀувага] хьажа).\nЦа ховш укхаза нийсденнадале, шоай браузера кнопка '''Юха''' тӀа пӀелга тоӀабе.",
        "noarticletext": "ХIанз укх оагӀув тӀа яздам доацаш да.\n[[Special:Search/{{PAGENAME}}|цу тайпара цӀи дувцам кораде]] кхыдола йоазувашках йийша я шун, вешта\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} тара дола таптарий йоазув карае], е\n'''[{{fullurl:{{FULLPAGENAME}}|action=edit}} изза мо цӀи йолаш оагӀув ела]'''</span>.",
        "noarticletext-nopermission": "ХIанз укх оагӀув тӀа яздам дац.\nШун йиш я, кхыдола йоазувнашках [[Special:Search/{{PAGENAME}}|дола цӀерий хаттам корае]] е <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} нийсамий тептара йоазувнаш корае].</span>",
        "note": "'''ХӀамоалар:'''",
        "previewnote": "'''Хьалхе б|аргтассам мара бац.'''\nЯздам кхы яздаь дац!",
-       "editing": "Ð\93Ó\80алаÑ\82нийÑ\81даÑ\80: $1",
-       "editingsection": "Ð\93IалаÑ\82нийÑ\81даÑ\80 $1 (оагÓ\80Ñ\83вдакъа)",
+       "editing": "Ð¥Ñ\83вÑ\86ам: $1",
+       "editingsection": "Ð¥Ñ\83вÑ\86ам: $1 (оагÓ\80Ñ\83ва Ð´Ã¡къа)",
        "editingcomment": "ГӀалатнийсдар $1 (керда декъам)",
        "editconflict": "ГӀалатнийсдара къовсам: $1",
        "yourtext": "Хьа яздам",
        "hiddencategories": "Ер оагӀув укх {{PLURAL:$1|1=къайла цатегаца|къайла цатегашца}} дакъа лоаца:",
        "permissionserrorstext-withaction": "$2 де бокъо яц {{PLURAL:$1|1=из бахьан долаш|из бахьанаш долаш}}:",
        "recreate-moveddeleted-warn": "'''Зем бе! Шо хьалххе дIайоаккхаш хинна оагӀув хьае гӀерта.'''\n\nХьажа, бокъонцахь езаш йолга.\nКӀалхагIа укх оагӀуви дӀадаккхами цӀи хувцами тептараш хьекха да.",
-       "moveddeleted-notice": "Ер оагӀув дӀаяьккха хиннай.\nНовкъостала, кӀалха дӀадаккхама а хувцама а тептарашкера нийсама йоазувнаш хьахьекха я.",
+       "moveddeleted-notice": "Ер оагӀув дӀаяккха хиннай.\nНовкъостала, кӀалха хьахьекха да дӀадаккхама а хувцама а тептарашкара яздараш.",
        "log-fulllog": "Деррига таптара бӀаргтасса",
        "edit-conflict": "Хувцамий къовсам.",
        "post-expand-template-inclusion-warning": "Зембаккхам: жамIан чIабалаш чулоаца дустам геттара доккха да.\nЦхьадола чIабалаш чулоацалургдац.",
        "post-expand-template-argument-warning": "Зем бе! Ер оагӀув цаӀ куцкепа |аьлдош мара чулоацац, юхадастара сел доккха дустам йолаш.\nЦу тайпара |аьлдешаш ӀокӀаладаькха да.",
        "post-expand-template-argument-category": "Куцкепий теркамза |аьлдешаш чулоаца оагӀувнаш",
        "viewpagelogs": "Укх оагӀува тептараш хьокха",
-       "currentrev-asof": "$1 тӀа эггара тӀехьара доржам",
+       "currentrev-asof": "тӀеххьара верси $1",
        "revisionasof": "$1 доржам",
        "revision-info": "$1; $2 хувцам",
        "previousrevision": "← Xьалхйоаг|араш",
        "nextrevision": "ТIехьайоагIараш →",
-       "currentrevisionlink": "Ð\94ола Ð´Ð¾Ñ\80жам",
+       "currentrevisionlink": "Ð¥IанзаÑ\80а Ð²ÐµÑ\80Ñ\81и",
        "cur": "хӀанз.",
        "next": "тӀехь.",
        "last": "хьалх.",
        "history-feed-title": "Хувцамий истори",
        "history-feed-description": "Укх оагӀуви вики тӀа хувцамий истори",
        "history-feed-item-nocomment": "$1гӀара $2гӀачу",
-       "rev-delundel": "хьахьокха/къайлаяьккха",
+       "rev-delundel": "хьахьокха/къайлаяккха",
        "rev-showdeleted": "хьахьокха",
        "revdelete-show-file-submit": "XӀаа",
        "revdelete-radio-set": "Къайла",
        "mergehistory-empty": "ВIашагIатохара хувцамаш кораяь яц.",
        "mergehistory-reason": "Бахьан:",
        "revertmerge": "Декъа",
-       "history-title": "\"$1\" â\80\94 Ñ\85Ñ\83вÑ\86амий истори",
+       "history-title": "\"$1\" â\80\94 Ñ\85Ñ\83вÑ\86амай истори",
        "lineno": "МугI $1:",
        "compareselectedversions": "Хьаржа доржамаша тарона тIа хьажа",
        "editundo": "юхавала/яла",
        "nextn": "{{PLURAL:$1|тlехьайоагlар $1|тlехьайоагlараш $1|тlехьайоагlараш $1}}",
        "prevn-title": "{{PLURAL:$1|1=$1 хьалхара йоазув|$1 хьалхара йоазувнаш}}",
        "nextn-title": "{{PLURAL:$1|1=$1 тIехьара йоазув|$1 тIехьара йоазувнаш}}",
-       "shown-title": "УкÑ\85 Ð¾Ð°Ð³IÑ\83вни $1 {{PLURAL:$1|1=йоазÑ\83в|йоазÑ\83внаÑ\88}} Ñ\85Ñ\8cаÑ\85Ñ\8cокÑ\85а",
+       "shown-title": "Ð¥Ñ\8cóкÑ\85а $1 {{PLURAL:$1|даÑ\8c Ð¹Ð¾Ð°Ð·Ð¾|даÑ\8c Ð¹Ð¾Ð°Ð·Ð¾Ð½Ð°Ñ\88}} Ñ\83кÑ\85 Ð¾Ã¡Ð³IÑ\83вна Ñ\82Iа",
        "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) хьажа",
        "searchmenu-exists": "'''Укх масса-хьахьоадайтамач ер оаг|ув \"[[:$1]]\" я'''",
        "searchmenu-new": "'''Укх \"[[:$1]]\" масса-хьахоадайтамач оагIув хьае!'''",
        "searchprofile-images-tooltip": "Паьлий лахар",
        "searchprofile-everything-tooltip": "Массадола оагIувний лахар (дувцама оагIувнаш чулоацаш)",
        "searchprofile-advanced-tooltip": "Iочуязаяь цIераренашках лаха",
-       "search-result-size": " $1 ({{PLURAL:$2|1=1 дош|$2 дешаш}})",
+       "search-result-size": "$1 ({{PLURAL:$2|$2 дош|$2 дешаш}})",
        "search-result-category-size": "{{PLURAL:$1|1=$1 дакъа|$1 дакъаш}} ({{PLURAL:$2|1=$2 кIалцатег|$2 кIалцатегаш}}, {{PLURAL:$3|1=$3 паьла|$3 паьлий}})",
        "search-redirect": "($1 дехьачуяьккхар)",
        "search-section": " (дакъа $1)",
-       "search-suggest": "Iа лохар из хила мега: $1",
+       "search-suggest": "Хьона эшар ер хила мега: $1",
        "search-interwiki-caption": "Гаргалон хьахьоадайтамаш",
        "search-interwiki-default": "$1 хьахиннараш:",
        "search-interwiki-more": "(кха)",
        "action-read": "Укх оагIуви дешам",
        "action-edit": "Ер оагIув хувца",
        "nchanges": "$1 {{PLURAL:$1|1=хувцам|хувцамаш}}",
+       "enhancedrc-history": "истори",
        "recentchanges": "Керда хувцамаш",
        "recentchanges-legend": "Керда хувцамий оттамаш",
        "recentchanges-summary": "КIалхагIа лоарамий доаламе тIехьара оагIувний хувцамаш дIаязадаь да {{grammar:genitive|{{SITENAME}}}}.",
        "recentchanges-feed-description": "Укх ларамца тIехьара массахувцамашт теркам бе.",
-       "recentchanges-label-newpage": "Укх хувцамаца керда оагIув даь хиннад",
+       "recentchanges-label-newpage": "Укх хувцамаца керда оагIув яь хиннай",
        "recentchanges-label-minor": "ЗIамига хувцам я",
        "recentchanges-label-bot": "Ер хувцам бIатаца яь е",
        "recentchanges-label-unpatrolled": "Ер хувцам ший моттиге кхы дIадехьаяьккхаяц.",
        "rcnotefrom": "КIалхагIа хувцамаш хьахьекха я <strong>$2</strong> денза (<strong>$1</strong> кхачалца).",
        "rclistfrom": "$3 $2 тIара хувцамаш хьахьокха",
        "rcshowhideminor": "$1 зIамига хувцамаш",
+       "rcshowhideminor-hide": "Къайлдаккха",
        "rcshowhidebots": "$1 боташ",
+       "rcshowhidebots-show": "Хьахьокха",
        "rcshowhideliu": "Чубаьнначара дакъалаьцархочий $1",
+       "rcshowhideliu-hide": "Къайлдаккха",
        "rcshowhideanons": "$1 цIияьккханза дакъалаьцархой",
+       "rcshowhideanons-show": "Хьахьокха",
+       "rcshowhideanons-hide": "Къайлдаккха",
        "rcshowhidepatr": "$1 теркам даь хувцамаш",
        "rcshowhidemine": "$1 сай хувцамаш",
+       "rcshowhidemine-hide": "Къайлдаккха",
        "rclinks": "$2 динах<br />$3 $1 хинна тIехьара хувцамаш хьахьокха",
        "diff": "кхы.",
        "hist": "истори",
        "newpageletter": "Н",
        "boteditletter": "б",
        "rc_categories_any": "МоллагIа а",
+       "rc-change-size-new": "Хувцам баьнначул тӀехьагIа бола боарам: $1 {{PLURAL:$1|байт}}",
        "rc-enhanced-expand": "Ма дарра чулоацамаш хьахьокха (JavaScriptаца)",
        "rc-enhanced-hide": "Ма дарра чулоацамаш къайладаккха",
        "recentchangeslinked": "Гаргалон хувцамаш",
        "recentchangeslinked-summary": "Ер, Iинк яь йола оагIув (е укх цатегачу чуйоагIараш), дукха ха йоацаш хьийца оагIувнашкий дагарле я.\n[[Special:Watchlist|Шун теркама дагарленашках]] чуйоагIа оагIувнаш '''белгалаяь я'''.",
        "recentchangeslinked-page": "ОагIува цIи",
        "recentchangeslinked-to": "ОагIувнаш тIа хувцамаш хьахьокха, хьахьекха йола оагIув тIа Iинкаш еш йола.",
-       "upload": "Ð\9fаÑ\8cл Ñ\87Ñ\83Ñ\8fÑ\8cккха",
+       "upload": "Файл Ñ\87Ñ\83даккха",
        "uploadbtn": "Паьл чуяьккха",
        "uploadlogpage": "Чуяьккхамий тептар",
        "filedesc": "Лоаца лоацам",
        "fileuploadsummary": "Лоаца лоацам:",
        "license": "ЦIийяздар",
        "license-header": "ЦIийяздар",
-       "imgfile": "паьл",
+       "imgfile": "файл",
        "listfiles": "Паьлий дагарче",
        "listfiles_date": "Денха",
        "listfiles_name": "Паьла цIи",
        "listfiles_size": "Дустам",
        "listfiles_description": "Лоацам",
        "listfiles_count": "Доржамаш",
-       "file-anchor-link": "Ð\9fаÑ\8cл",
+       "file-anchor-link": "Файл",
        "filehist": "Паьла истори",
        "filehist-help": "Хьалхе паьла мишта хиннай хьожаpгволаш/йолаш, дентаьрах/сахьата тIа пIелга тIообе.",
        "filehist-revert": "юхаяьккха",
        "filehist-filesize": "Паьла юстарал",
        "filehist-comment": "ХIамоалар",
        "imagelinks": "Паьлий пайда эца",
-       "linkstoimage": "{{PLURAL:$1|1=ТIехьайоагIа $1 оагIув Iинк ду|ТIехьайоагIа $1 оагIувнаш Iинкаш ду}} укх паьла тIа:",
+       "linkstoimage": "{{PLURAL:$1|1=ТIехьайоагIача $1 оагIуво тIахьожаву|ТIехьайоагIача $1 оагIувнаша тIахьожаву}} укх файла тIа:",
        "nolinkstoimage": "Йола паьла тIа  Iинк ю оагIувнаш дац",
        "sharedupload": "Ер паьла $1чера я, кхыча хьахьоадайтамча хьахайраде йийшайолаш я.",
        "sharedupload-desc-here": "Ер паьл $1чара я, кхыдола хьахьоадайтамача хайрамбе йийш йолаш да.\nЦун [$2 лоацама оагIувца] лоаца маIандар кIалхагIа латта.",
        "filedelete-reason-otherlist": "Кхыдола бахьан",
        "download": "хьачуяьккха",
        "unwatchedpages": "Теркамза оагIувнаш",
-       "randompage": "Ð\94агадоаÑ\86а йоазув",
+       "randompage": "Ца Ñ\85овÑ\88 Ð½Ð¸Ð¹Ñ\81Ñ\8aенна йоазув",
        "statistics": "Дагара куц",
        "statistics-pages": "ОагIувнаш",
        "brokenredirects-edit": "хувца",
        "brokenredirects-delete": "дIадаккха",
        "withoutinterwiki-submit": "Хьахьокха",
-       "nbytes": "$1 {{PLURAL:$1|1=бIат|бIаташ}}",
+       "nbytes": "$1 {{PLURAL:$1|байт}}",
        "nmembers": "$1 {{PLURAL:$1|1=дакъалаьцархо|дакъалаьцархой}}",
        "prefixindex": "ОагIувнаший хьалхера цIи хьагойтар",
        "shortpages": "Лоаца оагIувнаш",
        "movethispage": "Укх оагIува цIи хувца",
        "pager-newer-n": "{{PLURAL:$1|кердагIа дара|кердагIа дараш|кердагIа долачаьрахь}} $1",
        "pager-older-n": "{{PLURAL:$1|къаьнара дара|къаьнара дараш|къаьнара долaчаьрахь}} $1",
-       "booksources": "Китабий гIувам",
-       "booksources-search-legend": "Китаба лоаца маIандара тохкам",
+       "booksources": "Джейнай хьасташ (источники)",
+       "booksources-search-legend": "Джейнах лаьца хоам лахар",
+       "booksources-search": "Хьалáха",
        "log": "Тептараш",
        "allpages": "Еррига оагIувнаш",
        "prevpage": "($1) хьалхара оагIув",
        "allpagesto": "Укх оагIувнаш тIа бIарга дита:",
        "allarticles": "Еррига оагIувнаш",
        "allpagessubmit": "Кхоачашде",
-       "categories": "ЦаÑ\82егаш",
+       "categories": "Ð\9aаÑ\82егоÑ\80еш",
        "linksearch": "Т|ера|инкаш лахар",
-       "linksearch-ok": "Ð\9bаха",
+       "linksearch-ok": "Ð¥Ñ\8cалáха",
        "linksearch-line": "$1 тIа Iинк $2 юкъера",
        "listgrouprights-members": "(тоабий дагарче)",
        "emailuser": "Дакъалаьцархочоа д-хоамни:",
        "watchlistfor2": "$1 $2 царна",
        "addedwatchtext": "\"[[:$1]]\" оагIув, шун [[Special:Watchlist|теркама дагаршкахь]] чуяккха я. \nТехьара мел йола укх оагIувни хувцамаш цу дагаршкахь хоам беш хургья. Вешта [[Special:RecentChanges|керда хувцама дагаршкаехь]] сома къоалмаца хьакъоастлуш хургья.",
        "removedwatchtext": "\"[[:$1]]\" оагIув, шун [[Special:Watchlist|теркама дарагчера]] дIаяккха хиннай.",
-       "watch": "ТоÑ\85кам Ð±е",
+       "watch": "Ð\97е",
        "watchthispage": "Укх оагIува теркам бе",
        "unwatch": "Лора ма де",
        "watchlist-details": "Шун теркама дагарченгахь йола  $1 {{PLURAL:$1|1=оагIув|оагIувнаш}}, дувцама оагIувнаш ца лоархIаш.",
        "actioncomplete": "ДулархIам баьб",
        "actionfailed": "Оттам даьдац",
        "deletedtext": "\"$1\" дIаяьккха хиннай.\nТIехьара дIадаьккха дагарчена хьожаргволаш/хьожаргьйолаш, $2 хьажа.",
-       "dellogpage": "ДIадаккхара тептар",
+       "dellogpage": "ДIадаккхарай тептар",
        "deletecomment": "Бахьан:",
        "deleteotherreason": "Кхыдола бахьан/тIатохар:",
        "deletereasonotherlist": "Кхыдола бахьан",
        "rollbacklink": "юхаяьккха",
-       "protectlogpage": "Ð\9bоÑ\80ама тептар",
+       "protectlogpage": "Ð\9bоÑ\80адаÑ\80а тептар",
        "protectedarticle": "\"[[$1]]\" оагIув лорам деж я",
        "modifiedarticleprotection": "\"[[$1]]\" оагIувни лорама лагIа хувцаяьннай",
        "protectcomment": "Бахьан:",
        "restriction-upload": "Чудаккхар",
        "undeletelink": "БIаргтасса/юхаметтаоттаде",
        "undeleteviewlink": "бIаргтасса",
+       "undelete-search-submit": "Хьалáха",
        "namespace": "ЦIерий аренаш",
        "invert": "Хьаржар юхадаккха",
-       "blanknamespace": "(Ð\9aоÑ\80Ñ\82а)",
-       "contributions": "{{GENDER:$1|Ð\94акÑ\8aалаÑ\8cÑ\86аÑ\80хочунна}} къахьегам",
+       "blanknamespace": "(Ð\9aеÑ\80Ñ\82еÑ\80а)",
+       "contributions": "{{GENDER:$1|Ð\94оакÑ\8aаÑ\88хочунна}} къахьегам",
        "contributions-title": "$1 дакъалаьцархочунна къахьегам",
        "mycontris": "Са къахьегам",
        "contribsub2": "{{GENDER:$3|$1}} ($2) баь болх",
        "uctop": "(xIанзара)",
-       "month": "Цхьа бутт хьалхагIа (кхы хьалхагIа)",
-       "year": "Цхьа шу хьалхагIа (кхы хьалхагIа):",
+       "month": "Цхьан бетт (кхы хьалхагIа)",
+       "year": "Цхьан шера (кхы хьалхагIа):",
        "sp-contributions-newbies": "Керда даязья йоазоначера мара баь бола къахьегам ма хьокха",
        "sp-contributions-blocklog": "чIегаш",
        "sp-contributions-uploads": "чуяьккхамаш",
        "sp-contributions-search": "Къахьегама лахар",
        "sp-contributions-username": "IP-моттиг е цIи:",
        "sp-contributions-toponly": "ТIехьара доржамаш лоархаш дола хувцамаш мара ма хьокха",
-       "sp-contributions-submit": "Хьалаха",
-       "whatlinkshere": "Iинкаш укхаза",
+       "sp-contributions-submit": "Хьалáха",
+       "whatlinkshere": "Хьожаяргаш укхаза",
        "whatlinkshere-title": "\"$1\" тIа Iинкаш еш йола оагIувнаш",
        "whatlinkshere-page": "ОагIув",
-       "linkshere": "ТIехьара оагIувнаш '''[[:$1]]''' тIа Iинкаш ю:",
+       "linkshere": "ТIехьайоагIа оагIувнаш тIахьожаву «'''[[:$1]]'''»:",
        "nolinkshere": "'''[[:$1]]''' оагIув тIа, кхыдола оагIувашкара Iинкаш йоацаш я",
-       "isredirect": "дIа-Ñ\85Ñ\8cа оагIув",
-       "istemplate": "Ñ\87Ñ\83даккÑ\85ар",
-       "isimage": "паÑ\8cла Iинк",
+       "isredirect": "ТIаÑ\85Ñ\8cожадаÑ\80ан оагIув",
+       "istemplate": "Ñ\8eкÑ\8aейоалаÑ\8fр",
+       "isimage": "Файлан Ñ\85Ñ\8cожаÑ\8fÑ\80г",
        "whatlinkshere-prev": "{{PLURAL:$1|1=хьалхайоагIа|хьалхайоагIараш}} $1",
        "whatlinkshere-next": "{{PLURAL:$1|1=тIехьайоагIа|тIехьайоагIараш}} $1",
-       "whatlinkshere-links": "← Iинкаш",
+       "whatlinkshere-links": "← хьожаяргаш",
        "whatlinkshere-hideredirs": "$1 дIа-хьа чуяьккхамаш",
        "whatlinkshere-hidetrans": "$1 чуяьккхамаш",
        "whatlinkshere-hidelinks": "$1 Iинкаш",
        "blockip": "Укх {{GENDER:$1|доакъошхочоа}} ч|ега бола",
        "ipboptions": "2 сахьат:2 hours,1 ди:1 day,3 ди:3 days,1 кIира:1 week,2 кIира:2 weeks,1 бутт:1 month,3 бутт:3 months,6 бутт:6 months,1 шу:1 year,сиха ца луш:infinite",
        "ipblocklist": "ЧIега бела дакъалаьцархой",
+       "ipblocklist-submit": "Хьалáха",
        "blocklink": "чIегa тоха",
        "unblocklink": "чIега баста",
        "change-blocklink": "ЧIегатохар хувца",
        "tooltip-pt-preferences": "Шун оттамаш",
        "tooltip-pt-watchlist": "ОоагIувна дагарле, шо бIаргалокхаш йола",
        "tooltip-pt-mycontris": "Шун хувцамаш",
-       "tooltip-pt-login": "Укхаза хьай цIи аьле чувала/яла йиша я, амма чуцаваьлача/ялача хIама а дац",
+       "tooltip-pt-login": "Укхаза хьай цIи аьле чувала/яла йиша я, амма из параз дац",
        "tooltip-pt-logout": "Аравала/яла",
-       "tooltip-ca-talk": "ОагIувна чулоацаме дувцам",
-       "tooltip-ca-edit": "Хувца ер оагIув",
+       "tooltip-pt-createaccount": "Хьа бокъо я учёта яздар кхелла система чу вала, амма параз долаш дац из.",
+       "tooltip-ca-talk": "ОагIувна чулоацам дувца оттадар",
+       "tooltip-ca-edit": "Нийсъе ер оагIув",
        "tooltip-ca-addsection": "Керда декъам хьаде",
        "tooltip-ca-viewsource": "Ер оагIув хувцамах лораяь я, амма шун цунна гIувамага хьажа бокъо я.",
-       "tooltip-ca-history": "УкÑ\85 Ð¾Ð°Ð³IÑ\83вни Ñ\85Ñ\83вÑ\86ама Ñ\82аптар",
+       "tooltip-ca-history": "УкÑ\85 Ð¾Ð°Ð³IÑ\83ван Ð´Ð°Ñ\8c Ñ\85Ñ\83вÑ\86амаÑ\88 Ñ\82Iа Ð´Ð¾Ð»Ð° Ñ\82ептар",
        "tooltip-ca-protect": "Eр оагIув лорае",
        "tooltip-ca-delete": "Ер оагIув дIаяькха",
        "tooltip-ca-move": "Укх оагIува цIи хувца",
        "tooltip-ca-watch": "Ер оагIув теркам беча каьхата тIа тIаяьккха",
        "tooltip-ca-unwatch": "Ер оагIув теркам беча каьхата тIара дIаяькха",
-       "tooltip-search": "ЦÑ\83 Ñ\82айпаÑ\80а Ð´Ð¾Ñ\88 Ð»Ð°Ñ\85а {{SITENAME}}",
+       "tooltip-search": "Ð¥Ñ\8cалáÑ\85а {{grammar:prepositional|{{SITENAME}}}} Ñ\87Ñ\83",
        "tooltip-search-go": "Изза мо цӀи йолаш оагӀув тӀa дехьавала",
-       "tooltip-search-fulltext": "Изза мо яздам долаш оагӀувнаш лаха",
+       "tooltip-search-fulltext": "Изза мо яздар долаш оагӀувнаш лаха",
        "tooltip-p-logo": "Кертера оагIув тIа дехьавала",
        "tooltip-n-mainpage": "Кертера оагIув тIа дехьавала",
        "tooltip-n-mainpage-description": "Кертера оагIув тIа дехьавала",
-       "tooltip-n-portal": "Ð¥Ñ\8cаÑ\85Ñ\8cоадайÑ\82амаÑ\85Ñ\8c Ð»Ð°Ñ\8cÑ\86а, Ñ\85Ñ\8cа Ð´Ðµ Ð¹Ð¸Ñ\88даÑ\80, Ñ\84Ñ\83 Ð° Ð¼Ð¸Ñ\87Ñ\87а Ð° Ð¹Ð¾Ð°Ð»а",
+       "tooltip-n-portal": "Ð\93IалгIай Ð\92икипедиеÑ\85 Ð»Ð°Ñ\8cÑ\86а Ð´Ð°Ñ\80 Ð°, Ñ\83кÑ\85аза Ð´Ðµ Ð¼ÐµÐ³Ð°Ñ\88 Ð´Ð°Ñ\80 Ð°, Ð¼Ð°Ð»Ð°Ð³Iа Ñ\84Ñ\83д Ð°, Ð¼Ð¸Ñ\87а Ð´Ð° а",
        "tooltip-n-currentevents": "ХIанзара хоаман дагарле",
-       "tooltip-n-recentchanges": "ТÓ\80еÑ\85Ñ\8cаÑ\80а Ñ\85Ñ\83вÑ\86амий Ð´Ð°Ð³Ð°Ñ\80Ñ\87е",
-       "tooltip-n-randompage": "Ð\91е Ð¹Ð¾Ð°Ñ\86а Ð¾Ð°Ð³Ó\80Ñ\83в ела",
-       "tooltip-n-help": "Новкъостала моттиг",
-       "tooltip-t-whatlinkshere": "Ð\9cаÑ\81Ñ\81айола Ð¾Ð°Ð³IÑ\83вий Ð´Ð°Ð³Ð°Ñ\80ле, Ñ\83кÑ\85 Ð¾Ð°Ð³IÑ\83в Ñ\82Iа IинкаÑ\88 Ð»Ñ\83Ñ\88 Ð¹Ð¾Ð»Ð°",
+       "tooltip-n-recentchanges": "ТÓ\80еÑ\85Ñ\85Ñ\8cаÑ\80а Ñ\85Ñ\83вÑ\86амай Ñ\81пиÑ\81ок",
+       "tooltip-n-randompage": "Ð\91аÑ\88Ñ\85ало Ð¹Ð¾Ð°Ñ\86а Ñ\86а Ñ\85овÑ\88 Ð½Ð¸Ð¹Ñ\81Ñ\8aенна Ð¾Ð°Ð³Ó\80Ñ\83в Ñ\85Ñ\8cаела",
+       "tooltip-n-help": "Новкъостал лаха мегаш йола моттиг",
+       "tooltip-t-whatlinkshere": "УкÑ\85аза Ñ\82IаÑ\85Ñ\8cожавеÑ\88 Ð¹Ð¾Ð»Ð° Ð¾Ð°Ð³IÑ\83вай Ñ\81пиÑ\81ок",
        "tooltip-t-recentchangeslinked": "ОагIувнаш тIа тIехьара хувцамаш, укх оагIувнера Iинк яь йола",
        "tooltip-feed-rss": "Укх оагIувна RSSчу гойтар",
        "tooltip-feed-atom": "Укх оаг|увна Atomчу гойтар",
-       "tooltip-t-contributions": "Укх дакъалаьцархочу хьийца йола оагIувнаш хьахьокха",
+       "tooltip-t-contributions": "{{GENDER:$1|Укх доакъашхочо хийца}} йола оагIувнаш",
        "tooltip-t-emailuser": "Укх дакъалаьцархочоа зIы яхьийта",
-       "tooltip-t-upload": "Ð\9fаÑ\8cлаÑ\88 Ñ\87Ñ\83Ñ\8fÑ\8cккха",
-       "tooltip-t-specialpages": "Ð\93\83лакÑ\85а Ð¾Ð°Ð³IÑ\83вний Ð´Ð°Ð³Ð°Ñ\80Ñ\87e",
-       "tooltip-t-print": "УкÑ\85 Ð¾Ð°Ñ\83гIÑ\83вна ÐºÐ°Ñ\8cÑ\85аÑ\82заÑ\80бане Ð´Ð¾Ñ\80жам",
+       "tooltip-t-upload": "ФайлаÑ\88 Ñ\87Ñ\83даккха",
+       "tooltip-t-specialpages": "Ð\93\83лакÑ\85а Ð¾Ð°Ð³IÑ\83внаÑ\88",
+       "tooltip-t-print": "УкÑ\85 Ð¾Ð°Ñ\83гIÑ\83вна Ð·Ð°Ñ\80ба Ñ\82оÑ\85аÑ\80а Ð²ÐµÑ\80Ñ\81и",
        "tooltip-t-permalink": "Укх оагIув доржама даим латта Iинк",
        "tooltip-ca-nstab-main": "Йоазува чулоацам",
        "tooltip-ca-nstab-user": "Дакъалаьцархочунна ший оагIув",
-       "tooltip-ca-nstab-special": "Ер гIулакха оагIув я, из хувца хьо бокъо йолаш вац/яц.",
-       "tooltip-ca-nstab-project": "Ð¥Ñ\8cаÑ\85Ñ\8cоадайÑ\82ама оагIув",
+       "tooltip-ca-nstab-special": "Ер гIулакха оагIув я, из хувца бокъо яц",
+       "tooltip-ca-nstab-project": "Ð\9fÑ\80оекÑ\82ан оагIув",
        "tooltip-ca-nstab-image": "Паьла оагIув",
-       "tooltip-ca-nstab-template": "ЧIабала оагIув",
+       "tooltip-ca-nstab-template": "Кепан оагIув",
+       "tooltip-ca-nstab-help": "ГӀон оагIув",
        "tooltip-ca-nstab-category": "Цатега оагIув",
        "tooltip-minoredit": "Ер хувцар башха доаца санна белгалде",
        "tooltip-save": "Хувцамаш кходе",
        "tooltip-compareselectedversions": "Укх оагIувни шин доржамаш тIа юкъера хувцамаш зе.",
        "tooltip-watch": "Ер оагIув теркам беча каьхата тIа яькха",
        "tooltip-rollback": "ГIалaтнийсадаро тIехьара яь йола хувцамаш, пIелг тоIобе дIаяьккха.",
-       "tooltip-undo": "Ð\91аÑ\8c Ñ\85Ñ\83вÑ\86ам Ð´IабаÑ\8cккÑ\85e, Ð±IаÑ\80гаÑ\82аÑ\81Ñ\81ам Ñ\85Ñ\8cаÑ\85Ñ\8cокÑ\85а, ÐºÐ°Ñ\80а Ð´Ð°Ð»Ðµ, Ð´IаÑ\8fÑ\8cккÑ\85а Ð±Ð°Ñ\85Ñ\8cан IоÑ\87Ñ\83Ñ\8fзаде Ð¼Ð¾Ñ\82Ñ\82игаÑ\86а.",
+       "tooltip-undo": "Ð\94аÑ\8c Ñ\85Ñ\83вÑ\86аÑ\80 Ð´IадаÑ\8cккÑ\85а, Ñ\85Ñ\8cалÑ\85Ñ\85е Ñ\85Ñ\8cажаÑ\80 Ñ\85Ñ\8cаÑ\85Ñ\8cокÑ\85а, Ð´IадаккÑ\85аÑ\80а Ð±Ð°Ñ\85Ñ\8cан IоÑ\87Ñ\83Ñ\8fзаде Ð°Ñ\8cÑ\82Ñ\82Ñ\83в Ð±Ð¾Ð»Ð°Ñ\88.",
        "tooltip-summary": "Лоаца чулоацам Iочуязаде",
-       "previousdiff": "← Хьалхара хувцам",
-       "nextdiff": "ТIайоагIа хувцам",
+       "pageinfo-toolboxlink": "ОагIонах бола хоам",
+       "previousdiff": "← Хьалхара нийсдар",
+       "nextdiff": "ТIайоагIа нийсъар",
        "file-info-size": "$1 × $2 фихсам, паьла дустам: $3, MIME-тайп: $4",
-       "file-nohires": "Укхал доккхагIа доржам дац",
-       "svg-long-desc": "SVG-паьл, $1 × $2 фихелашца, паьла дустам: $3",
+       "file-nohires": "Укхал дуккхагIа доккхал долаш верси яц",
+       "svg-long-desc": "SVG-файл, номинально $1 × $2 {{PLURAL:$2|пиксель}}, файлан боарам: $3",
        "show-big-image": "ХьалхагIара сурт",
+       "show-big-image-size": "$1 × $2 пиксель",
        "noimages": "Суртaш бIаргагуш дац.",
-       "ilsubmit": "Ð\9bаха",
+       "ilsubmit": "Ð¥Ñ\8cалáха",
        "bad_image_list": "Бустам цу тайпара хила беза:\n\nДагарлен хьаракъаш мара лоарх|аш хургьяц (укх тамагIалгацa * дувлашду мугIараш).\nМугIарен хьалхара Iинк, сурт Iоттае пурам доаца Iинка, хила еза. \nЦу мугIара тIехьайоагIа Iинкаш, арадаккхар мо лоарх|аш хургья, вешта аьлча, йоазувашка чуIоттаде мегаш дола сурт санна ларх|а мега.",
        "metadata": "МетахIамаш",
        "metadata-help": "Паьлас чулоаца, кхыдола хIамаш, таьрахьа суртдоакхаргца е тIагIолладоакхаргца чудакхаш дола. Хьаяь паьл, гIалатахь мукъадаькха хинна дале, хьахьокхаш дола сурт, деррига хIамаш чулоацаргдац.",
        "metadata-fields": "Укх дагарченгахь дагaрадаь метахIамаша суртий мугIаш, сурт оагIув тIа хьахьекха хургья, чуерзaяь метахIамашийца. Вож мугIанаш ха йоалаш къайла хургья.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "exif-imagewidth": "Шерал",
        "exif-imagelength": "Лакхал",
+       "exif-orientation": "Суртан белгало",
        "exif-imagedescription": "Сурта цIи",
        "exif-artist": "Яздархо",
        "exif-colorspace": "Басара аре",
        "exif-pixelydimension": "Сурта шерал",
        "exif-pixelxdimension": "Сурта лакхал",
+       "exif-datetimedigitized": "Оцифровк яь таьрахь а, ха а",
        "exif-writer": "Яздама да",
        "exif-languagecode": "Мотт",
        "exif-iimcategory": "Цатег",
        "version-version": "($1)",
        "version-software-version": "Доржам",
        "fileduplicatesearch-filename": "ПаьлацIи:",
-       "fileduplicatesearch-submit": "Ð\9bаха",
-       "specialpages": "Ð\93\83лакÑ\85ий оагIувнаш",
+       "fileduplicatesearch-submit": "Ð¥Ñ\8cалáха",
+       "specialpages": "Ð\9bаÑ\8cÑ\80Ñ\85Ñ\85Iа Ð¹Ð¾Ð»Ð° оагIувнаш",
        "specialpages-group-users": "Дакъалаьцархой, цара бокъо",
        "specialpages-group-pages": "ОагIувний дагарченаш",
        "specialpages-group-pagetools": "ОагIувнаша гIирсаш",
        "external_image_whitelist": "#Ер мугI ший долаш тайпара дита<pre>\n#Каст-каста оаламаш укхаза дIаязаде(юкъе дола дакъа //)\n#арара суртий URLца дIанийсалургда уш.\n#Пайдан дола, сурташ мо хьахьекха хургья, дахIодараш, сурта тIа Iинкаш мо хуpгья хьахьекха.\n#Укх # тамагIалгаца дIадувлаш дола мугIанаш, оалам мо лоархаш да.\n#МугIанаш яздaтакха каьда да\n\n#Каст-каста оаламаш укх мугIа лакхе дIаязаде. Из мугI ший долаш тайпара дита</pre>",
        "tag-filter": "[[Special:Tags|Йоазоний]] цIенаярг:",
        "tag-filter-submit": "ЦIенъе",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|1=Белгало|Белгалонаш}}]]: $2)",
        "tags-title": "Йоазонаш",
        "tags-tag": "Йоазон цIи",
        "tags-hitcount-header": "Белгалаяь хувцамаш",
        "htmlform-submit": "ДIадахьийта",
        "htmlform-reset": "Хувцамаш юхадаккха",
        "htmlform-selectorother-other": "Кхыдола",
+       "logentry-newusers-create": "{{GENDER:$2|Доакъашхочо кхеллай}} учёта яздар $1",
        "rightsnone": "(а)",
        "revdelete-summary": "хувцамий лоацам",
-       "searchsuggest-search": "Лаха",
+       "searchsuggest-search": "Лахар",
        "special-characters-group-latin": "Лаьтмий",
        "special-characters-group-greek": "Джелтий",
        "special-characters-group-cyrillic": "Цырилиций",
index 25786f6..9e0fd9f 100644 (file)
@@ -23,7 +23,8 @@
                        "Jonbg",
                        "Matma Rex",
                        "Xð",
-                       "Sveinki"
+                       "Sveinki",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Undirstrika tengla:",
        "filecopyerror": "Mistókst að afrita skjal \"$1\" á \"$2\".",
        "filerenameerror": "Gat ekki endurnefnt skrána „$1“ í „$2“.",
        "filedeleteerror": "Gat ekki eytt skránni „$1“.",
-       "directorycreateerror": "Gat ekki búið til efnisskrána \"$1\".",
+       "directorycreateerror": "Gat ekki búið til möppuna \"$1\".",
        "directoryreadonlyerror": "Mappan \"$1\" er skrifvarin.",
        "directorynotreadableerror": "Mappan \"$1\" er ekki lesanleg.",
        "filenotfound": "Gat ekki fundið skrána „$1“.",
        "title-invalid-empty": "Umbeðinn síðutitill er auður eða inniheldur aðeins heiti nafnrýmis.",
        "title-invalid-utf8": "Umbeðinn síðutitill inniheldur ógilda UTF-8 runu.",
        "title-invalid-characters": "Umbeðinn síðutitill inniheldur ógilda stafi: \"$1\".",
+       "title-invalid-magic-tilde": "Umbeðinn síðutitill inniheldur ógilda tildurunu (<nowiki>~~~</nowiki>).",
+       "title-invalid-too-long": "Umbeðinn síðutitill er of langur. Hann má ekki vera lengri en $1 {{PLURAL:$1|bæti}} í UTF-8 stafatöflu.",
        "title-invalid-leading-colon": "Umbeðinn síðutitill inniheldur ógildan tvípunkt í byrjun.",
        "perfcached": "Eftirfarandi er afrit af umbeðinni síðu og gæti því ekki verið nýjasta útgáfa hennar. Allt að $1 {{PLURAL:$1|niðurstaða er aðgengileg|niðurstöður eru aðgengilegar}} í skyndiminninu.",
        "perfcachedts": "Eftirfarandi gögn eru í skyndiminninu, og voru síðast uppfærð $1. Allt að $4 {{PLURAL:$4|niðurstaða er aðgengileg|niðurstöður eru aðgengilegar}} í skyndiminninu.",
        "virus-unknownscanner": "óþekktur veiruskanni:",
        "logouttext": "'''Þú hefur verið skráð(ur) út.'''\n\nAthugaðu að sumar síður kunna að birtast líkt og þú sért ennþá skráð(ur) inn, þangað til að þú hreinsar skyndiminnið í vafranum þínum.",
        "cannotlogoutnow-title": "Get ekki skráð út núna",
+       "cannotlogoutnow-text": "Útskráning er ekki möguleg þegar verið er að nota $1.",
        "welcomeuser": "Velkomin(n), $1!",
        "welcomecreation-msg": "Aðgangurinn þinn hefur verið búinn til.\nEkki gleyma að breyta [[Special:Preferences|{{SITENAME}} stillingunum]] þínum.",
        "yourname": "Notandanafn:",
        "userlogin-remembermypassword": "Muna innskráningu mína",
        "userlogin-signwithsecure": "Nota örugga tengingu",
        "cannotloginnow-title": "Get ekki skráð inn núna",
+       "cannotloginnow-text": "Innskráning er ekki möguleg þegar verið er að nota $1.",
        "yourdomainname": "Þitt lén:",
        "password-change-forbidden": "Þú getur ekki breytt lykilorðum á þessum wiki.",
        "externaldberror": "Uppfærsla mistókst. Annaðhvort varð villa í gagnasafninu eða að þér sé óheimilt að uppfæra aðra aðganga.",
        "createacct-benefit-body2": "{{PLURAL:$1|síða|síður}}",
        "createacct-benefit-body3": "{{PLURAL:$1|nýlegur stuðningsaðili|nýlegir stuðningsaðilar}}",
        "badretype": "Lykilorðin sem þú skrifaðir eru ekki eins.",
+       "usernameinprogress": "Nú þegar er í vinnslu gerð aðgangs fyrir þennan notanda.\nHinkraðu aðeins.",
        "userexists": "Þetta notandanafn er þegar í notkun.\nVeldu þér eitthvað annað.",
        "loginerror": "Innskráningarvilla",
        "createacct-error": "Stofnun aðgangs mistókst",
        "createaccounterror": "Gat ekki búið til notanda: $1",
-       "nocookiesnew": "Innskráningin var búin til, en þú ert ekki skráð(ur) inn.\n{{SITENAME}} notar vefkökur til að skrá inn notendur.\nÞú hefur lokað fyrir vefkökur.\nGjörðu svo vel og opnaðu fyrir þær, skráðu þig svo inn með notandanafni og lykilorði.",
+       "nocookiesnew": "Notandaaðgangur var búin til, en þú ert ekki skráð(ur) inn.\n{{SITENAME}} notar vefkökur til að skrá inn notendur.\nÞú hefur lokað fyrir vefkökur.\nEndilega opnaðu fyrir þær, skráðu þig svo inn með notandanafni og lykilorði.",
        "nocookieslogin": "{{SITENAME}} notar vefkökur til innskráningar. Vafrinn þinn er ekki að taka á móti þeim. Virkjaðu móttöku á vefkökum í vafranum þínum til að geta skráð þig inn.",
-       "nocookiesfornew": "Notenda aðgangurinn var ekki stofnaður, því ekki fannst uppruni beiðnarinnar.\nGakktu úr skugga um að vefkökur séu virkar, endurhladdu þessari síðu og reyndu aftur.",
+       "nocookiesfornew": "Notandaaðgangurinn var ekki stofnaður, því ekki var hægt að staðfesta uppruna beiðnarinnar.\nGakktu úr skugga um að vefkökur séu virkar, endurlestu þessa síðu og reyndu aftur.",
        "noname": "Þú hefur ekki tilgreint gilt notandanafn.",
        "loginsuccesstitle": "Innskráning tókst",
        "loginsuccess": "'''Þú ert nú innskráð(ur) á {{SITENAME}} sem „$1“.'''",
        "wrongpassword": "Uppgefið lykilorð er rangt. Reyndu aftur.",
        "wrongpasswordempty": "Lykilorðsreiturinn var auður. Reyndu aftur.",
        "passwordtooshort": "Lykilorð skal vera að minnsta kosti $1 {{PLURAL:$1|stafur|stafir}}.",
+       "passwordtoolong": "Lykilorð geta ekki verið lengri en $1 {{PLURAL:$1|stafur|stafir}}.",
+       "passwordtoopopular": "Ekki má nota algeng lykilorð. Veldu eitthvað alveg sérstakt lykilorð.",
        "password-name-match": "Þarf að lykilorð þitt sé öðruvísi notandanafni þínu",
        "password-login-forbidden": "Notkun þessa notandanafns og lykilorðs er ekki leyfileg.",
        "mailmypassword": "Endurstilla lykilorð",
        "retypenew": "Endurtaktu nýja lykilorðið:",
        "resetpass_submit": "Skrifaðu aðgangsorðið og skráðu þig inn",
        "changepassword-success": "Það tókst að breyta lykilorðinu þínu!",
-       "changepassword-throttled": "Þú hefur gert of margar tilraunir til innskráningar.\nBíddu í $1 áður en þú reynir aftur.",
+       "changepassword-throttled": "Þú hefur gert of margar tilraunir til innskráningar að undanförnu.\nBíddu í $1 áður en þú reynir aftur.",
        "botpasswords-label-create": "Búa til",
        "botpasswords-label-update": "Uppfæra",
        "botpasswords-label-cancel": "Hætta við",
        "resetpass-submit-loggedin": "Breyta lykilorði",
        "resetpass-submit-cancel": "Hætta við",
        "resetpass-wrong-oldpass": "Vitlaust bráðabirgða- eða núverandi lykilorð.\nÞú gætir þegar verið búin/n að breyta lykilorðinu eða sótt um nýtt bráðabirgðalykilorð",
+       "resetpass-temp-emailed": "Þú skráðir þig inn með bráðabirgðakóða úr tölvupósti.\nTil að klára að skrá þig inn, verður þú að velja nýtt lykilorð hér:",
        "resetpass-temp-password": "Bráðabirgðalykilorð:",
        "resetpass-abort-generic": "Breytingum á lykilorðum hefur verið hætt með viðbót.",
+       "resetpass-expired": "Lykilorðið þitt er útrunnið. Skráðu nýtt lykilorð til að skrá þig inn.",
        "passwordreset": "Endurstilla lykilorð",
        "passwordreset-text-one": "Útfylltu þetta eyðublað til þess að endursetja lykilorðið.",
        "passwordreset-disabled": "Lokað hefur verið fyrir að endurstilla lykilorð á þessum wiki.",
        "passwordreset-emailtext-user": "Notandinn $1 á {{SITENAME}} hefur beðið um endursetningu lykilorðsins þíns fyrir {{SITENAME}} ($4). Aðgangur eftirfarandi {{PLURAL:$3|notanda er|notendum eru}} tengd þessu netfangi:\n\n$2\n\nEf þetta er það sem þú vildir, þarftu að skrá þig inn og velja nýtt lykilorð. {{PLURAL:$3|Bráðabirgðalykilorðið rennur|Bráðabirgðalykilorðin renna}} út eftir $5 {{PLURAL:$5|dag|daga}}.\n\nEf það varst ekki þú sem fórst fram á þetta, eða ef þú manst aftur lykilorðið þitt, og vilt ekki lengur breyta því, skaltu hunsa þessi skilaboð og halda áfram að nota gamla lykilorðið.",
        "passwordreset-emailelement": "Notandanafn: \n$1\n\nBráðabirgðalykilorð: \n$2",
        "passwordreset-emailsentemail": "Ef þetta netfang er skráð fyrir aðganginum þínum þá hefur töluvpóstur verið sendur til að endursetja lykilorðið.",
+       "passwordreset-emailsentusername": "Ef eitthvað netfang er skráð fyrir aðganginum þínum, þá mun verða sendur töluvpóstur til að endursetja lykilorðið.",
        "passwordreset-emailsent-capture": "Tölvupóstur til að endursetja lykilorðið hefur verið sendur í tölvupósti, sem er sýndur hér fyrir neðan.",
        "passwordreset-emailerror-capture": "Tölvupóstur til að endursetja lykilorðið var búinn til, sem er sýndur hér fyrir neðan, en ekki tókst að senda hana til {{GENDER:$2|notandans}}: $1",
        "changeemail": "Breyta eða fjarlægja netfang",
        "changeemail-none": "(ekkert)",
        "changeemail-password": "{{SITENAME}} lykilorðið þitt:",
        "changeemail-submit": "Breyta netfangi",
+       "changeemail-throttled": "Þú hefur gert of margar tilraunir til innskráningar.\nBíddu í $1 áður en þú reynir aftur.",
        "changeemail-nochange": "Settu inn annað nýtt tölvupóstfang",
        "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.\n\nÞú á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.",
        "previewnote": "'''Það sem sést hér er aðeins forskoðun og hefur ekki enn verið vistað!'''",
        "continue-editing": "Fara á breytingasvæði",
        "previewconflict": "Þessi forskoðun endurspeglar textann í efra breytingarsvæði eins og hann myndi líta út ef þú vistar.",
-       "session_fail_preview": "Því miður! Við gátum ekki unnið úr breytingu þinni vegna týndra setugagna.\n\nÞú hefur kannski verið skráð/ur út. <strong>Sannreyndu hvort þú sért ennþá skráð/ur inn og reyndu aftur</strong>.\nEf það virkar ekki, reyndu að [[Special:UserLogout|skrá þig út]], skrá þig aftur inn og athugaðu hvort vafrinn þinn leyfikökur frá þessu vefsvæði.",
-       "session_fail_preview_html": "Afsakaðu! Við gátum ekki unnið úr breytingunni þinni vegna týndra lotugagna.\n\n<em>Þar sem {{SITENAME}} styður hráan HTML kóða, þá hefur forskoðunin verið falin sem vörn gegn JavaScript árásum.</em>\n\n<strong>Ef þetta er vingjarnleg breyting, reyndu þá aftur.</strong>\nEf það virkar ekki, reyndu að [[Special:UserLogout|skrá þig út]], skrá þig aftur inn og athugaðu hvort vafrinn þinn leyfir kökur frá þessu vefsvæði.",
+       "session_fail_preview": "Því miður! Við gátum ekki unnið úr breytingu þinni vegna týndra setugagna.\n\nÞú hefur kannski verið skráð/ur út. <strong>Sannreyndu hvort þú sért ennþá skráð/ur inn og reyndu aftur</strong>.\nEf það virkar ekki, reyndu að [[Special:UserLogout|skrá þig út]], skrá þig aftur inn og athugaðu hvort vafrinn þinn leyfi vefkökur frá þessu vefsvæði.",
+       "session_fail_preview_html": "Afsakaðu! Við gátum ekki unnið úr breytingunni þinni vegna týndra setugagna.\n\n<em>Þar sem {{SITENAME}} styður hráan HTML kóða, þá hefur forskoðunin verið falin sem vörn gegn JavaScript árásum.</em>\n\n<strong>Ef þetta er lögleg breyting, reyndu þá aftur.</strong>\nEf það virkar ekki, reyndu að [[Special:UserLogout|skrá þig út]], skrá þig aftur inn og athugaðu hvort vafrinn þinn leyfi vefkökur frá þessu vefsvæði.",
        "token_suffix_mismatch": "'''Breytingu þinni hefur verið hafnað því að biðlarinn þinn ruglaði greinarmerkingum í breytingar tókanum.\"\nÞetta er gert til að hindra spillingu texta síðunnar.\nÞetta getur gerst þegar þú notar bilaðan vafra eða ónafngreinda vefsels þjónustu.",
        "edit_form_incomplete": "'''Sumir hlutar breytingarinnar bárust ekki til vefþjónsins; athugaðu hvort breytingin þín er óbreytt og reyndu aftur.'''",
        "editing": "Breyti $1",
        "template-protected": "(vernduð)",
        "template-semiprotected": "(hálfvernduð)",
        "hiddencategories": "Þessi síða er meðlimur í $1 {{PLURAL:$1|földum flokki|földum flokkum}}:",
-       "edittools": "<!-- Þessi texti verður sýndur undir breytingar og upphölunar eyðublöðum. -->",
+       "edittools": "<!-- Þessi texti verður sýndur undir breytinga- og innhleðslueyðublöðum. -->",
        "edittools-upload": "-",
        "nocreatetext": "{{SITENAME}} hefur takmarkað eiginleikann að gera nýjar síður.\nÞú getur farið til baka og breytt núverandi síðum, eða [[Special:UserLogin|skráð þið inn eða búið til aðgang]].",
        "nocreate-loggedin": "Þú hefur ekki leyfi til að búa til nýjar síður.",
        "mergehistory-from": "Upprunaleg síða:",
        "mergehistory-into": "Áætlunarsíða:",
        "mergehistory-list": "Breytingaskrár sem hægt er að sameina",
-       "mergehistory-merge": "Eftirtaldar útgáfur [[:$1]] má sameina [[:$2]].\nNotaðu valtakkadálkinn til þess að sameina aðeins þær útgáfur sem stofnaðar voru fyrir uppgefið tímamark.\nAthugaðu að með því að nota flakktenglana er þessi dálkur endurstilltur.",
+       "mergehistory-merge": "Eftirtaldar útgáfur [[:$1]] má sameina [[:$2]].\nNotaðu valreitadálkinn til þess að sameina aðeins þær útgáfur sem stofnaðar voru fyrir uppgefið tímamark.\nAthugaðu að með því að nota flakktenglana er þessi dálkur endurstilltur.",
        "mergehistory-go": "Sýna breytingar sem hægt er að sameina",
        "mergehistory-submit": "Sameina útgáfur",
        "mergehistory-empty": "Engar útgáfur sem hægt er að sameina.",
        "right-suppressredirect": "Ekki búa til tilvísun frá gamla nafninu þegar síða er færð",
        "right-upload": "Hlaða inn skrám",
        "right-reupload": "Yfirrita núverandi skrá",
-       "right-reupload-own": "Yfirrita núverandi skrá sem að ég hlóð inn sjálf(ur)",
+       "right-reupload-own": "Yfirrita fyrirliggjandi skrár sem að ég hlóð inn sjálf(ur)",
        "right-reupload-shared": "Hunsa skrár á sameiginlegu myndasafni staðbundið",
-       "right-upload_by_url": "Hlaða inn skrám frá vefslóð",
+       "right-upload_by_url": "Hlaða inn skrám af vefslóð",
        "right-purge": "Hreinsa skyndiminni síðu án staðfestingar",
        "right-autoconfirmed": "Sneiða hjá takmörkunum vistfanga",
        "right-bot": "Eru meðhöndlaðir eins og sjálfvirk aðgerð",
        "action-upload": "hlaða inn þessari skrá",
        "action-reupload": "yfirrita þessa skrá",
        "action-reupload-shared": "Hunsa þessa skrá á sameiginlega myndasafninu",
-       "action-upload_by_url": "hlaða inn þessari skrá frá vefslóð",
+       "action-upload_by_url": "hlaða inn þessari skrá af vefslóð",
        "action-writeapi": "Nota API skrifun",
        "action-delete": "eyða þessari síðu",
        "action-deleterevision": "eyða þessari breytingu",
        "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 síður frá öðrum wiki",
-       "action-importupload": "flytja inn síður frá skráarupphali",
+       "action-importupload": "flytja inn síður úr innsendri skrá",
        "action-patrol": "Merkja breytingar annara sem yfirfarnar",
        "action-autopatrol": "Merkja eigin breytingu sem yfirfarna",
        "action-unwatchedpages": "Skoða lista yfir óvaktaðar síður",
        "recentchangeslinked-page": "Síðutitill:",
        "recentchangeslinked-to": "Sýna breytingar á síðum sem tengjast uppgefinni síðu í staðinn",
        "recentchanges-page-added-to-category": "[[:$1]] bætt við flokk",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] og $2 {{PLURAL:$2|síðu|síðum}} bætt við flokk",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] og $2 [[Special:WhatLinksHere/$1|{{PLURAL:$2|síðu|síðum}}]] bætt við flokk",
        "recentchanges-page-removed-from-category": "[[:$1]] fjarlægð úr flokki",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] og $2 {{PLURAL:$2|síðu|síðum}} fjarlægð úr flokki",
        "autochange-username": "Sjálfvirk MediaWiki-breyting",
        "upload": "Hlaða inn skrá",
        "uploadbtn": "Hlaða inn skrá",
-       "reuploaddesc": "Aftur á innhlaðningarformið.",
+       "reuploaddesc": "Hætta við og fara aftur á innhleðsluformið.",
        "upload-tryagain": "Sendu breytta myndlýsingu",
        "uploadnologin": "Óinnskráð(ur)",
-       "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",
+       "uploadnologintext": "Þú verður $1 til að hlaða inn skrám.",
+       "upload_directory_missing": "Innhleðslumappan ($1) er týnd og vefþjónninn gat ekki búið hana til.",
+       "upload_directory_read_only": "Mistókst að skrifa í innhleðslumöppu ($1) á vefþjóninum.",
+       "uploaderror": "Villa í innhleðslu",
        "upload-recreate-warning": "<strong>Viðvörun: Skrá með þessu nafni hefur verið eytt eða færð.</strong>\n\nAnnáll varðandi eyðingu og færslu þessarar síðu er birtur hér fyrir neðan til skýringar: \\",
-       "uploadtext": "Notaðu eyðublaðið hér fyrir neðan til að hlaða inn skrám.\nTil að skoða eða leita í áður innhlöðnum skrám ferðu á [[Special:FileList|skráarlistann]], (endur)innhlaðnar skrár eru skráðar í [[Special:Log/upload|innhlaðningarskránni]], eyðingar í [[Special:Log/delete|eyðingaskránni]].\n\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Skrá.jpg]]</nowiki></code>''' til að sýna skrána í fullri upplausn.\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Skrá.png|200px|thumb|left|alt-texti]]</nowiki></code>''' til að nota 200 mynddíla upplausn, í ramma á vinstri spássíu með 'alt text' sem myndlýsingu.\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Skrá.ogg]]</nowiki></code>''' til að tengja í myndina án þess að sýna hana.",
+       "uploadtext": "Notaðu eyðublaðið hér fyrir neðan til að hlaða inn skrám.\nTil að skoða eða leita í áður innhlöðnum skrám ferðu á [[Special:FileList|skráarlistann]], (endur)innhlaðnar skrár eru skráðar í [[Special:Log/upload|innhleðsluskránni]], eyðingar í [[Special:Log/delete|eyðingaskránni]].\n\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Skrá.jpg]]</nowiki></code>''' til að sýna skrána í fullri upplausn.\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Skrá.png|200px|thumb|left|alt-texti]]</nowiki></code>''' til að nota 200 mynddíla upplausn, í ramma á vinstri spássíu með 'alt text' sem myndlýsingu.\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Skrá.ogg]]</nowiki></code>''' til að tengja í myndina án þess að sýna hana.",
        "upload-permitted": "{{PLURAL:$2|Heimiluð skráargerð|Heimilaðar skráargerðir}}: $1.",
        "upload-preferred": "{{PLURAL:$2|Ákjósanleg skrárgerð|Ákjósanlegar skrárgerðir}}: $1.",
        "upload-prohibited": "{{PLURAL:$2|Óheimiluð skrárgerð|Óheimilaðar skrárgerðir}}: $1.",
-       "uploadlogpage": "Innhlaðningarskrá",
+       "uploadlogpage": "Innhleðsluskráning",
        "uploadlogpagetext": "Fyrir neðan er listi yfir nýlegast innsendu skrárnar.\nSjá [[Special:NewFiles|myndasafn nýrra mynda]] til að sjá myndrænna yfirlit.",
        "filename": "Skráarheiti",
        "filedesc": "Lýsing",
        "fileexists-forbidden": "Skrá með þessu nafni er þegar til og ekki er hægt að skrifa yfir hana.\nEf þú vilt hlaða skránni þinni inn engu að síður, farðu þá til baka og veldu annað skráarheiti.\n[[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "Skrá með þessu nafni er þegar til í sameiginlega myndasafninu.\nEf þú vilt hlaða skránni þinni inn engu að síður, farðu þá til baka og veldu annað skráarheiti.\n[[File:$1|thumb|center|$1]]",
        "file-exists-duplicate": "Þessi skrá er afrit eftirfarandi {{PLURAL:$1|skráar|skráa}}:",
-       "file-deleted-duplicate": "Afriti þessarar skráar ([[:$1]]) hefur verið eytt.\nÞú ættir að fara yfir eyðingarsögu skráarinnar áður en þú velur að hlaða skránni aftur inn.",
+       "file-deleted-duplicate": "Afriti þessarar skrár ([[:$1]]) hefur verið eytt.\nÞú ættir að fara yfir eyðingarsögu skrárinnar áður en þú velur að hlaða skránni aftur inn.",
        "file-deleted-duplicate-notitle": "Skrá sem er eins og þessi skrá hefur verið hlaðið inn áður og titill hennar hefur verið falinn.\nÞú ættir að spyrja einhvern með réttindi til að skoða falin skráagögn til að fara yfir málið áður en þú hleður skránni inn.",
-       "uploadwarning": "Aðvörun",
+       "uploadwarning": "Aðvörun vegna innsendingar",
        "uploadwarning-text": "Breyttu myndalýsingunni hér fyrir neðan og reyndu aftur.",
        "savefile": "Vista",
        "uploaddisabled": "Lokað er fyrir að hlaða inn myndum.",
        "copyuploaddisabled": "Lokað er fyrir að hlaða inn myndum frá vefslóð.",
        "uploaddisabledtext": "Lokað er fyrir að hlaða inn skrám.",
-       "php-uploaddisabledtext": "Upphleðsla skráa er óvirk í PHP.\nAthugaðu file_uploads stillinguna.",
+       "php-uploaddisabledtext": "Innhleðsla skráa er óvirk í PHP.\nAthugaðu file_uploads stillinguna.",
        "uploadscripted": "Þetta skjal inniheldur (X)HTML eða forskriftu sem gæti valdið villum í vöfrum.",
        "uploadscriptednamespace": "Þessi SVG-skrá inniheldur ógilt nafnrými \"$1\".",
        "uploadvirus": "Skráin inniheldur veiru! Nánari upplýsingar: $1",
-       "uploadjava": "Þessi skrá er ZIP skrá sem inniheldur Java .class skráasnið.\nUpphleðsla Java skráa er óheimil, því þær geta farið framhjá öryggiskröfum.",
+       "uploadjava": "Þessi skrá er ZIP skrá sem inniheldur Java .class skráasnið.\nInnhleðsla Java skráa er óheimil, því þær geta farið framhjá öryggiskröfum.",
        "upload-source": "Upprunaleg skrá",
        "sourcefilename": "Upprunalegt skráarheiti:",
        "sourceurl": "Uppruni:",
        "destfilename": "Móttökuskráarheiti:",
        "upload-maxfilesize": "Hámarks skráarstærð: $1",
        "upload-description": "Myndlýsing",
-       "upload-options": "Valmöguleikar fyrir upphöl",
+       "upload-options": "Valmöguleikar fyrir innsendingar",
        "watchthisupload": "Vakta þessa skrá",
        "filewasdeleted": "Skrá af sama nafni hefur áður verið hlaðið inn og síðan eytt. Þú ættir að athuga $1 áður en þú hleður skránni inn.",
+       "filename-thumb-name": "Titillinn bendir til þess að myndin sé smámynd. Vinsamlegast ekki hlaða inn smámyndum aftur á sama wiki og þær komu frá. Annars, ef það er ekki tilfellið, lagaðu skráarnafnið svo það hafi merkingu og hafi ekki forskeyti smámynda.",
        "filename-bad-prefix": "Skráarheitið byrjar á <strong>\"$1\"</strong> og er ekki lýsandi fyrir skrána, sem bendir til þess að það hafi verið það búið til af stafrænni myndavél.\nVeldu lýsandi nafn fyrir skrána og reyndu aftur.",
        "upload-proto-error": "Vitlaus samskiptaregla",
-       "upload-proto-error-text": "Upphleðsla frá öðrum vefþjóni þarfnast vefslóðar sem byrjar á <code>http://</code> eða <code>ftp://</code>.",
+       "upload-proto-error-text": "Innhleðsla frá öðrum vefþjóni þarfnast vefslóðar sem byrjar á <code>http://</code> eða <code>ftp://</code>.",
        "upload-file-error": "Innri villa",
        "upload-file-error-text": "Innri villa: Gat ekki búið til bráðabirgðaskrá á vefþjóni.\nEndilega hafðu samband við [[Special:ListUsers/sysop|stjórnanda]].",
        "upload-misc-error": "Óþekkt innhleðsluvilla",
-       "upload-misc-error-text": "Upphal þitt mistókst vegna óþekktrar villu.\nAthugaðu hvort vefslóðin sé rétt og aðgengileg og að því loknu reyndu aftur.\nEf vandamálið lagast ekki, hafðu samband við [[Special:ListUsers/sysop|stjórnanda]].",
+       "upload-misc-error-text": "Innsending þín mistókst vegna óþekktrar villu.\nAthugaðu hvort vefslóðin sé rétt og aðgengileg og að því loknu reyndu aftur.\nEf vandamálið lagast ekki, hafðu samband við [[Special:ListUsers/sysop|stjórnanda]].",
        "upload-too-many-redirects": "Vefslóðin inniheldur of margar tilvísanir.",
        "upload-http-error": "HTTP villa kom upp: $1",
-       "upload-copy-upload-invalid-domain": "Lokað er fyrir afritun skráa frá öðrum vefþjón á þessu vefsvæði.",
+       "upload-copy-upload-invalid-domain": "Lokað er fyrir afritun skráa frá öðrum vefþjónum á þessu vefsvæði.",
        "upload-dialog-title": "Hlaða inn skrá",
        "upload-dialog-button-cancel": "Hætta við",
        "upload-dialog-button-done": "Lokið",
        "foreign-structured-upload-form-label-infoform-date": "Dagsetning",
        "foreign-structured-upload-form-label-own-work-message-local": "Ég skil að ég sé að hlaða inn skrá samkvæmt notkunarskilmálum og leyfisskilmálum {{SITENAME}}.",
        "foreign-structured-upload-form-label-not-own-work-message-local": "Ef þú getur ekki hlaðið inn þessari skrá samkvæmt reglum {{SITENAME}}, lokaðu þá þessum glugga og reyndu aðra aðferð.",
-       "foreign-structured-upload-form-label-not-own-work-local-local": "Þú gætir einnig prófað að nota [[Special:Upload|sjálfgefnu upphleðslusíðuna]].",
+       "foreign-structured-upload-form-label-not-own-work-local-local": "Þú gætir einnig prófað að nota [[Special:Upload|sjálfgefnu innhleðslusíðuna]].",
        "foreign-structured-upload-form-label-own-work-message-default": "Ég skil að ég sé að hlaða inn skrá á sameiginlegt vefsvæði. Ég staðfesti að ég sé að gera það samkvæmt notkunarskilmálum og leyfisskilmálum þess.",
        "foreign-structured-upload-form-label-not-own-work-message-default": "Ef þú getur ekki hlaðið inn þessari skrá samkvæmt reglum sameiginlega vefsvæðisins, lokaðu þá þessum glugga og reyndu aðra aðferð.",
-       "foreign-structured-upload-form-label-not-own-work-local-default": "Þú gætir einnig prófað að nota [[Special:Upload|upphleðslusíðuna á {{SITENAME}}]], ef það má hlaða þessari skrá inn samkvæmt reglum þeirra.",
+       "foreign-structured-upload-form-label-not-own-work-local-default": "Þú gætir einnig prófað að nota [[Special:Upload|innhleðslusíðuna á {{SITENAME}}]], ef það má hlaða þessari skrá inn samkvæmt reglum þeirra.",
        "foreign-structured-upload-form-label-own-work-message-shared": "Ég staðfesti að ég eigi höfundarréttinn að þessari skrá og samþykki óafturkræft að gefa þessa skrá til Wikimedia Commons undir  [https://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0] leyfi. Ég samþykki [https://wikimediafoundation.org/wiki/Terms_of_Use notendaskilmálana].",
-       "foreign-structured-upload-form-label-not-own-work-message-shared": "Ef þú átt ekki höfundarréttinn að þessari skrá, eða þú vilt gefa það út undir öðru leyfi, prófaðu  [https://commons.wikimedia.org/wiki/Special:UploadWizard Upphleðsluálfinn á Commons].",
-       "foreign-structured-upload-form-label-not-own-work-local-shared": "Þú gætir einnig prófað að nota [[Special:Upload|upphleðslusíðuna á {{SITENAME}}]], ef það má hlaða þessari skrá inn samkvæmt reglum þeirra.",
+       "foreign-structured-upload-form-label-not-own-work-message-shared": "Ef þú átt ekki höfundarréttinn að þessari skrá, eða þú vilt gefa það út undir öðru leyfi, prófaðu  [https://commons.wikimedia.org/wiki/Special:UploadWizard Innsendingaálfinn á Commons].",
+       "foreign-structured-upload-form-label-not-own-work-local-shared": "Þú gætir einnig prófað að nota [[Special:Upload|innhleðslusíðuna á {{SITENAME}}]], ef það má hlaða þessari skrá inn samkvæmt reglum þeirra.",
        "backend-fail-stream": "Gat ekki streymt skránni „$1“.",
        "backend-fail-backup": "Öryggisafritun skrárinnar $1 mistókst.",
        "backend-fail-notexists": "Skráin $1 er ekki til.",
        "invalid-chunk-offset": "Ógild raðbreyting bunka",
        "img-auth-accessdenied": "Aðgangur óheimill",
        "img-auth-nopathinfo": "PATH_INFO vantar.\nBiðlarinn þínn er ekki stilltur til að gefa upp þessar upplýsingar.\nÞær mega vera CGI-byggðar og mega ekki styðja img_auth.\nhttps://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization",
-       "img-auth-notindir": "Umbeðin slóð var ekki í stilltri upphlaðsmöppu.",
+       "img-auth-notindir": "Umbeðin slóð var ekki í stilltri innhleðslumöppu.",
        "img-auth-badtitle": "Mistókst að búa til gildan titil útfrá „$1”.",
        "img-auth-nologinnWL": "Þú ert ekki skráð(ur) inn og „$1“ er ekki á hvítlista.",
        "img-auth-nofile": "Skráin \"$1\" er ekki til.",
        "upload_source_url": "(skrá sem þú velur frá gildri og aðgengilegri vefslóð)",
        "upload_source_file": "(skrá sem þú velur á tölvunni þinni)",
        "listfiles-delete": "eyða",
-       "listfiles-summary": "Þessi kerfissíða sýnir allar upphlaðnar skrár.",
+       "listfiles-summary": "Þessi kerfissíða sýnir allar innsendar skrár.",
        "listfiles_search_for": "Leita að heiti gagnamiðils:",
        "listfiles-userdoesnotexist": "Notandinn \"$1\" er ekki skráður.",
        "imgfile": "skrá",
        "shared-repo-from": "frá $1",
        "shared-repo": "sameiginlegu myndasafni",
        "shared-repo-name-wikimediacommons": "Wikimedia Commons",
+       "filepage.css": "/* Allt CSS sem sett er hér er haft með á lýsingarsíðunni, en einnig á utanaðkomandi tilvísandi wiki-um (foreign client wikis). */",
        "upload-disallowed-here": "Þú getur ekki yfirskrifað þessa skrá.",
        "filerevert": "Taka aftur $1",
        "filerevert-legend": "Taka aftur skrá",
        "mimesearch": "MIME-leit",
        "mimesearch-summary": "Þessi síða gerir þér kleift að leita eftir skrám eftir MIME-gerð þeirra.\n\nLeitarstrengurinn á að vera á þessu formi: efnistag/myndasnið eða efnismerki/*, t.d. <code>image/jpeg</code>.",
        "mimetype": "MIME-tegund:",
-       "download": "Hlaða niður",
+       "download": "sækja",
        "unwatchedpages": "Óvaktaðar síður",
        "listredirects": "Endurbeiningar",
        "listduplicatedfiles": "Listi yfir afritaðar skrár",
        "statistics-articles": "Greinar alls",
        "statistics-pages": "Síður",
        "statistics-pages-desc": "Allar síður wiki-verkefnisins, þar á meðal spjallsíður, tilvísanir o.fl.",
-       "statistics-files": "Skráafjöldi",
+       "statistics-files": "Innsendar skrár",
        "statistics-edits": "Síðubreytingar frá því {{SITENAME}} byrjaði",
        "statistics-edits-average": "Meðal breytingafjöldi á síðu",
        "statistics-users": "Skráðir  [[Special:ListUsers|notendur]]",
        "apisandbox-submit": "Gera fyrirspurn",
        "apisandbox-reset": "Hreinsa",
        "apisandbox-retry": "Reyna aftur",
+       "apisandbox-loading": "Hleð inn upplýsingum fyrir API-eininguna \"$1\"...",
+       "apisandbox-no-parameters": "Þessi API-eining hefur engin viðföng.",
        "apisandbox-helpurls": "Hjálpartenglar",
        "apisandbox-examples": "Dæmi",
        "apisandbox-dynamic-parameters": "Auka viðföng",
        "sp-contributions-blocklog": "fyrri bönn",
        "sp-contributions-suppresslog": "bæld framlög notanda",
        "sp-contributions-deleted": "eyddar breytingar notanda",
-       "sp-contributions-uploads": "upphlaðið",
+       "sp-contributions-uploads": "innsendingar",
        "sp-contributions-logs": "aðgerðaskrá",
        "sp-contributions-talk": "spjall",
        "sp-contributions-userrights": "Breyta notandaréttindum",
        "importsuccess": "Innflutningi lokið!",
        "importnosources": "Engin wiki sem á að flytja inn frá hafa verið skilgreind og beinar innsendingar breytingaskráa eru óvirkar.",
        "importnofile": "Engri skrá var hlaðið inn.",
-       "importuploaderrorsize": "Upphleðsla skrárinnar mistókst.\nSkráin er stærri en leyfð hámarksstærð.",
-       "importuploaderrorpartial": "Upphleðsla skráarinnar mistókst.\nSkráinni var eingöngu hlaðið inn að hluta.",
-       "importuploaderrortemp": "Upphleðsla skrárinnar mistókst.\nBráðabirgðamappa fannst ekki.",
+       "importuploaderrorsize": "Innsending skrárinnar mistókst.\nSkráin er stærri en leyfð hámarksstærð.",
+       "importuploaderrorpartial": "Innsending skráarinnar mistókst.\nSkráinni var eingöngu hlaðið inn að hluta.",
+       "importuploaderrortemp": "Innsending skrárinnar mistókst.\nBráðabirgðamappa fannst ekki.",
        "import-parse-failure": "Þáttunarvilla við innflutning XML skjals",
        "import-noarticle": "Engin síða til innflutnings!",
        "import-nonewrevisions": "Engar breytingar voru fluttar inn (þær voru allar annaðhvort þegar til eða sleppt vegna villna).",
        "xml-error-string": "$1 í línu $2, dálki $3 ($4 bæt): $5",
        "import-upload": "Hlaða inn XML-gögnum",
-       "import-token-mismatch": "Týnd setugögn.\n\nÞú hefur kannski verið skráð/ur út. <strong>Athugaðu hvort þú sért ennþá skráð/ur inn og reyndu aftur</strong>.\nEf það virkar ekki, reyndu að [[Special:UserLogout|skrá þig út]], skrá þig aftur inn og gakktu úr skugga um að vafrinn þinn leyfi smákökur frá þessu vefsvæði.",
+       "import-token-mismatch": "Týnd setugögn.\n\nÞú hefur kannski verið skráð/ur út. <strong>Athugaðu hvort þú sért ennþá skráð/ur inn og reyndu aftur</strong>.\nEf það virkar ekki, reyndu að [[Special:UserLogout|skrá þig út]], skrá þig aftur inn og gakktu úr skugga um að vafrinn þinn leyfi vefkökur frá þessu vefsvæði.",
        "import-invalid-interwiki": "Get ekki flutt inn frá þessum wiki.",
        "import-error-edit": "Síðan \"$1\" var ekki flutt inn því þú hefur ekki réttindi til að breyta henni.",
        "import-error-create": "Síðan \"$1\" var ekki flutt inn því þú hefur ekki réttindi til að stofna hana.",
        "tags-edit-chosen-placeholder": "Veldu einhver merki",
        "tags-edit-chosen-no-results": "Engin merki fundust sem samsvara",
        "tags-edit-reason": "Ástæða:",
+       "tags-edit-nooldid-title": "Ógild markútgáfa",
        "tags-edit-none-selected": "Vinsamlega veldu a.m.k. eitt merki til að bæta við eða fjarlægja.",
        "comparepages": "Bera saman síður",
        "compare-page1": "Síða 1",
        "htmlform-chosen-placeholder": "Veldu valmöguleika",
        "htmlform-cloner-create": "Bæta við meiru",
        "htmlform-cloner-delete": "Fjarlægja",
+       "htmlform-cloner-required": "Það þarf allavega eitt gildi.",
        "htmlform-title-badnamespace": "[[:$1]] er ekki í \"{{ns:$2}}\" nafnrýminu.",
+       "htmlform-title-not-creatable": "\"$1\" er ekki hægt að nota við að búa til titil á síðu",
        "htmlform-title-not-exists": "$1 er ekki til",
        "htmlform-user-not-exists": "<strong>$1</strong> er ekki til.",
        "htmlform-user-not-valid": "<strong>$1</strong> er ekki gilt notandanafn.",
        "logentry-block-unblock": "$1 {{GENDER:$2|afbannaði}} {{GENDER:$4|$3}}",
        "logentry-block-reblock": "$1 {{GENDER:$2|breytti}} bann stillingum fyrir {{GENDER:$4|$3}}, rennur út $5 $6",
        "logentry-suppress-block": "$1 {{GENDER:$2|bannaði}} {{GENDER:$4|$3}}, rennur út eftir $5 $6",
-       "logentry-merge-merge": "$1 {{GENDER:$2|sameinaði}} $3 inn í $4 (útgáfur til $5)",
+       "logentry-import-upload": "$1 {{GENDER:$2|flutti inn}} $3 úr innsendri skrá",
+       "logentry-import-upload-details": "$1 {{GENDER:$2|flutti}} $3 inn úr innsendri skrá ($4 {{PLURAL:$4|útgáfa|útgáfur}})",
+       "logentry-import-interwiki": "$1 {{GENDER:$2|flutti inn}} $3 frá öðru wiki",
+       "logentry-import-interwiki-details": "$1 {{GENDER:$2|flutti}} $3 inn frá $5 ($4 {{PLURAL:$4|útgáfa|útgáfur}})",
+       "logentry-merge-merge": "$1 {{GENDER:$2|sameinaði}} $3 inn í $4 (útgáfur upp að $5)",
        "logentry-move-move": "$1 {{GENDER:$2|færði}} $3 á $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|færði}} $3 á $4 án þess að skilja eftir tilvísun",
        "logentry-move-move_redir": "$1 {{GENDER:$2|færði}} $3 á $4 yfir tilvísun",
        "logentry-newusers-create2": "$1 {{GENDER:$2|stofnaði}} notandaaðganginn $3",
        "logentry-newusers-byemail": "Notandaaðgangurinn $3 var {{GENDER:$2|búinn til}} af $1 og lykilorðið var sent með tölvupósti",
        "logentry-newusers-autocreate": "Aðgangurinn $1 var {{GENDER:$2|stofnaður}} sjálfvirkt",
+       "logentry-protect-move_prot": "$1 {{GENDER:$2|flutti}} verndunarstillingu úr $4 í $3",
+       "logentry-protect-unprotect": "$1 {{GENDER:$2|fjarlægði}} verndun af $3",
        "logentry-protect-protect": "$1 {{GENDER:$2|verndaði}} $3 $4",
+       "logentry-protect-modify": "$1 {{GENDER:$2|breytti}} verndunarstigi fyrir $3 $4",
        "logentry-rights-rights": "$1 {{GENDER:$2|breytti}} réttindum $3 frá $4 í $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|breytti}} réttindum $3",
        "logentry-rights-autopromote": "$1 fékk sjálfvirkt {{GENDER:$2|aukin}} réttindi frá $4 til $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|hlóð inn}} $3",
        "logentry-upload-overwrite": "$1 {{GENDER:$2|hlóð inn}} nýrri útgáfu af $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2|hlóð inn}} $3",
        "log-name-managetags": "Breytingaskrá yfir sýsl með merki",
        "logentry-managetags-create": "$1 {{GENDER:$2|bjó til}} merkið \"$4\"",
        "rightsnone": "(engum)",
        "searchsuggest-containing": "sem innihalda ...",
        "api-error-badaccess-groups": "Þú hefur ekki leyfi til að hlaða inn skrám.",
        "api-error-badtoken": "Innri villa: Skemmdur tóki.",
-       "api-error-copyuploaddisabled": "Ekki er hægt að hlaða upp með vefslóð á þessum vefþjón.",
+       "api-error-copyuploaddisabled": "Ekki er hægt að hlaða inn með vefslóð á þessum vefþjóni.",
        "api-error-duplicate": "Það {{PLURAL:$1|er önnur skrá|eru aðrar skrár}} þegar til á vefsvæðinu sem hafa sama innihald.",
        "api-error-duplicate-archive": "Það {{PLURAL:$1|var önnur skrá|voru aðrar skrár}} þegar á síðunni með sama innihald, en {{PLURAL:$1|henni|þeim}} var eytt.",
        "api-error-empty-file": "Skráin sem þú valdir er tóm.",
        "api-error-hookaborted": "Hætt var við breytinguna sem þú reyndir að gera með viðbót.",
        "api-error-http": "Innri villa: Get ekki tengst vefþjón.",
        "api-error-illegal-filename": "Þetta skráarheiti er ekki leyft.",
-       "api-error-internal-error": "Innri villa: Mistókst að vinna úr upphali þínu.",
+       "api-error-internal-error": "Innri villa: Mistókst að vinna úr innsendingunni þinni.",
        "api-error-invalid-file-key": "Innri villa: Skrá fannst ekki í bráðabirgðageymslu.",
        "api-error-missingparam": "Innri villa: Breytur vantar í beiðni.",
        "api-error-missingresult": "Innri villa: Gat ekki ákvarðað hvort tókst að afrita.",
        "api-error-mustbeloggedin": "Þú verður að vera skráður inn til að hlaða inn skrám.",
        "api-error-mustbeposted": "Innri villa: Beiðnin þarfnast HTTP POST.",
-       "api-error-noimageinfo": "Upphleðsla skrárinnar tókst, en vefþjónninn gaf okkur engar upplýsingar um skrána.",
-       "api-error-nomodule": "Innri villa: Engin upphlaðs eining valin.",
+       "api-error-noimageinfo": "Innsending skrárinnar tókst, en vefþjónninn gaf okkur engar upplýsingar um skrána.",
+       "api-error-nomodule": "Innri villa: Engin innsendingareining valin.",
        "api-error-ok-but-empty": "Innri villa: ekkert svar frá vefþjón.",
        "api-error-overwrite": "Óheimilt er að skrifa yfir skrá sem er þegar til.",
        "api-error-stashfailed": "Innri villa: Vefþjónninn gat ekki geymt bráðabirgðaskrá.",
        "expand_templates_generate_xml": "Birta XML-þáttunargreinar",
        "expand_templates_generate_rawhtml": "Birta hrátt HTML",
        "expand_templates_preview": "Forskoðun",
+       "expand_templates_preview_fail_html": "<em>Þar sem {{SITENAME}} styður hráan HTML kóða, þá hefur forskoðunin verið falin sem vörn gegn JavaScript árásum.</em>\n\n<strong>Ef þetta er lögleg breyting, reyndu þá aftur.</strong>\nEf það virkar ekki, reyndu að [[Special:UserLogout|skrá þig út]], skrá þig aftur inn og athugaðu hvort vafrinn þinn leyfi vefkökur frá þessu vefsvæði.",
+       "expand_templates_preview_fail_html_anon": "<em>Þar sem {{SITENAME}} styður hráan HTML kóða og þú ert ekki skráð/ur inn, þá hefur forskoðunin verið falin sem vörn gegn JavaScript árásum.</em>\n\n<strong>Ef þetta er lögleg breyting, reyndu að [[Special:UserLogin|skrá þig inn]], og prófa aftur.</strong>",
        "expand_templates_input_missing": "Þú verður að skrifa inn einhvern inntakstexta.",
        "pagelanguage": "Breyta tungumáli síðu",
        "pagelang-name": "Síða",
        "right-pagelang": "Breyta tungumáli síðu",
        "action-pagelang": "breyta tungumáli síðunnar",
        "log-name-pagelang": "Annáll yfir breytingar á tungumáli",
+       "log-description-pagelang": "Þetta er skráning yfir breytingar á tungumáli síðna.",
        "logentry-pagelang-pagelang": "$1 {{GENDER:$2|breytti}} tungumáli $3 úr $4 yfir í $5",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (virkt)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>óvirkt</strong>)",
        "api-error-blacklisted": "Veldu annan lýsandi titil",
        "sessionmanager-tie": "Get ekki sameinað margar gerðir auðkenningarbeiðna: $1.",
        "sessionprovider-generic": "$1 setur",
-       "sessionprovider-mediawiki-session-cookiesessionprovider": "setur með smákökum",
-       "sessionprovider-nocookies": "Smákökur gætu verið óvirkar. Gakktu úr skugga um að smákökur séu virkar og byrjaðu svo aftur.",
+       "sessionprovider-mediawiki-session-cookiesessionprovider": "setur með vefkökum",
+       "sessionprovider-nocookies": "Vefkökur gætu verið óvirkar. Gakktu úr skugga um að smákökur séu virkar og byrjaðu svo aftur.",
        "randomrootpage": "Handahófsvalin rótarsíða"
 }
index fb23335..270c002 100644 (file)
        "noemail": "Nessun indirizzo e-mail registrato per l'utente \"$1\".",
        "noemailcreate": "È necessario fornire un indirizzo e-mail valido",
        "passwordsent": "Una nuova password è stata inviata all'indirizzo e-mail registrato per l'utente \"$1\".\nPer favore, effettua un accesso non appena la ricevi.",
-       "blocked-mailpassword": "Per prevenire abusi, non è consentito usare la funzione \"Invia nuova password\" da un indirizzo IP bloccato.",
+       "blocked-mailpassword": "Il tuo indirizzo IP è bloccato alla modifica. Per prevenire abusi, non è consentito usare la funzione di recupero password da questo indirizzo IP.",
        "eauthentsent": "Un messaggio email di conferma è stato spedito all'indirizzo indicato.\nPer abilitare l'invio di messaggi email per questo utente è necessario seguire le istruzioni che vi sono indicate, in modo da confermare che si è i legittimi proprietari dell'indirizzo.",
        "throttled-mailpassword": "Una email di reimpostazione della password è già stata inviata da meno di {{PLURAL:$1|1 ora|$1 ore}}.\nPer prevenire abusi, la funzione di reimpostazione della password può essere usata solo una volta ogni {{PLURAL:$1|ora|$1 ore}}.",
        "mailerror": "Errore nell'invio del messaggio: $1",
        "botpasswords-insert-failed": "Impossibile aggiungere il nome bot \"$1\". È stato già aggiunto?",
        "botpasswords-update-failed": "Impossibile aggiornare il nome bot \"$1\". È stato cancellato?",
        "botpasswords-created-title": "Password bot creata",
-       "botpasswords-created-body": "La password bot \"$1\" è stata creata.",
+       "botpasswords-created-body": "La password per il bot di nome \"$1\" dell'utente \"$2\" è stata creata.",
        "botpasswords-updated-title": "Password bot aggiornata",
-       "botpasswords-updated-body": "La password bot \"$1\" è stata aggiornata.",
+       "botpasswords-updated-body": "La password per il bot di nome \"$1\" dell'utente \"$2\" è stata aggiornata.",
        "botpasswords-deleted-title": "Password bot cancellata",
-       "botpasswords-deleted-body": "La password bot \"$1\" è stata cancellata.",
+       "botpasswords-deleted-body": "La password per il bot di nome \"$1\" dell'utente \"$2\" è stata cancellata.",
        "botpasswords-newpassword": "La nuova password per accedere con <strong>$1</strong> è <strong>$2</strong>. <em>Registratelo per consultazioni future.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider non è disponibile.",
        "botpasswords-restriction-failed": "Le restrizioni di password bot impediscono questo accesso.",
        "passwordreset-emailsentusername": "Se c'è un indirizzo di posta elettronica associato con questo nome utente, allora verrà inviata una email per reimpostare la password.",
        "passwordreset-emailsent-capture": "È stata inviata una email di reimpostazione della password, il contenuto è riportato di seguito.",
        "passwordreset-emailerror-capture": "È stata generata una email di reimpostazione della password, riportata di seguito. L'invio {{GENDER:$2|all'utente}} non è riuscito: $1",
-       "changeemail": "Modifica o rimuovi indirizzo email",
+       "changeemail": "Modifica o rimuovi indirizzo di posta elettronica",
        "changeemail-header": "Completa questo modulo per cambiare il tuo indirizzo email. Se vuoi rimuovere l'associazione di qualsiasi indirizzo email dalla tua utenza, lascia il nuovo indirizzo email vuoto quando invii il modulo.",
        "changeemail-passwordrequired": "Sarà necessario inserire la password per confermare la modifica.",
        "changeemail-no-info": "Devi aver effettuato l'accesso per accedere a questa pagina direttamente.",
        "revdelete-submit": "Applica {{PLURAL:$1|alla versione selezionata|alle versioni selezionate}}",
        "revdelete-success": "Visibilità della versione aggiornata.",
        "revdelete-failure": "'''La visibilità della versione non può essere aggiornata:'''\n$1",
-       "logdelete-success": "'''Visibilità dell'evento impostata correttamente.'''",
+       "logdelete-success": "Impostata visibilità dell'evento.",
        "logdelete-failure": "'''La visibilità dell'evento non può essere impostata:'''\n$1",
        "revdel-restore": "cambia la visibilità",
        "pagehist": "Cronologia della pagina",
        "mergelog": "Unioni",
        "revertmerge": "Annulla unioni",
        "mergelogpagetext": "Di seguito sono elencate le ultime operazioni di unione della cronologia di due pagine.",
-       "history-title": "$1: cronologia delle modifiche",
-       "difference-title": "$1: differenze tra le versioni",
-       "difference-title-multipage": "$1 e $2: differenze tra le pagine",
+       "history-title": "Cronologia delle modifiche di \"$1\"",
+       "difference-title": "Differenze tra le versioni di \"$1\"",
+       "difference-title-multipage": "Differenze tra le pagine \"$1\" e \"$2\"",
        "difference-multipage": "(Differenze fra le pagine)",
        "lineno": "Riga $1:",
        "compareselectedversions": "Confronta le versioni selezionate",
        "prefs-watchlist-token": "Token osservati speciali:",
        "prefs-misc": "Varie",
        "prefs-resetpass": "Cambia password",
-       "prefs-changeemail": "Modifica o rimuovi indirizzo email",
-       "prefs-setemail": "Imposta un indirizzo email",
+       "prefs-changeemail": "Modifica o rimuovi indirizzo di posta elettronica",
+       "prefs-setemail": "Imposta un indirizzo di posta elettronica",
        "prefs-email": "Opzioni email",
        "prefs-rendering": "Aspetto",
        "saveprefs": "Salva",
        "prefs-custom-js": "JavaScript personalizzato",
        "prefs-common-css-js": "CSS/JavaScript condiviso per tutti i temi:",
        "prefs-reset-intro": "È possibile usare questa pagina per reimpostare le proprie preferenze a quelle predefinite del sito.\nL'operazione non può essere annullata.",
-       "prefs-emailconfirm-label": "Conferma dell'e-mail:",
+       "prefs-emailconfirm-label": "Conferma dell'email:",
        "youremail": "Indirizzo email:",
        "username": "{{GENDER:$1|Nome utente}}:",
        "prefs-memberingroups": "{{GENDER:$2|Membro}} {{PLURAL:$1|del gruppo|dei gruppi}}:",
        "recentchangeslinked-page": "Nome della pagina:",
        "recentchangeslinked-to": "Mostra solo le modifiche alle pagine collegate a quella specificata",
        "recentchanges-page-added-to-category": "[[:$1]] aggiunta alla categoria",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] e {{PLURAL:$2|una pagina è aggiunta|$2 pagine sono aggiunte}} alla categoria",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|un'altra pagina|altre $2 pagine}}]] sono state aggiunte alla categoria",
        "recentchanges-page-removed-from-category": "[[:$1]] rimossa dalla categoria",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e {{PLURAL:$2|un'altra pagina|altre $2 pagine}} rimosse dalla categoria",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|un'altra pagina|altre $2 pagine}}]] sono state rimosse dalla categoria",
        "autochange-username": "Modifica automatica MediaWiki",
        "upload": "Carica un file",
        "uploadbtn": "Carica",
        "uploadstash-summary": "Questa pagina consente l'accesso ai file che sono stati caricati (o sono in fase di caricamento) ma che non sono stati ancora pubblicati sul wiki. Questi file sono visibili solo all'utente che li ha caricati.",
        "uploadstash-clear": "Elimina i file in stash",
        "uploadstash-nofiles": "Non hai file in stash.",
-       "uploadstash-badtoken": "Questa azione non ha avuto successo, forse perché le tue credenziali di modifica sono scadute. Prova ancora.",
+       "uploadstash-badtoken": "Esecuzione dell'azione non riuscita, forse perché le tue credenziali di modifica sono scadute. Prova ancora.",
        "uploadstash-errclear": "La pulizia dei file non è riuscita.",
        "uploadstash-refresh": "Aggiorna l'elenco dei file",
+       "uploadstash-thumbnail": "vedi miniatura",
        "invalid-chunk-offset": "Offset della parte non valido.",
        "img-auth-accessdenied": "Accesso negato",
        "img-auth-nopathinfo": "PATH_INFO mancante.\nIl server non è impostato per passare questa informazione.\nPotrebbe essere basato su CGI e non può supportare img_auth.\nVedi https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization",
        "changecontentmodel-title-label": "Titolo della pagina",
        "changecontentmodel-model-label": "Nuovo modello di contenuto",
        "changecontentmodel-reason-label": "Motivo:",
+       "changecontentmodel-submit": "Modifica",
        "changecontentmodel-success-title": "Il modello di contenuto è stato modificato",
        "changecontentmodel-success-text": "Il tipo di contenuto di [[:$1]] è stato modificato.",
        "changecontentmodel-cannot-convert": "Il contenuto di [[:$1]] non può essere convertito in tipo $2.",
        "ipb-unblock": "Sblocca un utente o un indirizzo IP",
        "ipb-blocklist": "Elenca i blocchi attivi",
        "ipb-blocklist-contribs": "Contributi di {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 rimasti",
        "unblockip": "Sblocca l'utente",
        "unblockiptext": "Usare il modulo sottostante per restituire l'accesso in scrittura ad un utente o indirizzo IP bloccato.",
        "ipusubmit": "Rimuovi questo blocco",
        "import-logentry-upload-detail": "{{PLURAL:$1|una versione importata|$1 versioni importate}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|una versione importata|$1 versioni importate}} da $2",
        "javascripttest": "Sperimentazione JavaScript",
-       "javascripttest-pagetext-noframework": "Questa pagina è riservata all'esecuzione di test di JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Framework di test sconosciuto \"$1\".",
        "javascripttest-pagetext-unknownaction": "Azione sconosciuta \"$1\".",
-       "javascripttest-pagetext-frameworks": "Per cortesia, scegli uno dei seguenti framework per i test: $1",
-       "javascripttest-pagetext-skins": "Scegli un tema con cui eseguire i test:",
        "javascripttest-qunit-intro": "Vedi su mediawiki.org la [$1 documentazione riguardante i test].",
        "tooltip-pt-userpage": "La {{GENDER:|tua}} pagina utente",
        "tooltip-pt-anonuserpage": "La pagina utente di questo indirizzo IP",
        "confirmrecreate": "L'utente [[User:$1|$1]] ([[User talk:$1|discussioni]]) ha cancellato questa pagina dopo che hai iniziato a modificarla, per il seguente motivo: ''$2''\nPer favore, conferma che vuoi veramente ricreare questa pagina.",
        "confirmrecreate-noreason": "L'utente [[User:$1|$1]] ([[User talk:$1|discussioni]]) {{GENDER:$1|ha cancellato}} questa pagina dopo che hai iniziato a modificarla. Per favore, conferma che vuoi veramente ricreare questa pagina.",
        "recreate": "Ricrea",
-       "confirm_purge_button": "Conferma",
+       "confirm_purge_button": "OK",
        "confirm-purge-top": "Vuoi pulire la cache di questa pagina?",
        "confirm-purge-bottom": "Ripulire la cache di una pagina consente di mostrare la sua versione più aggiornata.",
        "confirm-watch-button": "OK",
        "version-libraries-description": "Descrizione",
        "version-libraries-authors": "Autori",
        "redirect": "Reindirizzamento da file, utente, pagina, versione o ID registro",
-       "redirect-legend": "Reindirizza a un file o una pagina",
        "redirect-summary": "Questa pagina speciale reindirizza a un file (specificando il nome del file), a una pagina (specificando un ID di versione o un ID pagina), a un utente (specificando un ID utente numerico) o ad un elemento del registro (specificando l'ID registro).\nEsempi: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Vai",
        "redirect-lookup": "Ricerca:",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|ha protetto}} $3 $4 [ricorsiva]",
        "logentry-protect-modify": "$1 {{GENDER:$2|ha modificato}} il livello di protezione per $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|ha modificato}} il livello di protezione per $3 $4 [ricorsiva]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|ha modificato}} l'appartenenza di $3 dal gruppo $4 al gruppo $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|ha modificato}} l'appartenenza di {{GENDER:$3|$3}} dal gruppo $4 al gruppo $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|ha modificato}} l'appartenenza a gruppi di $3",
        "logentry-rights-autopromote": "$1 è {{GENDER:$2|stato promosso|stata promossa|stato/a promosso/a}} automaticamente da $4 a $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|ha caricato}} $3",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "Simboli",
        "special-characters-group-greek": "Greco",
+       "special-characters-group-greekextended": "Greco esteso",
        "special-characters-group-cyrillic": "Cirillico",
        "special-characters-group-arabic": "Arabo",
        "special-characters-group-arabicextended": "Arabo esteso",
        "sessionprovider-generic": "sessioni $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessioni basate su cookie",
        "sessionprovider-nocookies": "I cookie possono essere disattivati. Assicurati di avere i cookie abilitati e ha inizia nuovamente.",
-       "randomrootpage": "Pagina radice casuale"
+       "randomrootpage": "Pagina radice casuale",
+       "log-action-filter-block": "Tipo di blocco:",
+       "log-action-filter-delete": "Tipo di cancellazione:",
+       "log-action-filter-patrol": "Tipo di verifica:",
+       "log-action-filter-protect": "Tipo di protezione:",
+       "log-action-filter-upload": "Tipo di caricamento:",
+       "log-action-filter-all": "Tutto",
+       "log-action-filter-block-block": "Blocco",
+       "log-action-filter-block-reblock": "Modifica blocco",
+       "log-action-filter-block-unblock": "Sblocco",
+       "log-action-filter-delete-delete": "Cancellazione pagina",
+       "log-action-filter-delete-restore": "Ripristino pagina",
+       "log-action-filter-delete-event": "Cancellazione registro",
+       "log-action-filter-delete-revision": "Cancellazione versione",
+       "log-action-filter-patrol-patrol": "Verifica manuale",
+       "log-action-filter-patrol-autopatrol": "Verifica automatica",
+       "log-action-filter-protect-protect": "Protezione",
+       "log-action-filter-protect-modify": "Modifica protezione",
+       "log-action-filter-protect-unprotect": "Sprotezione",
+       "log-action-filter-upload-upload": "Nuovo caricamento",
+       "log-action-filter-upload-overwrite": "Ricaricamento"
 }
index af4af2c..3a07609 100644 (file)
        "nocookiesfornew": "発信元を確認できなかったため、アカウントは作成されませんでした。\nCookieを有効にしていることを確認して、このページを再読込してもう一度試してください。",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "有効な利用者名が指定されていません。",
-       "loginsuccesstitle": "ã\83­ã\82°ã\82¤ã\83³æ\88\90å\8a\9f",
+       "loginsuccesstitle": "ã\83­ã\82°ã\82¤ã\83³æ¸\88ã\81¿",
        "loginsuccess": "<strong>{{SITENAME}}に「$1」としてログインしました。</strong>",
        "nosuchuser": "「$1」という名前の利用者は見当たりません。\n利用者名では大文字と小文字を区別します。\n綴りが正しいことを確認するか、[[Special:UserLogin/signup|新たにアカウントを作成]]してください。",
        "nosuchusershort": "「$1」という名前の利用者は存在しません。\n綴りを確認してください。",
        "noemail": "利用者「$1」のメールアドレスは登録されていません。",
        "noemailcreate": "有効なメールアドレスを入力する必要があります。",
        "passwordsent": "新しいパスワードを「$1」に登録されたメールアドレスにお送りしました。\nメールが届いたら、再度ログインしてください。",
-       "blocked-mailpassword": "ã\81\94使ç\94¨ä¸­ã\81®IPã\82¢ã\83\89ã\83¬ã\82¹ã\81\8bã\82\89ã\81®ç·¨é\9b\86ã\81¯ã\83\96ã\83­ã\83\83ã\82¯ã\81\95ã\82\8cã\81¦ã\81\8aã\82\8aã\80\81ä¸\8dæ­£å\88©ç\94¨é\98²æ­¢ã\81®ã\81\9fã\82\81ã\80\81ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\81®å\86\8dç\99ºè¡\8cæ©\9fè\83½ã\81¯使用できません。",
+       "blocked-mailpassword": "ã\81\94使ç\94¨ä¸­ã\81®IPã\82¢ã\83\89ã\83¬ã\82¹ã\81\8bã\82\89ã\81®ç·¨é\9b\86ã\81¯ã\83\96ã\83­ã\83\83ã\82¯ã\81\95ã\82\8cã\81¦ã\81\8aã\82\8aã\81¾ã\81\99ã\80\82ä¸\8dæ­£å\88©ç\94¨é\98²æ­¢ã\81®ã\81\9fã\82\81ã\80\81ã\81\93ã\81®IPã\82¢ã\83\89ã\83¬ã\82¹ã\81\8bã\82\89ã\81¯ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\81®å\86\8dç\99ºè¡\8cæ©\9fè\83½ã\81\8c使用できません。",
        "eauthentsent": "指定したメールアドレスに、アドレス確認のためのメールをお送りしました。\nメールに記載された手順に従って、このアカウントの所有者であることの確認が取れると、このアカウント宛のメールを受け取れるようになります。",
        "throttled-mailpassword": "パスワード再設定メールを過去 {{PLURAL:$1|$1 時間}}に送信済みです。\n悪用防止のため、パスワードの再設定は {{PLURAL:$1|$1 時間}}に 1 回のみです。",
        "mailerror": "メールを送信する際にエラーが発生しました: $1",
        "botpasswords-insert-failed": "ボット「$1」の追加に失敗しました。既に追加されていないか確認してください。",
        "botpasswords-update-failed": "ボット「$1」の更新に失敗しました。削除されていないか確認してください。",
        "botpasswords-created-title": "ボット用パスワードが作成されました",
-       "botpasswords-created-body": "ボット「$1」のパスワードが作成されました。",
+       "botpasswords-created-body": "利用者「$2」のボット名「$1」のためのパスワードが作成されました。",
        "botpasswords-updated-title": "ボット用パスワードが更新されました",
-       "botpasswords-updated-body": "ボット「$1」のパスワードを更新しました。",
+       "botpasswords-updated-body": "利用者「$2」のボット名「$1」のためのパスワードが更新されました。",
        "botpasswords-deleted-title": "ボット用パスワードが削除されました",
-       "botpasswords-deleted-body": "ボット「$1」のパスワードを削除しました。",
+       "botpasswords-deleted-body": "利用者「$2」のボット名「$1」のためのパスワードが削除されました。",
        "botpasswords-newpassword": "<strong>$1</strong> 用の新しいパスワードは <strong>$2</strong> です。 <em>後で参照するために、この情報を控えておいてください</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider が有効ではありません。",
        "botpasswords-invalid-name": "指定された利用者名には、ボット用パスワードの区切りである「$1」 が含まれていません。",
        "revdelete-submit": "選択された{{PLURAL:$1|版}}に適用",
        "revdelete-success": "版の閲覧レベルを更新しました。",
        "revdelete-failure": "版の閲覧レベルを更新できませんでした:\n$1",
-       "logdelete-success": "記録の閲覧レベルを変更しました。",
+       "logdelete-success": "記録の閲覧レベルを設定しました。",
        "logdelete-failure": "記録の閲覧レベルを設定できませんでした。\n$1",
        "revdel-restore": "閲覧レベルを変更",
        "pagehist": "ページの履歴",
        "recentchangeslinked-page": "ページ名:",
        "recentchangeslinked-to": "このページへのリンク元での変更の表示に切り替え",
        "recentchanges-page-added-to-category": "[[:$1]]をカテゴリに追加",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]]と他{{PLURAL:$2|1ページ|$2ページ}}をカテゴリに追加",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]]と他[[Special:WhatLinksHere/$1|{{PLURAL:$2|1ページ|$2ページ}}]]をカテゴリに追加",
        "recentchanges-page-removed-from-category": "[[:$1]]をカテゴリから除外",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]]と他{{PLURAL:$2|1ページ|$2ページ}}をカテゴリから除外",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]]と他 [[Special:WhatLinksHere/$1|{{PLURAL:$2|1ページ|$2ページ}}]]をカテゴリから除外",
        "autochange-username": "メディアウィキ自動変更",
        "upload": "ファイルをアップロード",
        "uploadbtn": "ファイルをアップロード",
        "rollback-success": "$1による編集を差し戻しました。\n$2による直前の版へ変更されました。",
        "sessionfailure-title": "セッションの失敗",
        "sessionfailure": "ログインのセッションに問題が発生しました。\nセッション乗っ取りを防ぐため、操作を取り消しました。\n前のページへ戻って再度読み込んだ後に、もう一度試してください。",
-       "changecontentmodel": "ã\83\9aã\83¼ã\82¸ã\81®ã\82³ã\83³ã\83\86ã\83³ã\83\88・モデルの変更",
+       "changecontentmodel": "ã\83\9aã\83¼ã\82¸ã\81®ã\82³ã\83³ã\83\86ã\83³ã\83\84・モデルの変更",
        "changecontentmodel-legend": "コンテンツモデルを変更",
        "changecontentmodel-title-label": "ページ名",
        "changecontentmodel-model-label": "新しい コンテンツ モデル",
        "changecontentmodel-reason-label": "理由:",
-       "changecontentmodel-success-title": "コンテント・モデルは変更されました",
-       "changecontentmodel-success-text": "[[:$1]]のコンテント・タイプは変更されています。",
+       "changecontentmodel-submit": "変更",
+       "changecontentmodel-success-title": "コンテンツ・モデルは変更されました",
+       "changecontentmodel-success-text": "[[:$1]]のコンテンツ・タイプは変更されました。",
        "changecontentmodel-cannot-convert": "[[:$1]]上のコンテントは$2の型には変換できません。",
        "changecontentmodel-nodirectediting": "$1 コンテント・モデルは、ダイレクト編集をサポートしていません。",
        "log-name-contentmodel": "コンテント・モデル変更記録",
-       "log-description-contentmodel": "ã\83\9aã\83¼ã\82¸ã\81®ã\82³ã\83³ã\83\86ã\83³ã\83\88ã\83»ã\83¢ã\83\87ã\83«ã\81«é\96¢é\80£ã\81\99ã\82\8bã\82¤ã\83\99ã\83³ã\83\88",
-       "logentry-contentmodel-change": "$1 ã\81\8cã\83\9aã\83¼ã\82¸ $3 ã\81®ã\82³ã\83³ã\83\86ã\83³ã\83\88・モデルを \"$4\" から \"$5\" に{{GENDER:$2|変更しました}}",
+       "log-description-contentmodel": "ã\83\9aã\83¼ã\82¸ã\81®ã\82³ã\83³ã\83\86ã\83³ã\83\84ã\83»ã\83¢ã\83\87ã\83«ã\81«é\96¢é\80£ã\81\99ã\82\8bå\87ºæ\9d¥äº\8b",
+       "logentry-contentmodel-change": "$1 ã\81\8cã\83\9aã\83¼ã\82¸ $3 ã\81®ã\82³ã\83³ã\83\86ã\83³ã\83\84・モデルを \"$4\" から \"$5\" に{{GENDER:$2|変更しました}}",
        "logentry-contentmodel-change-revertlink": "差し戻し",
        "logentry-contentmodel-change-revert": "差し戻し",
        "protectlogpage": "保護記録",
        "import-logentry-upload-detail": "$1{{PLURAL:$1|版}} をインポートしました",
        "import-logentry-interwiki-detail": "$2からインポート済みの$1{{PLURAL:$1|版}}",
        "javascripttest": "JavaScript をテスト中",
-       "javascripttest-pagetext-noframework": "このページは JavaScript のテストを実行するために予約されています。",
-       "javascripttest-pagetext-unknownframework": "テストフレームワーク「$1」は不明です。",
        "javascripttest-pagetext-unknownaction": "不明な操作「$1」。",
-       "javascripttest-pagetext-frameworks": "以下のテストフレームワークから1つ選択してください: $1",
-       "javascripttest-pagetext-skins": "テストを実行する外装を選択してください:",
        "javascripttest-qunit-intro": "mediawiki.org上の[$1 テストのドキュメント]を参照してください。",
        "tooltip-pt-userpage": "{{GENDER:|自分の利用者}}ページ",
        "tooltip-pt-anonuserpage": "自分が編集しているIPアドレスの利用者ページ",
        "version-libraries-description": "説明",
        "version-libraries-authors": "作者",
        "redirect": "ファイル名、利用者ID、ページID、版ID、記録IDでの転送",
-       "redirect-legend": "ファイルまたはページヘの転送",
        "redirect-summary": "この特別ページは、ファイル (ファイル名を指定)、ページ (版 ID またはページ ID を指定)、利用者ページ (利用者 ID を整数で指定) 、記録項目 (記録 ID を指定) に転送されます。使用例: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], [[{{#Special:Redirect}}/logid/186]]",
        "redirect-submit": "実行",
        "redirect-lookup": "検索の種類:",
        "tags-delete-not-allowed": "拡張機能によって定義されているタグは削除できません(ただし拡張機能が明示的に削除を許可している場合を除く)。",
        "tags-delete-not-found": "タグ「$1」は存在しません。",
        "tags-delete-too-many-uses": "タグ「$1」は少なくとも$2版に付与されており、削除できません。",
-       "tags-delete-warnings-after-delete": "ã\82¿ã\82°ã\80\8c$1ã\80\8dã\81®å\89\8aé\99¤ã\81«æ\88\90å\8a\9fã\81\97ã\81¾ã\81\97ã\81\9fã\81\8cã\80\81以ä¸\8bã\81®{{PLURAL:$2|è­¦å\91\8a}}ã\81\8cç\99ºç\94\9fã\81\97ã\81¾ã\81\97ã\81\9fï¼\9a",
+       "tags-delete-warnings-after-delete": "タグ「$1」の削除しましたが、以下の{{PLURAL:$2|警告}}が発生しました:",
        "tags-activate-title": "タグの有効化",
        "tags-activate-question": "タグ「$1」を有効化しようとしています。",
        "tags-activate-reason": "理由:",
        "tags-edit-reason": "理由:",
        "tags-edit-revision-submit": "変更を {{PLURAL:$1|this revision|$1 revisions}} に適用",
        "tags-edit-logentry-submit": "変更を {{PLURAL:$1|this log entry|$1 log entries}} に適用",
-       "tags-edit-success": "変更が正常に適用されました。",
+       "tags-edit-success": "変更が適用されました。",
        "tags-edit-failure": "変更は適用できませんでした: $1",
        "tags-edit-nooldid-title": "無効な対象版",
        "tags-edit-nooldid-text": "この関数を実行しましたが、対象の版が指定されていない、あるいは指定された版が存在しません。",
        "logentry-protect-protect-cascade": "$1 が $3 を {{GENDER:$2|保護}}しました $4 [カスケード]",
        "logentry-protect-modify": "$1 が $3 の保護レベルを{{GENDER:$2|変更}}しました $4",
        "logentry-protect-modify-cascade": "$1 が $3 の保護レベルを{{GENDER:$2|変更}}しました $4 [カスケード]",
-       "logentry-rights-rights": "$1 が $3 の所属グループを $4 から $5 に{{GENDER:$2|変更しました}}",
+       "logentry-rights-rights": "$1 が {{GENDER:$3|$3}} の所属グループを $4 から $5 に{{GENDER:$2|変更しました}}",
        "logentry-rights-rights-legacy": "$1 が $3 の所属グループを{{GENDER:$2|変更しました}}",
        "logentry-rights-autopromote": "$1 が $4 から $5 に自動的に{{GENDER:$2|昇格しました}}",
        "logentry-upload-upload": "$1 が $3 を {{GENDER:$2|アップロードしました}}",
        "special-characters-group-ipa": "国際音声記号",
        "special-characters-group-symbols": "記号",
        "special-characters-group-greek": "ギリシア文字",
+       "special-characters-group-greekextended": "ギリシア文字拡張",
        "special-characters-group-cyrillic": "キリル文字",
        "special-characters-group-arabic": "アラビア文字",
        "special-characters-group-arabicextended": "アラビア文字拡張",
        "mw-widgets-titleinput-description-redirect": "$1 へのリダイレクト",
        "api-error-blacklisted": "他の、説明的なタイトルをお選びください。",
        "sessionprovider-generic": "$1 セッション",
-       "randomrootpage": "おまかせルートページ"
+       "randomrootpage": "おまかせルートページ",
+       "log-action-filter-block": "ブロックの種類",
+       "log-action-filter-protect": "保護の種類:",
+       "log-action-filter-upload": "アップロードの種類",
+       "log-action-filter-all": "すべて",
+       "log-action-filter-block-block": "ブロック",
+       "log-action-filter-block-reblock": "ブロック変更",
+       "log-action-filter-block-unblock": "ブロック解除",
+       "log-action-filter-delete-delete": "ページの削除",
+       "log-action-filter-delete-restore": "ページの復帰",
+       "log-action-filter-protect-protect": "保護",
+       "log-action-filter-protect-modify": "保護の設定変更",
+       "log-action-filter-protect-unprotect": "保護解除",
+       "log-action-filter-upload-upload": "新規アップロード",
+       "log-action-filter-upload-overwrite": "再アップロード"
 }
index 264a219..a8fd122 100644 (file)
@@ -8,7 +8,8 @@
                        "Ælsån",
                        "Midnight Gambler",
                        "아라",
-                       "Jyllanj"
+                       "Jyllanj",
+                       "Ghiutun"
                ]
        },
        "tog-underline": "Unjestreg henwisnenge:",
        "thumbnail-more": "Forstör",
        "thumbnail_error": "Fejl we oprettels å thumbnail: $1",
        "importlogpage": "Importlogg",
-       "tooltip-pt-userpage": "Din brugesiid",
-       "tooltip-pt-mytalk": "Din diskusjonssiid",
-       "tooltip-pt-preferences": "Din instellenge",
+       "tooltip-pt-userpage": "{{GENDER:|Din brugesiid}}",
+       "tooltip-pt-mytalk": "{{GENDER:|Din}} diskusjonssiid",
+       "tooltip-pt-preferences": "{{GENDER:|Din}} instellenge",
        "tooltip-pt-watchlist": "Listen öwe side som du öwewåge for øndrenge",
-       "tooltip-pt-mycontris": "List öwe din bidraw",
+       "tooltip-pt-mycontris": "List öwe {{GENDER:|din}} bidraw",
        "tooltip-pt-login": "Du opfordas te å logg på, men dä ä ett obligatorisk.",
        "tooltip-pt-logout": "Logg å",
        "tooltip-pt-createaccount": "Du opfordas te å oprett e konto å logg på, men dä ä ett obligatorisk",
        "tooltip-t-whatlinkshere": "En list mä åll side som henwise hertil",
        "tooltip-t-recentchangeslinked": "Siensti øndrenge i side som denn siid henwise til",
        "tooltip-feed-atom": "Atom-feed for siden",
-       "tooltip-t-contributions": "Sie bidrawen te brugari",
+       "tooltip-t-contributions": "List öwe bidrawen te {{GENDER:$1|brugari}}",
        "tooltip-t-emailuser": "Senj i e-mail te brugari",
        "tooltip-t-upload": "Lägg e bilj elle i ånj mediafil op",
        "tooltip-t-specialpages": "List öwe åll specialside",
index 334f83c..b76c486 100644 (file)
@@ -25,7 +25,8 @@
                        "Macofe",
                        "SHOTHA",
                        "Gi777ga",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Sopopruidze"
                ]
        },
        "tog-underline": "ბმულების ხაზგასმა:",
        "myprivateinfoprotected": "თქვენ არ გაქვთ თქვენი პირადი ინფორმაციის შეცვლის ნებართვა.",
        "mypreferencesprotected": "თქვენ არ გაქვთ თქვენი კონფიგურაციის შეცვლის ნებართვა.",
        "ns-specialprotected": "გვერდების რედაქტირება სახელთა სივრცეში {{ns:special}} შეუძლებელია.",
-       "titleprotected": "á\83¨á\83\94á\83\9bá\83\93á\83\94á\83\92á\83\98 á\83\92á\83\95á\83\94á\83 á\83\93á\83\98á\83¡ á\83¨á\83\94á\83¥á\83\9bá\83\9cá\83\90 á\83\90á\83\99á\83 á\83«á\83\90á\83\9aá\83£á\83\9aá\83\98á\83\90 á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\94á\83\9a [[User:$1|$1]]-ს მიერ.\nმოცემულია შემდეგი ახსნა: <em>$2</em>.",
+       "titleprotected": "á\83¨á\83\94á\83\9bá\83\93á\83\94á\83\92á\83\98 á\83¡á\83\90á\83\97á\83\90á\83£á\83 á\83\98á\83¡ á\83¨á\83\94á\83¥á\83\9bá\83\9cá\83\90 á\83\90á\83\99á\83 á\83«á\83\90á\83\9aá\83£á\83\9aá\83\98á\83\90 á\83\9bá\83\9dá\83\9bá\83®á\83\9bá\83\90á\83 á\83\94á\83\91á\83\94á\83\9a [[User:$1|$1]]-á\83\98ს მიერ.\nმოცემულია შემდეგი ახსნა: <em>$2</em>.",
        "filereadonlyerror": "ფაილის \"$1\" შეცვლა ვერ ხერხდება, რადგანაც ფაილის საცავი \"$2\" მხოლოდ კითხვის რეჟიმშია.\n\nსისტემურმა ადმინისტრატორმა, რომელმაც ის დაბლოკა, მოიყვანა შემდეგი მიზეზი: \"$3\".",
        "invalidtitle-knownnamespace": "დაუშვებელი სათაური სახელთა სივრცე \"$2\" და ტექსტი \"$3\"-თან",
        "invalidtitle-unknownnamespace": "დაუშვებელი სათაური უცნობი სახელთა სივრცის ნომერი $1 და ტექსტი \"$2\"-ით",
        "badretype": "თქვენს მიერ შეყვანილი პაროლები ერთმანეთს არ ემთხვევა.",
        "usernameinprogress": "ამ მომხმარებლისათვის ანგარიში იქმნება. გთხოვთ, დაიცადეთ.",
        "userexists": "ეს სახელი უკვე გამოყენებულია.\nგთხოვთ, აირჩიეთ სხვა.",
-       "loginerror": "á\83¨á\83\94á\83ªá\83\93á\83\9dá\83\9bá\83\90 á\83\90á\83\95á\83¢á\83\9dá\83 á\83\98á\83\96á\83\90á\83ªá\83\98á\83\98á\83¡á\83\90á\83¡",
+       "loginerror": "á\83\90á\83\95á\83¢á\83\9dá\83 á\83\98á\83\96á\83\90á\83ªá\83\98á\83\98á\83¡ á\83¨á\83\94á\83ªá\83\93á\83\9dá\83\9bá\83\90",
        "createacct-error": "ანგარიშის შექმნის შეცდომა",
        "createaccounterror": "$1 ანგარიშის შექმნა ვერ მოხერხდა.",
        "nocookiesnew": "მომხმარებლის ჩანაწერი შექმნილია, მაგრამ თქვენ არ გაგივლიათ რეგისტრაცია. {{SITENAME}} იყენებს cookies, რომლებიც თქვენს ბრაუზერში გათიშულია. გთხოვთ, აამოქმედოთ ისინი და შემდგომ ხელახლა გაიარეთ რეგისტრაცია.",
        "nocookiesfornew": "მომხმარებლის ანგარიში არ შექმნილა, რადგან მისი წყარო ვერ დადასტურდა.\nუზრუნველყოფილი უნდა იყოს ჭდეების აქტიურობა. შემდეგ განაახლეთ გვერდი და სცადეთ ხელახლა",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "თქვენს მიერ მითითებული მომხმარებლის სახელი ქმედითი არ არის.",
-       "loginsuccesstitle": "სისტემაში შესვლა განხორციელდა.",
+       "loginsuccesstitle": "სისტემაში შესვლა განხორციელდა",
        "loginsuccess": "'''ამჟამად შესული ხართ {{SITENAME}}-ში როგორც „$1“.'''",
        "nosuchuser": "მომხმარებელი სახელად $1 არ არსებობს.\nმომხმარებელთა სახელები გრძნობადია ასოების რეგისტრამდე..\nშეამოწმეთ სახელის დაწერა ან[[Special:UserLogin/signup|შექმენით ახალი ანგარიში]].",
        "nosuchusershort": "მომხმარებელი სახელით „$1“ არ არსებობს. შეამოწმეთ მართლწერა.",
        "createaccount-title": "ანგარიშის შექმნა {{SITENAME}}-თვის",
        "createaccount-text": "ვიღაცამ შექმნა ანგარიში სახელით „$2“ და პაროლით „$3“ თქვენი ელექტრონული ფოსტისთვის {{SITENAME}}-ში ($4). გთხოვთ დარეგისტრირდეთ და შეცვალოთ პაროლი.\n\nშეგიძლიათ ყურადღება არ მიაქციოთ ამ შეტყობინებას, თუ ანგარიში შეცდომით შეიქმნა.",
        "login-throttled": "You have made too many recent login attempts.\nPlease wait $1 before trying again.",
-       "login-abort-generic": "á\83\97á\83¥á\83\95á\83\94á\83\9cá\83\98 á\83\90á\83\95á\83¢á\83\9dá\83 á\83\98á\83\96á\83\90á\83ªá\83\98á\83\90 á\83¬á\83\90á\83 á\83£á\83\9bá\83\90á\83¢á\83\94á\83\91á\83\94á\83\9aá\83\98ა – გაუქმდა",
+       "login-abort-generic": "á\83\97á\83¥á\83\95á\83\94á\83\9cá\83\98 á\83\90á\83\95á\83¢á\83\9dá\83 á\83\98á\83\96á\83\90á\83ªá\83\98á\83\90 á\83\95á\83\94á\83  á\83\92á\83\90á\83\9cá\83®á\83\9dá\83 á\83ªá\83\98á\83\94á\83\9aá\83\93ა – გაუქმდა",
        "login-migrated-generic": "თქვენი ანგარიში გადატანილი იქნა, და თქვენი მომხმარებლის სახელი ამ ვიკიში აღარ არსებობს.",
        "loginlanguagelabel": "ენა: $1",
        "suspicious-userlogout": "თქვენი მოთხოვნა გასვლის შესახებ გაუქმებულია, რადგანაც იგი გავს ქეშირებადი პროქსის ან არაკორექტული ბრაუზერის მოთხოვნას.",
        "newpassword": "ახალი პაროლი:",
        "retypenew": "ახალი პაროლი განმეორებით:",
        "resetpass_submit": "მიუთითეთ პაროლი და დარეგისტრირდით",
-       "changepassword-success": "á\83\97á\83¥á\83\95á\83\94á\83\9cá\83\98 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98 á\83¬á\83\90á\83 á\83\9bá\83\90á\83¢á\83\94á\83\91á\83\98á\83\97 á\83¨á\83\94á\83\98á\83ªá\83\95á\83\90á\83\9aá\83\90!",
+       "changepassword-success": "თქვენი პაროლი შეიცვალა!",
        "changepassword-throttled": "თქვენ განახორციელეთ ანგარიშში შესვლის ზედმეტად ბევრი მცდელობა. გამორებით შეყვანამდე გთხოვთ დაიცადოთ $1.",
        "botpasswords": "ბოტის პაროლები",
        "botpasswords-summary": "<em>ბოტების კოდები</em> საშუალებას იძლევა მომხმარებლის ანგარიშთან დაკავშირების API-ის გამოყენებით ანგარიშის ძირითადი შესვლის მონაცემების გამოყენების გარეშე. მომხმარებლის უფლებები ასეთი შესვლისას შესაძლოა შეზღუდული იყოს.\n\nთუ არ იცით ეს რატომ უნდა გააკეთოთ, ალბათ არც უნდა გააკეთოთ. ასეთი კოდის წამოქმნა და სხვისთვის გადაცემა არაა რეკომენდირებული.",
        "botpasswords-insert-failed": "ბოტის სახელის $1\" დამატება შეუძლებელია. უკვე დამატებულია?",
        "botpasswords-update-failed": "ბოტის სახელის \"$1\" განახლება შეუძლებელია. წაშლილია?",
        "botpasswords-created-title": "ბოტის პაროლი შექმნილია",
-       "botpasswords-created-body": "ბოტის პაროლი \"$1\" წარმატებით შეიქმნა.",
+       "botpasswords-created-body": "ბოტის პაროლი მომხმარებელ \"$2\"-ის \"$1\" სახელისთვის შეიქმნა.",
        "botpasswords-updated-title": "ბოტის პაროლი განახლდა",
-       "botpasswords-updated-body": "ბოტის პაროლი \"$1\" წარმატებით განახლდა.",
+       "botpasswords-updated-body": "ბოტის პაროლი \"$2\" მომხმარებლის \"$1\"-ის სახელისთვის განახლდა.",
        "botpasswords-deleted-title": "ბოტის პაროლი წაშლილია",
-       "botpasswords-deleted-body": "ბოტის პაროლი \"$1\" წაიშალა.",
+       "botpasswords-deleted-body": "ბოტის პაროლი \"$2\" მომხმარებლის \"$1\"-ის სახელისთვის წაიშალა.",
        "botpasswords-newpassword": "ახალი პაროლი <strong>$1</strong>-ით შესასვლელად არის <strong>$2</strong>. <em>გთხოვთ დაიმახსოვრეთ ან ჩაიწერეთ.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider არ არის ხელმისაწვდომი.",
        "botpasswords-restriction-failed": "ბოტის პაროლის შეზღუდვები არ უშვებს ამ ავტორიზაციას.",
        "resetpass-no-info": "კონკრეტულად ამ გვერდთან სამუშაოდ თქვენ უნდა წარადგინოთ თავი სისტემისადმი.",
        "resetpass-submit-loggedin": "პაროლის შეცვლა",
        "resetpass-submit-cancel": "გაუქმება",
-       "resetpass-wrong-oldpass": "á\83\90á\83 á\83\90á\83¡á\83¬á\83\9dá\83 á\83\98 á\83\93á\83 á\83\9dá\83\94á\83\91á\83\98á\83\97á\83\98 á\83\90á\83\9c á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\98 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98.\ná\83¨á\83\94á\83¡á\83\90á\83«á\83\9aá\83\9dá\83\90 á\83\97á\83¥á\83\95á\83\94á\83\9c á\83¬á\83\90á\83 á\83\9bá\83\90á\83¢á\83\94á\83\91á\83\98á\83\97 á\83¨á\83\94á\83ªá\83\95á\83\90á\83\9aá\83\94á\83\97 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98 á\83\90á\83\9c á\83\9bá\83\9dá\83\98á\83\97á\83®á\83\9dá\83\95á\83\94á\83\97 á\83\90á\83®á\83\90ლი.",
+       "resetpass-wrong-oldpass": "á\83\90á\83 á\83\90á\83¡á\83¬á\83\9dá\83 á\83\98 á\83\93á\83 á\83\9dá\83\94á\83\91á\83\98á\83\97á\83\98 á\83\90á\83\9c á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\98 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98.\ná\83¨á\83\94á\83¡á\83\90á\83«á\83\9aá\83\9dá\83\90 á\83\97á\83¥á\83\95á\83\94á\83\9c á\83£á\83\99á\83\95á\83\94 á\83¨á\83\94á\83ªá\83\95á\83\90á\83\9aá\83\94á\83\97 á\83\9eá\83\90á\83 á\83\9dá\83\9aá\83\98 á\83\90á\83\9c á\83\9bá\83\9dá\83\98á\83\97á\83®á\83\9dá\83\95á\83\94á\83\97 á\83\90á\83®á\83\90á\83\9aá\83\98 á\83\93á\83 á\83\9dá\83\94á\83\91á\83\98á\83\97á\83\98 á\83\9eá\83\90á\83 á\83\9dლი.",
        "resetpass-recycled": "გთხოვთ, შეცვალეთ პაროლი იმაზე, რომელიც განსხვავდება თქვენი მიმდინარე პაროლისაგან.",
        "resetpass-temp-emailed": "თქვენ წარდგენილი ხართ დროებითი პაროლის დახმარებით, რომელიც მიღებულია ელექტრონული ფოსტით. სისტემაში შესვლის დასრულებისთვის, აუცილებელია ახალი პაროლის წარდგენა:",
        "resetpass-temp-password": "დროებითი პაროლი:",
        "revdelete-unsuppress": "მოხსენით შეზღუდვა ვერსიების აღდგენისგან",
        "revdelete-log": "მიზეზი:",
        "revdelete-submit": "{{PLURAL:$1|არჩეული ვერსიის|არჩეული ვერსიების}} განხორციელება",
-       "revdelete-success": "'''ვერსიის ხილვადობა შეიცვალა.'''",
+       "revdelete-success": "გადახედვის ხილვადობა განახლებულია.",
        "revdelete-failure": "'''ვერსიის ხილვადობა არ შეიძლება დაყენებული იქნას:'''\n$1",
-       "logdelete-success": "á\83\9bá\83\9dá\83\95á\83\9aá\83\94á\83\9cá\83\98á\83¡ á\83®á\83\98á\83\9aá\83\95á\83\90á\83\93á\83\9dá\83\91á\83\90 á\83¬á\83\90á\83 á\83\9bá\83\90á\83¢á\83\94á\83\91á\83\98á\83\97 á\83¨á\83\94á\83\98á\83ªá\83\95á\83\90á\83\9aá\83\90.",
+       "logdelete-success": "á\83\9bá\83\9dá\83\95á\83\9aá\83\94á\83\9cá\83\98á\83¡ á\83®á\83\98á\83\9aá\83\95á\83\90á\83\93á\83\9dá\83\91á\83\98á\83¡ á\83®á\83\94á\83\9aá\83¡á\83\90á\83¬á\83§á\83\9d.",
        "logdelete-failure": "'''ჟურნალის ხილვადობა არ არის დაყენებული:'''\n$1",
        "revdel-restore": "ხილვადობის შეცვლა",
        "pagehist": "გვერდის ისტორია",
        "userrights-unchangeable-col": "ჯგუფები, რომლებიც არ შეგიძლიათ შეცვალოთ",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "მომხმარებელთა უფლებების კონფლიქტი! გთხოვთ ხელმეორედ შეინახოთ თქვენი ცვლილებები.",
-       "userrights-removed-self": "á\83\97á\83¥á\83\95á\83\94á\83\9c á\83¬á\83\90á\83 á\83\9bá\83\90á\83¢á\83\94á\83\91á\83\98á\83\97 á\83¬á\83\90á\83¨á\83\90á\83\9aá\83\94á\83\97 á\83¡á\83\90á\83\99á\83£á\83\97á\83\90á\83 á\83\98 á\83£á\83¤á\83\9aá\83\94á\83\91á\83\90. á\83¨á\83\94á\83¡á\83\90á\83\91á\83\90á\83\9bá\83\98á\83¡á\83\90á\83\93, á\83\97á\83¥á\83\95á\83\94á\83\9c á\83\90á\83¦á\83\90á\83  á\83\92á\83\94á\83¥á\83\9cá\83\94á\83\91á\83\90á\83\97 á\83\90á\83\9b á\83\92á\83\95á\83\94á\83 á\83\93á\83\97á\83\90á\83\9c á\83¬á\83\95á\83\93á\83\9dá\83\9bá\83\98á\83¡ á\83¡á\83\90á\83¨á\83£á\83\90á\83\9aá\83\94á\83\91á\83\90",
+       "userrights-removed-self": "თქვენ წაშალეთ საკუთარი უფლება. შესაბამისად, თქვენ აღარ გექნებათ ამ გვერდთან წვდომის საშუალება",
        "group": "ჯგუფი:",
        "group-user": "მომხმარებლები",
        "group-autoconfirmed": "ავტომატურად დადასტურებული მომხმარებლები",
        "recentchangeslinked-page": "გვერდის დასახელება:",
        "recentchangeslinked-to": "საპირისპიროდ აჩვენეთ ამ გვერდზე ბმულის მქონე გვერდების ცვლილებები",
        "recentchanges-page-added-to-category": "[[:$1]] დამატებულია კატეგორიაში",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] და {{PLURAL:$2|ერთი გვერდი|$2 გვერდი}} დამატებულია კატეგორიაში",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] და [[Special:WhatLinksHere/$1|{{PLURAL:$2|ერთი გვერდი|$2 გვერდი}}]] დამატებულია კატეგორიაში",
        "recentchanges-page-removed-from-category": "[[:$1]] წაიშალა კატეგორიიდან",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] და {{PLURAL:$2|ერთი გვერდი|$2 გვერდი}} წაიშალა კატეგორიიდან",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] და [[Special:WhatLinksHere/$1|{{PLURAL:$2|ერთი გვერდი|$2 გვერდი}}]] წაიშალა კატეგორიიდან",
        "autochange-username": "მედიავიკის ავტომატური ცვლილება",
        "upload": "ფაილის დამატება",
        "uploadbtn": "ფაილის დამატება",
        "backend-fail-read": "ფაილი $1-ის წაკითხვა ვერ მოხერხდა.",
        "backend-fail-create": "ფაილი $1-ის ჩაწერა ვერ მოხერხდა.",
        "backend-fail-maxsize": "ფაილი $1-ის ჩაწერა ვერ მოხერხდა, რადგანაც მისი ზომა აჭარბებს {{PLURAL:$2|ერთ ბაიტს|$2 ბაიტს}}.",
-       "backend-fail-readonly": "საცავი \"$1\" ამჟამად ხელმისაწვდომია მხოლოდ წაკითხვის რეჟიმში. მიზეზი: \"$2\"",
+       "backend-fail-readonly": "საცავი \"$1\" ამჟამად ხელმისაწვდომია მხოლოდ წაკითხვის რეჟიმში. მიზეზი: <em>$2</em>",
        "backend-fail-synced": "ფაილი \"$1\" იმყოფება შიდა საცავის შეუთანხმებელ მდგომარეობაში",
        "backend-fail-connect": "\"$1\" საცავთან დაკავშირება ვერ მოხერხდა.",
        "backend-fail-internal": "\"$1\" საცავში მოხდა დაუდგენელი შეცდომა.",
        "uploadstash-summary": "ამ გვერდზე შესაძლებელია იმ ფაილთა მოძიება, რომლებიც უკვე აიტვირთნენ ან ახლა იტვირთებინ, მაგრამ ჯერ ვიკიში არ გამოქვეყნებულან. ეს ფაილები, გარდა ამტვირთავი მომხმარებლისა, ჯერ საჯაროდ არავის უნახავს.",
        "uploadstash-clear": "დაფარული ფაილების გასუფთავება",
        "uploadstash-nofiles": "თქვენ არ გაქვთ დაფარული ფაილები.",
-       "uploadstash-badtoken": "á\83\9bá\83\98á\83\97á\83\98á\83\97á\83\94á\83\91á\83£á\83\9aá\83\98 á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\94á\83\91á\83\90 á\83\95á\83\94á\83  á\83¨á\83\94á\83¡á\83 á\83£á\83\9aá\83\93á\83\90. á\83¨á\83\94á\83¡á\83\90á\83«á\83\9aá\83\9dá\83\90, á\83\97á\83¥á\83\95á\83\94á\83\9cá\83\98 á\83£á\83¡á\83\90á\83¤á\83 á\83\97á\83®á\83\9dá\83\94á\83\91á\83\98á\83¡ á\83\9bá\83\90á\83\9cá\83\93á\83\90á\83¢á\83\98á\83¡ á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\94á\83\91á\83\98á\83¡ á\83\95á\83\90á\83\93á\83\90 á\83\90á\83\9bá\83\9dá\83\98á\83¬á\83£á\83 á\83\90. á\83\99á\83\98á\83\93á\83\94á\83\95 á\83¡á\83ªá\83\90á\83\93á\83\94á\83\97.",
+       "uploadstash-badtoken": "á\83\9bá\83\98á\83\97á\83\98á\83\97á\83\94á\83\91á\83£á\83\9aá\83\98 á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\94á\83\91á\83\90 á\83\95á\83\94á\83  á\83¨á\83\94á\83¡á\83 á\83£á\83\9aá\83\93á\83\90. á\83¨á\83\94á\83¡á\83\90á\83«á\83\9aá\83\9dá\83\90, á\83 á\83\94á\83\93á\83\90á\83¥á\83¢á\83\98á\83 á\83\94á\83\91á\83\98á\83¡ á\83£á\83¤á\83\9aá\83\94á\83\91á\83\90á\83\9bá\83\9dá\83¡á\83\98á\83\9aá\83\94á\83\91á\83\98á\83¡ á\83\9bá\83\9dá\83¥á\83\9bá\83\94á\83\93á\83\94á\83\91á\83\98á\83¡ á\83\95á\83\90á\83\93á\83\90 á\83\90á\83\9bá\83\9dá\83\98á\83¬á\83£á\83 á\83\90. á\83\92á\83\97á\83®á\83\9dá\83\95á\83\97, á\83¡á\83ªá\83\90á\83\93á\83\94á\83\97 á\83\97á\83\90á\83\95á\83\98á\83\93á\83\90á\83\9c.",
        "uploadstash-errclear": "ფაილების გასუფთავება ვერ მოხერხდა.",
        "uploadstash-refresh": "ფაილების სიის განახლება",
        "invalid-chunk-offset": "არასწორი საწყისი წერტილი",
        "delete-toobig": "ამ გვერდს ძალიან გრძელი ისტორია გააჩნია,  $1 {{PLURAL:$1|ვერსიაზე|ვერსიიებზე|ვერსიებზე}} მეტი. მისი წაშლა აიკრძალა {{SITENAME}}-ის კორექტურად მუშაობის უზრუნველყოფისთვის.",
        "delete-warning-toobig": "ამ გვერდს ძალიან გრძელი ისტორია გააჩნია,  $1 {{PLURAL:$1|ვერსიაზე|ვერსიიებზე|ვერსიებზე}} მეტი.\nმისმა წაშლამ შესაძლოა გამოიწვიოს საიტის მონაცემთა ბაზის  {{SITENAME}} არაკორექტული მუშაობა;\nიმოქმედეთ სიფრთხილით.",
        "deleteprotected": "თქვენ არ შეგიძლიათ ამ გვერდის წაშლა, რადგან ის დაცულია.",
-       "deleting-backlinks-warning": "'''გაფრთხილება:'''  [[Special:WhatLinksHere/{{FULLPAGENAME}}|სხვა გვერდები]] დაკავშირებულია ამ წასაშლელ გვერდთან.",
+       "deleting-backlinks-warning": "<strong>გაფრთხილება:</strong> [[Special:WhatLinksHere/{{FULLPAGENAME}}|სხვა გვერდები]] დაკავშირებულია ამ წასაშლელ გვერდთან.",
        "rollback": "ცვლილებების გაუქმება",
        "rollbacklink": "სწრაფი გაუქმება",
        "rollbacklinkcount": "$1 {{PLURAL:$1|ცვლილების|ცვლილების}} გაუქმება",
        "changecontentmodel-title-label": "გვერდის სათაური",
        "changecontentmodel-model-label": "შინაარსის ახალი მოდელი",
        "changecontentmodel-reason-label": "მიზეზი:",
+       "changecontentmodel-submit": "შეცვლა",
        "changecontentmodel-success-title": "შინაარსის მოდელი შეიცვალა",
        "changecontentmodel-success-text": "[[:$1]]-ის კონტენტის ტიპი შეიცვალა.",
        "changecontentmodel-cannot-convert": "[[:$1]]-ის შინაარსის $2-ის ტიპზე კონვერტაცია შეუძლებელია.",
        "changecontentmodel-nodirectediting": "$1 შინაარსის მოდელს არ აქვს პირდაპირი რედაქტირების მხარდაჭერა",
        "log-name-contentmodel": "შინაარსის მოდელის შეცვლის ჟურნალი",
        "log-description-contentmodel": "გვერდის შინაარსის მოდელთან დაკავშირებული მოვლენები",
+       "logentry-contentmodel-new": "$1-მ {{GENDER:$2|შექმნა}} გვერდი $3, არა-სტანდარტული მოდელით \"$5\"",
        "logentry-contentmodel-change": "$1-მა {{GENDER:$2|შეცვალა}} $3-ის გვერდის შინაარსის მოდელი \"$4\"-დან \"$5\"-ზე",
        "logentry-contentmodel-change-revertlink": "დაბრუნება",
        "logentry-contentmodel-change-revert": "დაბრუნება",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|ვერსია|ვერსია}} იმპორტირებულია",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|ვერსია|ვერსია}} იმპორტირებულია $2-დან",
        "javascripttest": "JavaScript-ის ტესტირება",
-       "javascripttest-pagetext-noframework": "ეს გვერდი დარეგისტრირებულია JavaScript-ის ტესტების გასაშვებად.",
-       "javascripttest-pagetext-unknownframework": "„$1-ის“ ტესტირების უცნობი გარემო.",
        "javascripttest-pagetext-unknownaction": "უცნობი ქმედება „$1“.",
-       "javascripttest-pagetext-frameworks": "გთხოვთ, აირჩიეთ ტესტირების ერთ-ერთი შემდეგი გარემო: $1",
-       "javascripttest-pagetext-skins": "ტესტების გასაშვებად აირჩიეთ გაფორმების თემა:",
        "javascripttest-qunit-intro": "იხილეთ [$1 ტესტირების დოკუმენტები] mediawiki.org-ზე.",
        "tooltip-pt-userpage": "{{GENDER:|თქვენი მომხმარებლის}} გვერდი",
        "tooltip-pt-anonuserpage": "ჩემი IP-ის მქონე მომხმარებლის გვერდი",
        "confirm_purge_button": "კარგი",
        "confirm-purge-top": "გსურთ ამ გვერდის ქეშის წაშლა?",
        "confirm-purge-bottom": "ქეშის გაწმენდის შემდეგ იქნება ნაჩვენები ბოლო ვერსია.",
-       "confirm-watch-button": "á\83\99á\83\90á\83 á\83\92á\83\98",
+       "confirm-watch-button": "á\83\93á\83\98á\83\90á\83®",
        "confirm-watch-top": "დავამატო ეს გვერდი თქვენი კონტროლის სიას?",
-       "confirm-unwatch-button": "á\83\99á\83\90á\83 á\83\92á\83\98",
+       "confirm-unwatch-button": "á\83\93á\83\98á\83\90á\83®",
        "confirm-unwatch-top": "მოვხსნა ეს გვერდი თქვენი კონტროლის სიიდან?",
        "semicolon-separator": ";&#32;",
        "comma-separator": ",&#32;",
        "version-libraries-description": "აღწერა",
        "version-libraries-authors": "ავტორები",
        "redirect": "გადამისამართება ფაილიდან, მომხმარებლიდან, გვერდიდან, ვერსიის ან ავტორიზაციის იდენტიფიკატორიდან",
-       "redirect-legend": "გადამისამართება ფაილზე ან გვერდზე",
        "redirect-summary": "ეს დამხმარე გვერდი ამისამართებს ფაილზე (ფაილის სახელიდან) გვერდზე, (გვერდის ან ვერსიის იდენტიფიკატორიდან), მომხმარებლის გვერდზე (მომხმარებლის რაოდენობრივი იდენტიფიკატორიდან) ან ჟურნალის მონაცემზე. გამოყენება:\n[[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], or [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "მიდი",
        "redirect-lookup": "ძიება:",
        "tags-delete-not-allowed": "გაფართოებით განსაზღვრული ტეგები, არ შეიძლება იყოს წაშლილი, თუკი გაფართოება აშკარად არ იძლევა ამის გაკეთების შესაძლებლობას",
        "tags-delete-not-found": "აღნიშვნა „$1“ არ არსებობს.",
        "tags-delete-too-many-uses": "ტეგი \"$1\" მიღებულია $2 ვერსიებთან, რაც იმას ნიშნავს, რომ იგი არ შეიძლება იყოს წაშლილი",
-       "tags-delete-warnings-after-delete": "á\83¢á\83\94á\83\92á\83\98 â\80\9e$1â\80\9c á\83¬á\83\90á\83 á\83\9bá\83\90á\83¢á\83\94á\83\91á\83\98á\83\97 á\83\98á\83¥á\83\9cá\83\90 á\83¬á\83\90á\83¨á\83\9aá\83\98á\83\9aá\83\98, á\83\97á\83£á\83\9bá\83ªá\83\90 á\83\90á\83¦á\83\9bá\83\9dá\83©á\83\94á\83\9cá\83\98á\83\9aá\83\98 á\83\98á\83§á\83\9d á\83¨á\83\94á\83\9bá\83\93á\83\94á\83\92á\83\98 á\83¨á\83\94á\83¢á\83§á\83\9dá\83\91á\83\98á\83\9cá\83\94á\83\91á\83\90: $2",
+       "tags-delete-warnings-after-delete": "á\83¢á\83\94á\83\92á\83\98 â\80\9e$1â\80\9c á\83¬á\83\90á\83\98á\83¨á\83\90á\83\9aá\83\90, á\83\97á\83£á\83\9bá\83ªá\83\90 á\83\90á\83¦á\83\9bá\83\9dá\83©á\83\94á\83\9cá\83\98á\83\9aá\83\98á\83\90 á\83¨á\83\94á\83\9bá\83\93á\83\94á\83\92á\83\98 {{PLURAL:$2|á\83¨á\83\94á\83¢á\83§á\83\9dá\83\91á\83\98á\83\9cá\83\94á\83\91á\83\90\83¨á\83\94á\83¢á\83§á\83\9dá\83\91á\83\98á\83\9cá\83\94á\83\91á\83\94á\83\91á\83\98}}:",
        "tags-activate-title": "ტეგის გააქტიურება",
        "tags-activate-question": "თქვენ ცდილობთ დასათაურების გააქტიურებას „$1“.",
        "tags-activate-reason": "მიზეზი:",
        "tags-edit-revision-legend": "ტეგების დამატება ან წაშლა {{PLURAL:$1|ეს გადასინჯვა|ყველა $1 გადასინჯვა}}",
        "tags-edit-logentry-legend": "ტეგების დამატება ან წაშლა {{PLURAL:$1|ეს ჩანაწერი ჟურნალში|ყველა $1 ჟურნალის ჩანაწერი}}",
        "tags-edit-existing-tags": "არსებული დასათაურებები:",
-       "tags-edit-existing-tags-none": "''არა''",
+       "tags-edit-existing-tags-none": "<em>არცერთი</em>",
        "tags-edit-new-tags": "ახალი აღნიშვნა:",
        "tags-edit-add": "ამ აღნიშვნის დამატება:",
        "tags-edit-remove": "ამ აღნიშვნის წაშლა:",
        "tags-edit-reason": "მიზეზი:",
        "tags-edit-revision-submit": "ცვლილებების მიღება {{PLURAL:$1|ეს გადასინჯვა|$1 გადასინჯვები}}",
        "tags-edit-logentry-submit": "მიღებული ცვლილებები {{PLURAL:$1|ეს ჩანაწერია ჟურნალში|$1 ჩანაწერების ჟურნალი}}",
-       "tags-edit-success": "á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\94á\83\91á\83\98 á\83¬á\83\90á\83 á\83\9bá\83\90á\83¢á\83\94á\83\91á\83£á\83\9aá\83\90á\83\93 á\83\98á\83¥á\83\9cá\83\90 á\83\9bá\83\98á\83¦á\83\94á\83\91á\83£á\83\9aá\83\98",
+       "tags-edit-success": "á\83ªá\83\95á\83\9aá\83\98á\83\9aá\83\94á\83\91á\83\94á\83\91á\83\98 á\83\9bá\83\98á\83¦á\83\94á\83\91á\83£á\83\9aá\83\98á\83\90.",
        "tags-edit-failure": "ცვლილებები არ იქნა შენახული: $1",
        "tags-edit-nooldid-title": "არ არის მოცემული სამიზნე ვერსია",
        "tags-edit-nooldid-text": "ამ ფუნქციის შესასრულებლად თქვენ არ გაქვთ გაცემული სამიზნე ვერსია, ან მითითებული ვერსია არ არსებობს",
index 1a03e7f..8d9a6ad 100644 (file)
        "filemissing": "فائل نیکی",
        "thumbnail_error": "$1 څیق سایزو ھوٹو ساوزیکا مسئلہ",
        "tooltip-pt-userpage": "تہ صارفی صفحہ",
-       "tooltip-pt-mytalk": "تہ صفحۂ مشقولگی",
+       "tooltip-pt-mytalk": "{{GENDER:|تہ}} صفحۂ مشقولگی",
        "tooltip-pt-preferences": " تہ ترجیحات",
        "tooltip-pt-watchlist": "ھتے صفحاتن فہرست کہ ھتیتان تبدیلی تہ زیرِنظر شینی",
-       "tooltip-pt-mycontris": "تہ کاردو کورمان فہرست",
+       "tooltip-pt-mycontris": "{{GENDER:|تہ}} کاردو کورمان فہرست",
        "tooltip-pt-login": "تہ بچے داخلِ نوشتہ بیک جم شیر، لیکن ھیہ ضروری نو",
        "tooltip-pt-logout": "خارج بوس",
        "tooltip-pt-createaccount": "تتے دعوت دیونو بویان کہ کھاتہ ساوزاوے۔لیکن کھاتہ ساوزیک لازمی نو-",
        "tooltip-t-recentchangeslinked": "ھیہ صفحہو سوم مربوط صفحاتہ بیرو حالیہ تبدیلی",
        "tooltip-feed-rss": "ھیہ صفحو بچے اسس خورد",
        "tooltip-feed-atom": "ھیہ صفحو بچے آٹوم فیڈ",
-       "tooltip-t-contributions": "Ù\86Ù\88غ ØªØ¯Ù\88Û\8cÙ\86",
+       "tooltip-t-contributions": "Ù\85ضÙ\85Ù\88Ù\86Ù\86 Ù\84سٹ {{GENDER:$1|Ú¾Û\8cÛ\81 ØµØ§Ø±Ù\81}}Ù\88",
        "tooltip-t-emailuser": "ھیہ ممباروت بشلی کغاز(ای میل) انڅاوے",
        "tooltip-t-upload": "فائلو اپلوڈ کورے",
        "tooltip-t-specialpages": "سف خاص صفحاتن فہرست",
index 7c44420..0835680 100644 (file)
@@ -13,7 +13,8 @@
                        "아라",
                        "Macofe",
                        "Batyrbek.kz",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Сілтеменің астын сызу:",
        "october-date": "Қазан $1",
        "november-date": "Қараша $1",
        "december-date": "Желтоқсан $1",
+       "period-am": "Түстен бұрыңғы",
+       "period-pm": "Түстен кейінгі",
        "pagecategories": "{{PLURAL:$1|Санат|Санат}}",
        "category_header": "«$1» санатындағы беттер",
        "subcategories": "Санатшалар",
        "laggedslavemode": "<strong>Ескерту:</strong> Бетте жуықтағы жаңартулар болмауы мүмкін.",
        "readonly": "Дерекқоры құлыпталған",
        "enterlockreason": "Құлыптау себебін, қай уақытқа дейін құлыпталғанын кірістіріп, енгізіңіз.",
-       "readonlytext": "Ð\91ұл Ð´ÐµÑ\80екÒ\9bоÑ\80 Ð¶Ð°Ò£Ð°Ð´Ð°Ð½ Ð¶Ð°Ð·Ñ\83 Ð¶Ó\99не Ð±Ð°Ñ\81Ò\9bа Ó©Ð·Ð³ÐµÑ\80Ñ\96Ñ\81Ñ\82еÑ\80 Ð¶Ð°Ñ\81аÑ\83дан Ð°Ò\93Ñ\8bмда Ò\9bұлÑ\8bпÑ\82алÑ\8bнÒ\93ан, Ð¼Ò¯Ð¼ÐºÑ\96н ÐºÒ¯Ð½Ð´Ðµ-күн Ð´ÐµÑ\80екÒ\9bоÑ\80дÑ\8b Ð±Ð°Ð¿Ñ\82аÑ\83 Ò¯Ñ\88Ñ\96н, Ð±Ò±Ð½Ñ\8b Ð±Ñ\96Ñ\82Ñ\96Ñ\80геннен Ñ\81оң Ò\9bалÑ\8bпÑ\82Ñ\8b Ñ\96Ñ\81ке Ò\9bайÑ\82аÑ\80Ñ\8bладÑ\8b.\n\nÒ\9aұлÑ\8bпÑ\82аÒ\93ан Ó\99кÑ\96мÑ\88Ñ\96 Ð±Ò±Ð½Ñ\8b Ð±Ñ\8bлай Ñ\82Ò¯Ñ\81Ñ\96ндÑ\96Ñ\80едÑ\96: $1",
+       "readonlytext": "Ð\9cүмкÑ\96н Ð¶Ð¾Ñ\81паÑ\80лÑ\8b Ð´ÐµÑ\80екÒ\9bоÑ\80 Ñ\82екникалÑ\8bÒ\9b Ò\9bÑ\8bзмеÑ\82 ÐºÓ©Ñ\80Ñ\81еÑ\82Ñ\83Ñ\96 Ò¯Ñ\88Ñ\96н Ð±Ò±Ð» Ð´ÐµÑ\80екÒ\9bоÑ\80 Ð¶Ð°Ò£Ð° ÐµÐ½Ð³Ñ\96зÑ\96лÑ\96мдеÑ\80 Ð¶Ó\99не Ð±Ð°Ñ\81Ò\9bа Ó©Ð·Ð³ÐµÑ\80Ñ\96Ñ\81Ñ\82еÑ\80 Ð¶Ð°Ñ\81аÑ\83дан Ò\9bазÑ\96Ñ\80гÑ\96 Ñ\83аÒ\9bÑ\8bÑ\82Ñ\82а Ò\9bұлÑ\8bпÑ\82алÑ\8bнÒ\93ан, Ð±Ò±Ð½Ñ\8b Ð±Ñ\96Ñ\82Ñ\96Ñ\80геннен Ñ\81оң Ò\9bалÑ\8bпÑ\82Ñ\8b Ñ\96Ñ\81ке Ò\9bайÑ\82аÑ\80Ñ\8bладÑ\8b.\n\nÒ\9aұлÑ\8bпÑ\82аÒ\93ан Ð¶Ò¯Ð¹Ðµ Ó\99кÑ\96мÑ\88Ñ\96Ñ\81Ñ\96 Ð¼Ñ\8bна Ñ\82Ò¯Ñ\81Ñ\96ндÑ\96Ñ\80менÑ\96 Ò\9bалдÑ\8bÑ\80дÑ\8b: $1",
        "missing-article": "Бар болуы жөн былай аталған бет мәтіні дерекқорда табылмады: «$1» $2.\n\nБұл ескірген айырма сілтемесіне немесе жойылған бет тарихы сілтемесіне ергеннен бола береді.\n\nЕгер бұл орынды болмаса, бағдарламалық жасақтамадағы қатеге тап болуыңыз мүмкін.\nБұл туралы нақты URL жайына аңғартпа жасап, [[Special:ListUsers/sysop|әкімшіге]] баяндаңыз.",
        "missingarticle-rev": "(түзету нұсқасы#: $1)",
        "missingarticle-diff": "(Айырым: $1, $2)",
        "mypreferencesprotected": "Сізде баптауларыңызды өңдеуге рұқсатыңыз жоқ.",
        "ns-specialprotected": "Арнайы беттер өңдеуге келмейді.",
        "titleprotected": "Бұл атауды бастаудан [[User:$1|$1]] қорғаған.\nКелтірілген себебі: <em>$2</em>.",
-       "filereadonlyerror": "«$2» файл қоры тек қана оқу тәртіптемесінде тұрғасын «$1» файлын өзгерту мүмкін емес.\nБұл тәртіптемені қондырған әкімші келесі түсіндірмені қалдырды: «$3»",
+       "filereadonlyerror": "«$2» файл қоры тек қана оқу тәртіптемесінде тұрғасын «$1» файлын өзгерту мүмкін емес.\n\nЖүйе әкімшісі оны кім құлыптағанын бұл түсіндірмені ұсынды: «$3»",
        "invalidtitle-knownnamespace": "«$2» есім кеңістік түрі және  «$3» мәтіні жарамсыз",
        "invalidtitle-unknownnamespace": "Нөмері $1 белгісіз есім кеңістік атауы және «$2» мәтіні жарамсыз",
        "exception-nologin": "Кірмегенсіз",
        "virus-scanfailed": "скайнерлеу орындалмады (коды: $1)",
        "virus-unknownscanner": "белгісіз антивирус:",
        "logouttext": "<strong>Жүйеден шықтыңыз.</strong>\n\nКейбір беттер браузеріңіздің кэшін тазартқанша әлі де жүйеге кіріп отырғаныңыздай көрінуі мүмкіндігін ескеріңіз.",
+       "cannotlogoutnow-title": "Қазір шығу мүмкін емес",
+       "cannotlogoutnow-text": "$1 қолданған кезде шығу мүмкін емес.",
        "welcomeuser": "Қош келдіңіз, $1!",
        "welcomecreation-msg": "Сіз тіркелдіңіз.\n{{SITENAME}} [[Special:Preferences|баптауларыңызды]] өзіңіз қалауыңыз бойынша өзгерте аласыз.",
        "yourname": "Қатысушы аты:",
        "remembermypassword": "Тіркелгімді осы браузерде ұмытпа (ең көбі $1 {{PLURAL:$1|күн|күн}})",
        "userlogin-remembermypassword": "Мені жүйеде сақтап қою",
        "userlogin-signwithsecure": "Қауіпсіз байланысуды қолдану",
+       "cannotloginnow-title": "Қазір шығу мүмкін емес",
+       "cannotloginnow-text": "$1 қолданған кезде шығу мүмкін емес.",
        "yourdomainname": "Үйшігіңіз:",
        "password-change-forbidden": "Сіз бұл уикиде құпия сөзіңізді өзгерте алмайсыз.",
        "externaldberror": "Осы арада не шеттік растау дерекқорында қате болды, немесе шеттік тіркелгіңізді жаңалау рұқсаты жоқ.",
        "nocookieslogin": "Қатысушы кіру үшін {{SITENAME}} торабында «cookies» деген қолданылады.\nСізде «cookies» өшірілген.\nСоны қосыңыз да кіруді қайта байқап көріңіз.",
        "nocookiesfornew": "Оның қайнарын растай алмағандықтан қатысушының аккаунты тіркелмеді. «Cookies» қосылып тұрғанына көз жеткізіңіз, бетті қайта жаңартыңыз және тағы байқап көріңіз.",
        "noname": "Сізде жарамды қатысушы аты анықталмаған.",
-       "loginsuccesstitle": "Кіруіңіз сәтті болды.",
+       "loginsuccesstitle": "Кірдіңіз.",
        "loginsuccess": "<strong>Сіз енді {{SITENAME}} жобасына «$1» ретінде кірдіңіз.</strong>",
        "nosuchuser": "Мұнда «$1» деп аталған қатысушы тіркелмеген.\nҚатысушы аттары кіші әріптерден тұру керек.\nЕмлеңізді тексеріңіз немесе [[Special:UserLogin/signup|жаңа тіркелгі жасаңыз]].",
        "nosuchusershort": "Мұнда «$1» деп аталған қатысушы тіркелмеген.\nЕмлеңізді тексеріңіз.",
        "wrongpasswordempty": "Құпия сөз бос болған.\nҚайта байқап көріңіз.",
        "passwordtooshort": "Құпиясөзде кем дегенде {{PLURAL:$1|1таңба|таңба}} болуы керек.",
        "passwordtoolong": "Құпиясөз {{PLURAL:$1|1таңбадан|таңбадан}} көп болмау керек.",
+       "passwordtoopopular": "Көп жағдайда таңдалатын құпиясөзді қолдана алмайсыз. Басқа бірегей құпиясөз таңдаңыз.",
        "password-name-match": "Құпия сөзіңіз қатысушы атынан өзгеше болуы қажет.",
        "password-login-forbidden": "Бұл қатысушы аты мен құпия сөзін пайдалануға тыйым салынған.",
        "mailmypassword": "Құпия сөзді қалпына кеттіру",
        "createaccount-title": "{{SITENAME}} жобасына тіркелу",
        "createaccount-text": "Әлдебіреу е-пошта мекенжайыңызды пайдаланып {{SITENAME}} жобасында ($4) «$2» деген атау, «$3» деген құпия сөзбен тіркелгі жасаған.\nҚазір жүйеге кіріуіңіз және құпия сөзіңізді өзгертуіңіз керек.\n\nЕгер бұл тіркелгі қателікпен жасалса осы хабарламаны елемеуіңізге болады.",
        "login-throttled": "Сіз жүйеге кіру үшін тым көп талпыныс жасадыңыз.\nҚайта байқап көрмес бұрын $1 күте тұрыңыз.",
-       "login-abort-generic": "Ð\96үйеге ÐºÑ\96Ñ\80Ñ\83 Ñ\81Ó\99Ñ\82Ñ\81Ñ\96з Ð±Ð¾Ð»ды - Доғарылды.",
+       "login-abort-generic": "СÑ\96здÑ\96Ò£ ÐºÑ\96Ñ\80Ñ\83Ñ\96Ò£Ñ\96з Ð¾Ñ\80Ñ\8bндалмады - Доғарылды.",
        "login-migrated-generic": "Тіркелгіңіздің тасымалданған болатын және сіздің қатысуыш есіміңіз бұдан былай осы уикиде болмайды.",
        "loginlanguagelabel": "Тіл: $1",
        "suspicious-userlogout": "Сіздің жүйеден шығу сұранымыңыз қабылданбады, өйткені бұл бұзылған браузер немесе кэштеуші прокси арқылы жіберілгенге ұқсайды.",
        "newpassword": "Жаңа құпия сөзіңіз:",
        "retypenew": "Жаңа құпия сөзіңізді қайталаңыз:",
        "resetpass_submit": "Құпия сөзді қойыңыз да кіріңіз",
-       "changepassword-success": "Құпия сөзіңіз сәтті өзгертілді!",
+       "changepassword-success": "Құпия сөзіңіз өзгертілді!",
        "changepassword-throttled": "Сіз жақында кіруге тым көп әрекет жасадыңыз.\nҚайта байқап көру үшін $1 уақыт күте тұрыңыз.",
+       "botpasswords": "Бот құпиясөздері",
+       "botpasswords-disabled": "Бот құпиясөздері өшірілген.",
+       "botpasswords-no-central-id": "Бот құпиясөздерін қолдану үшін, орталықтандырылған тіркелгіңізбен кіруіңіз керек.",
+       "botpasswords-existing": "Бар бот құпиясөздері",
+       "botpasswords-createnew": "Жаңа бот құпиясөзін бастау",
+       "botpasswords-editexisting": "Бар бот құпиясөзін өңдеу",
+       "botpasswords-label-appid": "Бот атауы:",
+       "botpasswords-label-create": "Бастау",
+       "botpasswords-label-update": "Жаңарту",
+       "botpasswords-label-cancel": "Болдырмау",
+       "botpasswords-label-delete": "Жою",
+       "botpasswords-label-resetpassword": "Құпия сөзді қалпына кеттіру",
+       "botpasswords-label-grants": "Қолданылатын гранттар:",
+       "botpasswords-label-restrictions": "Пайдалану шектеулері:",
+       "botpasswords-bad-appid": "\"$1\" бот атауы жарамды емес.",
+       "botpasswords-insert-failed": "\"$1\" бот атауын қосу орындалмады. Ол әлдеқашан қосылған ба еді?",
+       "botpasswords-update-failed": "\"$1\" бот атауын жаңарту орындалмады. Ол әлдеқашан жойылған ба еді?",
+       "botpasswords-created-title": "Бот құпиясөзі құрылды",
+       "botpasswords-updated-title": "Бот құпиясөзі жаңартылды",
+       "botpasswords-deleted-title": "Бот құпиясөзі жойылды",
        "resetpass_forbidden": "Құпия сөз өзгертілмейді",
        "resetpass-no-info": "Бұл бетке тікелей ену үшін жүйеге кіруіңіз керек.",
        "resetpass-submit-loggedin": "Құпия сөзді өзгерту",
        "resetpass-submit-cancel": "Болдырмау",
-       "resetpass-wrong-oldpass": "Уақытша немесе қазіргі құпия сөзіңіз жарамсыз.\nМүмкін сіз құпия сөзді сәтті өзгерткенсіз немесе жаңа уақытша құпия сөзге сұраным жасағансыз.",
+       "resetpass-wrong-oldpass": "Уақытша немесе қазіргі құпия сөзіңіз жарамсыз.\nМүмкін сіз құпия сөзді өзгерткенсіз немесе жаңа уақытша құпия сөзге сұраным жасағансыз.",
        "resetpass-recycled": "Құпия сөзіңізді қазіргі құпия сөзіңізден өзгеше етіп өзгертіңіз.",
        "resetpass-temp-emailed": "Сіз уақытша email-ды кодпен кірдіңіз.\nКіруді аяқтау үшін жаңа құпия сөзді мында орнатуыңыз керек:",
        "resetpass-temp-password": "Уақытша құпия сөз:",
        "passwordreset-emailtext-ip": "Әлде кім (мүмкін сіз болуыңыз, $1 IP адресінен) {{SITENAME}} сайтында ($4) құпия сөзді өзгертуге өтініш білдірді. Мына қатысушы {{PLURAL:$3|аккаунты|аккаунттары}} осы электронды почта қатысты:\n\n$2\n\n{{PLURAL:$3|Бұл уақытша құпия сөз|Бұл уақытша құпия сөздер}} {{PLURAL:$5|бір күнде|$5 күнде}}уақыты аяқталады.\nСіз кіруіңіз және жаңа құпия сөзді таңдауыңыз керек. Егер бұл өтінішті басқа біреу жасаса, немесе сіз  бұрынғы құпия сөзіңізді еске түсірсеңіз және құпия сөзді ауыстыруды қаламасаңыз, сіз бұл хабарламаны ескермей және бұрынғы құпия сөзді қолдана беруіңізге болады.",
        "passwordreset-emailtext-user": "$1 есімді қатысушы {{SITENAME}} сайтында ($4) құпия сөзді өзгертуге өтініш білдірді. Мына қатысушы {{PLURAL:$3|аккаунт|аккаунттар}} осы електронды почта қатысты:\n\n$2\n\n{{PLURAL:$3|Бұл уақытша құпия сөз|Бұл уақытша құпия сөздер}} {{PLURAL:$5|бір күнде|$5 күнде}}уақыты аяқталады.\nСіз кіруіңіз және жаңа құпия сөзді таңдауыңыз керек. Егер бұл өтінішті басқа біреу жасаса, немесе сіз  бұрынғы құпия сөзіңізді еске түсірсеңіз, және құпия сөзді ауыстыруды қаламасаңыз, сіз бұл хабарламаны ескермей және бұрыңғы құпия сөзді қолдана беруіңізге болады.",
        "passwordreset-emailelement": "Қатысушы есімі: \n$1\n\nУақытша құпия сөз: \n$2",
-       "passwordreset-emailsentemail": "Құпия сөзді өзгерту электронды пошта арқылы жөнелтілді.",
+       "passwordreset-emailsentemail": "Бұл email мекенжайы тіркелгіңізге байланысқан, сол себепті құпия сөзді өзгерту электронды пошта арқылы жөнелтіледі.",
        "passwordreset-emailsent-capture": "Құпия сөзді өзгерту электронды пошта арқылы жөнелтілді, ол төменде көрсетілген.",
        "passwordreset-emailerror-capture": "Құпиясөзді өзгерту электрон хаты жасалды, ол төменде көрсетілген, бірақ ол {{GENDER:$2|қатысушыға}} жөнелтілмеді: $1",
        "changeemail": "Е-пошта мекенжайын өзгерту немесе аластау",
        "copyrightwarning": "{{SITENAME}} жобасына қосқан барлық үлестеріңіз $2 (көбірек ақпарат үшін: $1) аясында жарияланатынын ескеріңіз.\nЕгер еңбегіңіздің еркін өңделуін және ақысыз көпшілікке таралуын қаламасаңыз мұнда жарияламаңыз<br />\nТағы да бұл мәліметті өзіңіз жазғаныңызға не қоғам қазынасынан немесе сондай ашық қорлардан көшірілгеніне бізге уәде бересіз.\n<strong>Авторлық құқықпен қорғалған мәліметті рұқсатсыз жарияламаңыз!</strong>",
        "copyrightwarning2": "{{SITENAME}} жобасына қосқан барлық үлестеріңізді басқа үлескерлер өңдеуге, өзгертуге немесе аластауы мүмкін екенін ескеріңіз.\nЕгер еңбегіңіздің еркін өңделуін қаламасаңыз осында жарияламаңыз.<br />\nТағы да бұл мәліметті өзіңіз жазғаныңызға не қоғам қазынасынан немесе сондай ашық қорлардан көшірілгеніне бізге уәде бересіз. (көбірек ақпарат үшін $1 құжатын қараңыз).\n<strong>Авторлық құқықпен қорғалған мәліметті рұқсатсыз жарияламаңыз!</strong>",
        "longpageerror": "<strong>ҚАТЕЛІК: Сақтамақшы болған мәтініңіздің көлемі {{PLURAL:$1|бір килобайт|$1 килобайт}} ең көбі {{PLURAL:$2|килобайт|$2 килобайт}} рұқсат етілген көлемінен асқан.</strong>\nБұл сақталмайды.",
-       "readonlywarning": "<strong>Ð\95СÐ\9aÐ\95РТУ: Ð\94еÑ\80екÒ\9bоÑ\80 Ñ\82еÑ\85никалÑ\8bÒ\9b Ð¶Ò±Ð¼Ñ\8bÑ\81Ñ\82аÑ\80 Ð¶Ð°Ñ\81аÑ\83 Ò¯Ñ\88Ñ\96н Ò\9bұлÑ\8bпÑ\82алÒ\93ан Ñ\81ондÑ\8bÒ\9bÑ\82ан Ð´Ó\99л Ò\9bазÑ\96Ñ\80 Ó©Ò£Ð´ÐµÐ¼ÐµÒ£Ñ\96здÑ\96 Ñ\81аÒ\9bÑ\82ай Ð°Ð»Ð¼Ð°Ð¹Ñ\81Ñ\8bз.</strong>\nÐ\9aейÑ\96н Ñ\81аÒ\9bÑ\82аÑ\83 Ò¯Ñ\88Ñ\96н Ð¼Ó\99Ñ\82Ñ\96нÑ\96Ò£Ñ\96здÑ\96 Ð¼Ó\99Ñ\82Ñ\96н Ñ\84айлÑ\8bна ÐºÓ©Ñ\88Ñ\96Ñ\80Ñ\96п Ð°Ð»Ñ\83Ò£Ñ\8bзÒ\93а Ð±Ð¾Ð»Ð°Ð´Ñ\8b. \n\nÐ\90дминÑ\81Ñ\82Ñ\80аÑ\82оÑ\80 оны құлыптау себебін келесідей түсіндіреді: $1",
+       "readonlywarning": "<strong>Ð\95СÐ\9aÐ\95РТУ: Ð\94еÑ\80екÒ\9bоÑ\80 Ñ\82еÑ\85никалÑ\8bÒ\9b Ð¶Ò±Ð¼Ñ\8bÑ\81Ñ\82аÑ\80 Ð¶Ð°Ñ\81аÑ\83 Ò¯Ñ\88Ñ\96н Ò\9bұлÑ\8bпÑ\82алÒ\93ан Ñ\81ондÑ\8bÒ\9bÑ\82ан Ð´Ó\99л Ò\9bазÑ\96Ñ\80 Ó©Ò£Ð´ÐµÐ¼ÐµÒ£Ñ\96здÑ\96 Ñ\81аÒ\9bÑ\82ай Ð°Ð»Ð¼Ð°Ð¹Ñ\81Ñ\8bз.</strong>\nÐ\9aейÑ\96н Ñ\81аÒ\9bÑ\82аÑ\83 Ò¯Ñ\88Ñ\96н Ð¼Ó\99Ñ\82Ñ\96нÑ\96Ò£Ñ\96здÑ\96 Ð¼Ó\99Ñ\82Ñ\96н Ñ\84айлÑ\8bна ÐºÓ©Ñ\88Ñ\96Ñ\80Ñ\96п Ð°Ð»Ñ\83Ò£Ñ\8bзÒ\93а Ð±Ð¾Ð»Ð°Ð´Ñ\8b. \n\nÐ\96үйе Ð°Ð´Ð¼Ð¸Ð½Ñ\81Ñ\82Ñ\80аÑ\82оÑ\80Ñ\8b оны құлыптау себебін келесідей түсіндіреді: $1",
        "protectedpagewarning": "<strong>Ескерту: Бұл бет өңдеуден қорғалған сондықтан тек әкімші құқықтары бар қатысушылар ғана өңдей алады.</strong>\nТөменде соңғы журнал жазбасы көрсетілген:",
        "semiprotectedpagewarning": "<strong>Ескерту:</strong> Бет жартылай қорғалған, сондықтан осыны тек тіркелген қатысушылар өңдей алады.\nТөменде бет журналының соңғы жазбасы көрсетілген:",
        "cascadeprotectedwarning": "<strong>Ескерту:</strong> Бұл бет қорғалған, сондықтан тек әкімші құқықтары бар қатысушылар ғана өңдей алады, себебі бұл келесі «баулы қорғауы» бар {{PLURAL:$1|бетіне|беттеріне}} кірістілген бет:",
        "revdelete-unsuppress": "Қалпына келтірілген түзетулерден тиымдарды аластау",
        "revdelete-log": "Себебі:",
        "revdelete-submit": "Бөлектенген {{PLURAL:$1|түзетуге|түзетулерге}} қолдану",
-       "revdelete-success": "'''Түзету көрінісі сәтті жаңартылды.'''",
+       "revdelete-success": "Түзету көрінісі жаңартылды.",
        "revdelete-failure": "'''Түзету көрінісі жаңартылмады:'''\n$1",
-       "logdelete-success": "'''Журнал көрінісі сәтті қойылды.'''",
+       "logdelete-success": "Журнал көрінісі қойылды.",
        "logdelete-failure": "Журнал көрінулігі орнатылмады:\n$1",
        "revdel-restore": "көрінісін өзгерту",
        "pagehist": "Бет тарихы",
        "userrights": "Қатысушы құқықтарын реттеу",
        "userrights-lookup-user": "Қатысушы топтарын реттеу",
        "userrights-user-editname": "Қатысушы атын енгізіңіз:",
-       "editusergroup": "Қатысушы топтарын өңдеу",
+       "editusergroup": "{{GENDER:$1|Қатысушы}} топтарын өңдеу",
        "editinguser": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|есімді қатысушының}} қатысушы құқықтарын өзгерту",
        "userrights-editusergroup": "Қатысушы топтарын өңдеу",
-       "saveusergroups": "Қатысушы топтарын сақтау",
+       "saveusergroups": "{{GENDER:$1|Қатысушы}} топтарын сақтау",
        "userrights-groupsmember": "Мүшелігі:",
        "userrights-groupsmember-auto": "Бұлтарасыз мүше:",
        "userrights-groups-help": "Бұл қатысушы кіретін топтарды реттей аласыз.\n* Құсбелгі қойылған көзі қатысушы бұл топқа кіргенін көрсетеді;\n* Құсбелгі алып тасталған көз қатысушы бұл топқа кірмегенін көрсетеді;\n* Келтірілген * топты бір үстегенінен кейін аластай алмайтындығын, не қарама-қарсысын көрсетеді.",
        "userrights-changeable-col": "Өзгерте алатын топтар",
        "userrights-unchangeable-col": "Өзгерте алмайтын топтар",
        "userrights-conflict": "Қатысушы құқықтарының қақтығысы! Өзгертулеріңізді қайта қарап шығыңыз және құптаңыз.",
-       "userrights-removed-self": "Өзіңіздің құқықтарыңызды сәтті алып тастадыңыз.  As such, you are no longer able to access this page.",
+       "userrights-removed-self": "Өзіңіздің құқықтарыңызды алып тастадыңыз.  Осылайша бұл бетке бұдан былай қатынай алмайсыз.",
        "group": "Топ:",
        "group-user": "Қатысушылар",
        "group-autoconfirmed": "Өздіктіқұпталған қатысушылар",
        "right-noratelimit": "Еселік шектелімдері ықпал етпейді",
        "right-import": "Басқа уикилерден беттерді сырттан алу",
        "right-importupload": "Файлдарды жүктеу арқылы беттерді сырттан алу",
-       "right-patrol": "Басқарардың өңдемелерін зерттелді деп белгілеу",
+       "right-patrol": "Басқарардың өңдемелерін тексерілді деп белгілеу",
        "right-autopatrol": "Өз өңдемелерін тексерілді деп өздіктік белгілеу",
        "right-patrolmarks": "Жуықтағы өзгерістердегі зерттеу белгілерін көру",
        "right-unwatchedpages": "Бақыланылмаған бет тізімін көру",
        "action-rollback": "жекелік беттегі соңғы өңдеген қатысушының соңғы өңдемелерін жылдам шегіндіру",
        "action-import": "беттерді басқа уикиден импортау",
        "action-importupload": "беттерді файл жүктеуінен импорттау",
-       "action-patrol": "басқалардың өңдеулерін зерттелді деп белгілеу",
-       "action-autopatrol": "өзіңіздің өңдемеңізді зерттелді деп белгілеу",
+       "action-patrol": "басқалардың өңдемелерін тексерілді деп белгілеу",
+       "action-autopatrol": "өзіңіздің өңдемеңізді тексерілді деп белгілеу",
        "action-unwatchedpages": "бақыланылмаған беттер тізімін қарау",
        "action-mergehistory": "Бұл беттің өзгеріс тарихын қосу",
        "action-userrights": "Қатысушылардың барлық құқықтарын өзгерту",
        "recentchangeslinked-page": "Бет атауы:",
        "recentchangeslinked-to": "Керісінше, келтірілген бетке сілтейтін беттердегі өзгерістерді көрсет",
        "recentchanges-page-added-to-category": "[[:$1]] бетіне санат қосты",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] және {{PLURAL:$2|бір бет|$2 бет}} санатқа қосылды",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] және [[Special:WhatLinksHere/$1|{{PLURAL:$2|бір бет|$2 бет}}]] санатқа қосылды",
        "recentchanges-page-removed-from-category": "[[:$1]] санаттан алынды",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] және {{PLURAL:$2|бір бет|$2 бет}} санаттан алынды",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] және [[Special:WhatLinksHere/$1|{{PLURAL:$2|бір бет|$2 бет}}]] санаттан алынды",
        "autochange-username": "МедиаУики өздікті өзгерісі",
        "upload": "Файл жүктеу",
        "uploadbtn": "Файлды жүктеу",
        "backend-fail-read": "«$1» файлы оқылмайды.",
        "backend-fail-create": "«$1» файлы жазылмайды.",
        "backend-fail-maxsize": "\"$1\" файлы жазылмайды, себебі {{PLURAL:$2|1 байттан|$2 байттан}} үлкенірек.",
-       "backend-fail-readonly": "«$1» сақтау сервері қазіргі уақытта «тек оқу» режимінде орналасқан. Себебі: «<em>$2</em>»",
+       "backend-fail-readonly": "«$1» сақтау сервері қазіргі уақытта тек оқу режимінде орналасқан. Себебі: <em>$2</em>",
        "backend-fail-synced": "«$1» файлы ішкі сақтау серверінде келісімсіз жағдайда орналасқан",
        "backend-fail-connect": "«$1» сақтау серверіне байланыспады.",
        "backend-fail-internal": "«$1» сақтау серверінде белгісіз қате кездесті.",
        "apihelp-no-such-module": "«$1» модулі табылмады.",
        "apisandbox-submit": "Сұраныс жасау",
        "apisandbox-reset": "Тазарту",
-       "apisandbox-examples": "Мысалы",
-       "apisandbox-results": "Нәтижесі",
+       "apisandbox-examples": "Мысалдар",
+       "apisandbox-results": "Нәтижелер",
        "apisandbox-request-url-label": "URL сұранысы",
-       "apisandbox-request-time": "Сұраныс уақыты: $1",
+       "apisandbox-request-time": "Сұраныс уақыты: {{PLURAL:$1|$1 мс}}",
        "booksources": "Кітап қайнарлары",
        "booksources-search-legend": "Кітап қайнарларын іздеу",
        "booksources-search": "Іздеу",
        "log-title-wildcard": "Мына мәтіннен басталытын тақырып аттарын іздеу",
        "showhideselectedlogentries": "Таңдалған журнал енгізілімдерін көрсету/жасыру",
        "log-edit-tags": "Таңдалған журнал жазбаларының өңдеу белгілері",
+       "checkbox-select": "Таңдау: $1",
+       "checkbox-all": "Барлығы",
+       "checkbox-none": "Ешқандай",
+       "checkbox-invert": "Керісінше",
        "allpages": "Барлық беттер",
        "nextpage": "Келесі бетке ($1)",
        "prevpage": "Алдыңғы бетке ($1)",
        "listgrouprights-namespaceprotection-header": "Есім кеңістігі шектелімдері",
        "listgrouprights-namespaceprotection-namespace": "Атау кеңістігі",
        "listgrouprights-namespaceprotection-restrictedto": "Қатысушыға өңдеу үшін берілген құқық(тар)",
+       "listgrants-rights": "Құқықтар",
        "trackingcategories": "Санаттарды қадағалау",
        "trackingcategories-summary": "Бұл бет МедиаУики бағдарламалық жасақтамасынан автоматты түрде толтырылатын санаттарды есептеп тізеді. Олардың есімдерін {{ns:8}} есім кеңістігіндегі сәйкес жүйе хабарлары  арқылы өзгертуге болады.",
        "trackingcategories-msg": "Санатты қадағалау",
        "emailccsubject": "$1 дегенге хатыңыздың көшірмесі: $2",
        "emailsent": "Хат жөнелтілді",
        "emailsenttext": "Е-пошта хатыңыз жөнелтілді.",
-       "emailuserfooter": "Бұл электронды хатты {{SITENAME}} сайтындағы «{{int:emailuser}}» функцияцы арқылы $1 деген $2 дегенге жіберген.",
+       "emailuserfooter": "Бұл электронды хатты {{SITENAME}} сайтындағы «{{int:emailuser}}» функцияцы арқылы $1 деген {{GENDER:$2|$2}} дегенге {{GENDER:$1|жіберген}}.",
        "usermessage-summary": "Жүйе хабарламасы қалдырылуда.",
        "usermessage-editor": "Жүйе мессенжері",
        "watchlist": "Бақылау тізімі",
        "watchlistanontext": "Бақылау тізіміңіздегі даналарды қарау не өңдеу үшін кіріңіз.",
        "watchnologin": "Кірмегенсіз",
        "addwatch": "Бақылау тізіміңізге қосу",
-       "addedwatchtext": "«[[:$1]]» Ð±ÐµÑ\82Ñ\96 [[Special:Watchlist|баÒ\9bÑ\8bлаÑ\83 Ñ\82Ñ\96зÑ\96мÑ\96Ò£Ñ\96зге]] Ò\9bоÑ\81Ñ\8bлдÑ\8b.\nÐ\91ұл Ð±ÐµÑ\82Ñ\82Ñ\96Ò£ Ð¶Ó\99не Ð±Ð°Ð¹Ð»Ð°Ð½Ñ\8bÑ\81Ñ\82Ñ\8b Ñ\82алÒ\9bÑ\8bлаÑ\83 Ð±ÐµÑ\82Ñ\96нÑ\96Ò£ ÐºÐµÐ»ÐµÑ\88екÑ\82егÑ\96 Ó©Ð·Ð³ÐµÑ\80Ñ\96Ñ\81Ñ\82еÑ\80Ñ\96 Ñ\81онда Ñ\82Ñ\96зÑ\96мделедÑ\96.",
+       "addedwatchtext": "«[[:$1]]» Ð¶Ó\99не Ð¾Ð½Ñ\8bÒ£ Ñ\82алÒ\9bÑ\8bлаÑ\83 Ð±ÐµÑ\82Ñ\96 [[Special:Watchlist|баÒ\9bÑ\8bлаÑ\83 Ñ\82Ñ\96зÑ\96мÑ\96Ò£Ñ\96зге]] Ò\9bоÑ\81Ñ\8bлдÑ\8b.",
        "addedwatchtext-short": "«$1» беті бақылау тізіміңізге қосылды.",
        "removewatch": "Бақылау тізіміңізден аластату",
-       "removedwatchtext": "«[[:$1]]» беті [[Special:Watchlist|бақылау тізіміңізден]] аласталды.",
+       "removedwatchtext": "«[[:$1]]» Ð¶Ó\99не Ð¾Ð½Ñ\8bÒ£ Ñ\82алÒ\9bÑ\8bлаÑ\83 Ð±ÐµÑ\82Ñ\96 [[Special:Watchlist|баÒ\9bÑ\8bлаÑ\83 Ñ\82Ñ\96зÑ\96мÑ\96Ò£Ñ\96зден]] Ð°Ð»Ð°Ñ\81Ñ\82алдÑ\8b.",
        "removedwatchtext-short": "«$1» беті бақылау тізіміңізден аласталды",
        "watch": "Бақылау",
        "watchthispage": "Бұл бетті бақылау",
        "wlshowhideanons": "анонимді қатысушылар",
        "wlshowhidepatr": "тексерілген өңдемелер",
        "wlshowhidemine": "өңдемелерім",
+       "wlshowhidecategorization": "Бет санаттаулары",
        "watchlist-options": "Бақылау тізімінің баптаулары",
        "watching": "Бақылауда…",
        "unwatching": "Бақыламауда…",
        "delete-toobig": "Бұл бетте үлкен түзету тарихы бар, $1 {{PLURAL:$1|түзетуден|түзетуден}} астам.\nБұндай беттердің жоюы {{SITENAME}} торабын әлдеқалай үзіп тастауына бөгет салу үшін тиымдалған.",
        "delete-warning-toobig": "Бұл бетте үлкен өңдеу тарихы бар, $1 {{PLURAL:$1|түзетуден|түзетуден}} астам.\nБұның жоюы {{SITENAME}} торабындағы дерекқор әрекеттерді үзіп тастауын мүмкін;\nбұны абайлап өткізіңіз.",
        "deleteprotected": "Сіз бұл бетті жоя алмайсыз, себебі ол қорғалған.",
-       "deleting-backlinks-warning": "'''Ескерту:''' Сіз жоймақшы болған бетке [[Special:WhatLinksHere/{{FULLPAGENAME}}|басқа беттерден]] сілтенген немесе [[Special:WhatLinksHere/{{FULLPAGENAME}}|басқа беттерге]] кірістірілген.",
+       "deleting-backlinks-warning": "</strong>Ескерту:</strong>  Сіз жоймақшы болған бетке [[Special:WhatLinksHere/{{FULLPAGENAME}}|басқа беттерден]] сілтенген немесе [[Special:WhatLinksHere/{{FULLPAGENAME}}|басқа беттерге]] кірістірілген.",
        "rollback": "Өңдемелерді шегіндіру",
        "rollbacklink": "шегіндіру",
        "rollbacklinkcount": "$1 {{PLURAL:$1|өңдемені|өңдемені}} шегіндіру",
        "whatlinkshere-submit": "Өту",
        "autoblockid": "#$1 өздікбұғаттауы",
        "block": "Қатысушыны бұғаттау",
-       "unblock": "Ò\9aаÑ\82Ñ\8bÑ\81Ñ\83Ñ\88Ñ\8bнÑ\8b Ð±Ò±Ò\93аÑ\82Ñ\82аÑ\83Ñ\8bнан Ð±Ð¾Ñ\81аÑ\82Ñ\83",
+       "unblock": "Қатысушыны бұғатынан босату",
        "blockip": "{{GENDER:$1|Қатысушыны}} бұғаттау",
        "blockip-legend": "Қатысушыны бұғаттау",
        "blockiptext": "Төмендегі форманы жазу рұқсатын белгілі IP мекенжайынан не қатысушы есімінен бұғаттау үшін қолданыңыз.\nБұны тек бұзақылықты болдырмау үшін және де [[{{MediaWiki:Policy-url}}|ережелер]] бойынша атқаруыңыз кажет.\nТөменге тиісті себебін көрсетіңіз (мысалы дәлелге бұзақылықпен өзгертілген беттерді келтіріңіз).",
        "ipb-confirmhideuser": "Сіз қатысушыны бұғаттауда «қатысушыны жасыру» параметрін қосқасыз. Бұл барлық тізімдерден және журнал жазбаларынан қатысушы есімін жасырады. Сіз шынымен бұлай жасауды қалайсыз ба?",
        "ipb-confirmaction": "Егер сіз шынымен оны істеуді қаласаңыз, төмендегі жолақтан «{{int:ipb-confirm}}» дегенді белгілеңіз.",
        "ipb-edit-dropdown": "Бұғаттау себептерін өңдеу",
-       "ipb-unblock-addr": "$1 Ð´ÐµÐ³ÐµÐ½Ð´Ñ\96 Ð±Ò±Ò\93аÑ\82Ñ\82аÑ\83Ñ\8bнан Ð±Ð¾Ñ\81аÑ\82Ñ\83",
+       "ipb-unblock-addr": "$1 дегенді бұғатынан босату",
        "ipb-unblock": "Қатысушы атын немесе IP мекенжайын бұғаттамау",
        "ipb-blocklist": "Бұғатталғандарды қарау",
        "ipb-blocklist-contribs": "{{GENDER:$1|$1}} есімді қатысушының үлесі",
-       "unblockip": "Ò\9aаÑ\82Ñ\8bÑ\81Ñ\83Ñ\88Ñ\8bнÑ\8b Ð±Ò±Ò\93аÑ\82Ñ\82аÑ\83Ñ\8bнан Ð±Ð¾Ñ\81аÑ\82Ñ\83",
+       "unblockip": "Қатысушыны бұғатынан босату",
        "unblockiptext": "Төмендегі форманы IP мекенжайымен не қатысушы есімімен алдын-ала бұғатталған қатысушыға жазу рұқсатын қалпына келтіріу үшін қолданыңыз.",
        "ipusubmit": "Осы бұғаттауды алып тастау",
        "unblocked": "[[User:$1|$1]] бұғаттауы өшірілді",
        "blocklog-showsuppresslog": "Бұл қатысушы ұдайы жасырылып және бұғатталып отырған.\nДерек үшін төменде жасыру журналы берілген:",
        "blocklogentry": "[[$1]] дегенді $2 мерзімге бұғаттады $3",
        "reblock-logentry": "[[$1]] дегеннің бұғатталу мерзімінің аяқталуын $2 $3 дегенге өзгертті.",
-       "blocklogtext": "Ð\91ұл Ò\9bаÑ\82Ñ\8bÑ\81Ñ\83Ñ\88Ñ\8bлаÑ\80дÑ\8b Ð±Ò±Ò\93аÑ\82Ñ\82аÑ\83 Ð¶Ó\99не Ð±Ò±Ò\93аÑ\82Ñ\82аÑ\83Ñ\8bнан Ð±Ð¾Ñ\81аÑ\82Ñ\83 Ó\99Ñ\80екеÑ\82Ñ\82еÑ\80Ñ\96нÑ\96Ò£ Ð¶Ñ\83Ñ\80налÑ\8b.\nӨздÑ\96кÑ\82Ñ\96к Ð±Ò±Ò\93аÑ\82Ñ\82алÒ\93ан IP Ð¼ÐµÐºÐµÐ½Ð¶Ð°Ð¹Ð»Ð°Ñ\80 Ñ\82Ñ\96зÑ\96мделмеген.\nÒ\9aазÑ\96Ñ\80гÑ\96 Ñ\83аÒ\9bÑ\8bÑ\82Ñ\82аÒ\93Ñ\8b Ð±ÐµÐ»Ñ\81ендÑ\96 Ñ\82иÑ\8bмдаÑ\80 Ð¼ÐµÐ½ Ð±Ò±Ò\93аÑ\82Ñ\82аÑ\83лаÑ\80дÑ\8b [[Special:BlockList|бұÒ\93аÑ\82Ñ\82аÑ\83 Ñ\82Ñ\96зÑ\96мÑ\96нен]] Ò\9bаÑ\80аңÑ\8bз.",
-       "unblocklogentry": "$1 ÐµÑ\81Ñ\96мдÑ\96 Ò\9bаÑ\82Ñ\8bÑ\81Ñ\83Ñ\88Ñ\8bнÑ\8b Ð±Ò±Ò\93аÑ\82Ñ\82аÑ\83Ñ\8bнан Ð±Ð¾Ñ\81аÑ\82Ñ\82Ñ\8b",
+       "blocklogtext": "Бұл қатысушыларды бұғаттау және бұғатынан босату әрекеттерінің журналы.\nӨздіктік бұғатталған IP мекенжайлар тізімделмеген.\nҚазіргі уақыттағы белсенді тиымдар мен бұғаттауларды [[Special:BlockList|бұғаттау тізімінен]] қараңыз.",
+       "unblocklogentry": "$1 есімді қатысушыны бұғатынан босатты",
        "block-log-flags-anononly": "тек аноним қатысушылар",
        "block-log-flags-nocreate": "тіркелуін өшірді",
        "block-log-flags-noautoblock": "автобұғаттау өшірілген",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|нұсқа|нұсқа}} импортталды",
        "import-logentry-interwiki-detail": "$2 дегеннен $1 {{PLURAL:$1|нұсқа|нұсқа}} импортталды",
        "javascripttest": "JavaScript сынақталуда",
-       "javascripttest-pagetext-noframework": "Бұл бет JavaScript сынақтарын жүргізу үшін резервтелген.",
-       "javascripttest-pagetext-unknownframework": "«$1» белгісіз сынау ортасы.",
        "javascripttest-pagetext-unknownaction": "Белгісіз әрекет «$1».",
-       "javascripttest-pagetext-frameworks": "Келесі сынау ортасының біреуін таңдаңыз: $1",
-       "javascripttest-pagetext-skins": "Сынақ жүргізу үшін мәнерді таңдаңыз:",
        "javascripttest-qunit-intro": "[$1 сынақтау құжаттамасын]  mediawiki.org-тен қара.",
        "tooltip-pt-userpage": "Жеке бетіңіз",
        "tooltip-pt-anonuserpage": "Бұл IP мекенжайдың жеке беті",
        "tooltip-pt-mytalk": "Талқылау бетіңіз",
        "tooltip-pt-anontalk": "Бұл IP мекенжай өңдемелерін талқылау",
-       "tooltip-pt-preferences": "Бапталымдарым",
+       "tooltip-pt-preferences": "{{GENDER:|Бапталымдарым}}",
        "tooltip-pt-watchlist": "Өзгерістерін бақылап тұрған беттер тізімім.",
-       "tooltip-pt-mycontris": "Өңдеулеріңіздің тізімі",
+       "tooltip-pt-mycontris": "{{GENDER:|Үлестеріңіздің}} тізімі",
        "tooltip-pt-anoncontribs": "Бұл IP мекенжаймен жасаған өңдемелер тізімі",
        "tooltip-pt-login": "Кіруіңізді ұсынамыз, ол міндетті емес.",
        "tooltip-pt-logout": "Шығу",
        "tooltip-t-recentchangeslinked": "Мыннан сілтенген беттердің жуықтағы өзгерістері",
        "tooltip-feed-rss": "Бұл беттің RSS арнасы",
        "tooltip-feed-atom": "Бұл беттің Atom арнасы",
-       "tooltip-t-contributions": "Осы қатысушының үлестерінің тізімі",
+       "tooltip-t-contributions": "{{GENDER:$1|Осы қатысушының}} үлестері тізімі",
        "tooltip-t-emailuser": "Осы қатысушыға хат жөнелту",
        "tooltip-t-info": "Бұл бет туралы көбірек мәлімет",
        "tooltip-t-upload": "Файлдарды жүктеу",
        "pageinfo-category-pages": "Беттер саны",
        "pageinfo-category-subcats": "Санатшалар саны",
        "pageinfo-category-files": "Файлдар саны",
-       "markaspatrolleddiff": "Ð\97еÑ\80Ñ\82Ñ\82елді деп белгілеу",
+       "markaspatrolleddiff": "ТекÑ\81еÑ\80Ñ\96лді деп белгілеу",
        "markaspatrolledtext": "Бұл бетті тексерілді деп белгілеу",
        "markedaspatrolled": "Тексерілді деп белгіленді",
        "markedaspatrolledtext": "Бөлектенген нұсқа [[:$1]] тексерілді деп белгіленді.",
        "rcpatroldisabled": "Жуықтағы өзгерістерді зерттеуі өшірілген",
        "rcpatroldisabledtext": "Жуықтағы өзгерістерді зерттеу мүмкіндігі ағымда өшірілген.",
        "markedaspatrollederror": "Зерттелді деп белгіленбейді",
-       "markedaspatrollederrortext": "Ð\97еÑ\80Ñ\82Ñ\82елді деп белгілеу үшін түзетуді келтіріңіз.",
+       "markedaspatrollederrortext": "ТекÑ\81еÑ\80Ñ\96лді деп белгілеу үшін түзетуді келтіріңіз.",
        "markedaspatrollederror-noautopatrol": "Өз жасаған өзгерістеріңізді зерттелді деп белгілей алмайсыз.",
        "markedaspatrollednotify": "$1 бетіндегі бұл өзгеріс тексерілді деп белгіленді.",
        "markedaspatrollederrornotify": "Тексерілді деп белгіленбеді.",
        "seconds-abbrev": "$1с",
        "minutes-abbrev": "$1мин",
        "hours-abbrev": "$1сағ",
-       "seconds": "{{PLURAL:$1|$1 секунт|$1 секунт}}",
+       "seconds": "{{PLURAL:$1|$1 секунд|$1 секунд}}",
        "minutes": "{{PLURAL:$1|$1 минут|$1 минут}}",
        "hours": "{{PLURAL:$1|$1 сағат|$1 сағат}}",
        "days": "{{PLURAL:$1|$1 күн|$1 күн}}",
        "scarytranscludefailed-httpstatus": "[$1: HTTP $2 үшін үлгі келтіруі сәтсіз болды]",
        "scarytranscludetoolong": "[URL тым ұзын]",
        "deletedwhileediting": "Ескету: Бұл бетті өңдеуіңізді бастағанда, осы бет жойылды!",
-       "confirmrecreate": "Бұл бетті өңдеуіңізді бастағанда [[User:$1|$1]] ([[User talk:$1|талқылауы]]) осы бетті жойды, келтірген себебі:\n: ''$2''\nОсы бетті қайта бастауын нақты тілегеніңізді құптаңыз.",
+       "confirmrecreate": "Бұл бетті өңдеуіңізді бастағанда [[User:$1|$1]] ([[User talk:$1|талқылауы]]) осы бетті жойды, келтірген себебі:\n: <em>$2</em>\nОсы бетті қайта бастауын нақты тілегеніңізді құптаңыз.",
        "confirmrecreate-noreason": "Бұл бетті өңдеп бастағаныңызда [[User:$1|$1]] ([[User talk:$1|талқылауы]]) жойды. \nОсы бетті қайта бастауын нақты тілегеніңізді құптаңыз.",
        "recreate": "Қайта бастау",
        "unit-pixel": " нүкте",
        "size-bytes": "$1 байт",
        "size-kilobytes": "$1 КБ",
        "lag-warn-normal": "{{PLURAL:$1|секунтта|секунтта}} $1 жаңалау өзгерістер бұл тізімде көрсетілмеуі мүмкін.",
-       "lag-warn-high": "Дерекқор сервері көп кешігуі себебінен, $1 {{PLURAL:$1|секунтта|сеунтта}} жаңалау өзгерістер бұл тізімде көрсетілмеуі мүмкін.",
+       "lag-warn-high": "Дерекқор сервері көп кешігуі себебінен, $1 {{PLURAL:$1|секундтан|секундтан}} жаңалау өзгерістер бұл тізімде көрсетілмеуі мүмкін.",
        "watchlistedit-normal-title": "Бақылау тізімді өңдеу",
        "watchlistedit-normal-legend": "Бақылау тізімінен тақырып аттарын аластау",
        "watchlistedit-normal-explain": "Бақылау тізіміңіздегі тақырып аттар төменде көрсетіледі.\nТақырып атын аластау үшін, бүйір көзге құсбелгі салыңыз, және \"{{int:Watchlistedit-normal-submit}}\" дегенді нұқыңыз.\nТағы да [[Special:EditWatchlist/raw|қам тізімді өңдей]] аласыз.",
        "version-libraries-description": "Сипаттамасы",
        "version-libraries-authors": "Автор(лары)",
        "redirect": "Файл, қатысушы, бет немесе нұсқа ID-і бойынша бағыттаулар",
-       "redirect-legend": "Файл немесе бетке айдатулар",
        "redirect-summary": "Бұл арнайы бет файлға (файл атауы берілген), бетке (нұсқа ID-і немесе бет ID-і берілген), не қатысушы бетіне бағыттайды (қатысушы сандық ID-і берілген). Қолданылуы: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], немесе [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Өту",
        "redirect-lookup": "Іздеу:",
        "tags-edit-revision-legend": "{{PLURAL:$1|Бұл нұсқадан|Барлық $1 нұсқадан}} тегтерді аластау не қосу",
        "tags-edit-logentry-legend": "{{PLURAL:$1|Бұл журнал жазбасынан|Барлық $1 журнал жазбасынан}} тегтерді аластау не қосу",
        "tags-edit-existing-tags": "Бар тегтер:",
-       "tags-edit-existing-tags-none": "«Ештеңе»",
+       "tags-edit-existing-tags-none": "<em>Ештеңе</em>",
        "tags-edit-new-tags": "Жаңа тегтер:",
        "tags-edit-add": "Мына тегтерді қосу:",
        "tags-edit-remove": "Мына тегтерді аластау:",
        "tags-edit-reason": "Себебі:",
        "tags-edit-revision-submit": "{{PLURAL:$1|Бұл нұсқадағы|$1 нұсқадағы}} өзгерістерді қолдану",
        "tags-edit-logentry-submit": "{{PLURAL:$1|Бұл журнал жазбасындағы|$1 журнал жазбасындағы}} өзгерістерді қолдану",
-       "tags-edit-success": "Өзгерістер сәтті қолданылды.",
+       "tags-edit-success": "Өзгерістер қолданылды.",
        "tags-edit-failure": "Өзгерістер қолданылмады: $1",
        "tags-edit-nooldid-title": "Нысана түзету жарамсыз",
        "tags-edit-nooldid-text": "Бұл функцияны орындау үшін толық нұсқасын сұрамағансыз немесе көрсетілген нұсқа жоқ.",
        "api-error-badaccess-groups": "Сізге бұл уикиге файл жүктеуге рұқсат етілмеген.",
        "api-error-badtoken": "Ішкі қате: Жаман байрақша",
        "api-error-copyuploaddisabled": "URL бойынша жүктеу бұл серверде өшірілген",
-       "api-error-duplicate": "{{PLURAL:$1|басқа файл|кейбір басқа файл}} әлеқашан сайтта басқа мазмұнда бар.",
+       "api-error-duplicate": "{{PLURAL:$1|басқа [$2 файл]|кейбір [$2 басқа файл]}} әлеқашан сайтта ,бірдей мазмұнда бар.",
        "api-error-empty-file": "Сіз жіберген файл бос.",
        "api-error-emptypage": "Бос бетті жаңадан бастау рұқсат етілмейді.",
        "api-error-fetchfileerror": "Ішкі қателік: Файлды алу барысында қате кетті.",
        "api-error-unknownerror": "Белгісіз қате: \"$1\".",
        "api-error-uploaddisabled": "Бұл уикиде жүктеп беру өшірілген.",
        "api-error-verification-error": "Бұл файл бүлінген болуы мүмкін немесе теріс кеңейтуі бар.",
-       "duration-seconds": "$1 {{PLURAL:$1|секунт|секунт}}",
+       "duration-seconds": "$1 {{PLURAL:$1|секунд|секунд}}",
        "duration-minutes": "$1 {{PLURAL:$1|минут|минут}}",
        "duration-hours": "$1 {{PLURAL:$1|сағат|сағат}}",
        "duration-days": "$1 {{PLURAL:$1|күн|күн}}",
        "rotate-comment": "Сурет сағат бағытымен $1 {{PLURAL:$1|бұрыш|бұрыш}} айналды",
        "limitreport-title": "Деректер анализаторы:",
        "limitreport-cputime": "CPU уақытында қолданылуы",
-       "limitreport-cputime-value": "$1 {{PLURAL:$1|секунт|секунт}}",
+       "limitreport-cputime-value": "$1 {{PLURAL:$1|секунд|секунд}}",
        "limitreport-walltime": "Нақты уақытта қолданылуы",
-       "limitreport-walltime-value": "$1 {{PLURAL:$1|секунт|секунт}}",
+       "limitreport-walltime-value": "$1 {{PLURAL:$1|секунд|секунд}}",
        "limitreport-ppvisitednodes": "Аралаған түйіндер саны",
        "limitreport-ppgeneratednodes": "Препроцессордың жинақталатын түйіндерінің саны",
        "limitreport-postexpandincludesize": "Кірістірілген ашық мөлшері",
        "expand_templates_preview": "Қарап шығу",
        "expand_templates_preview_fail_html": "<em>Мұнда сессия деректері жоғалған, себебі {{SITENAME}} жобасында HTML іске қосылған, JavaScript шабуылдарына қарсы сақтық шарасы үшін алдын ала қарап шығу жасырылған.</em>\n\n<strong>Егер бұл өңдеме адал ниетті әрекет болса қайта байқап көріңіз.</strong> \nЕгер бұл әлі істемесе жүйеден [[Special:UserLogout|шығып]] қайта кіріп көріңіз.",
        "expand_templates_preview_fail_html_anon": "<em>JavaScript шабуылдарына қарсы сақтық шарасы үшін алдын ала қарап шығу жасырылған, себебі {{SITENAME}} жобасында HTML іске қосылған және сіз жүйеге кірмегенсіз,.</em>\n\n<strong>Егер бұл өңдеме адал ниетті әрекет болса қайта байқап көріңіз.</strong> \nЕгер бұл әлі істемесе, жүйеге [[Special:UserLogin|кіріп]] қайта байқап көріңіз.",
-       "pagelanguage": "ТÑ\96л Ñ\82аңдаÑ\83 Ð±ÐµÑ\82Ñ\96",
+       "pagelanguage": "Ð\91еÑ\82 Ñ\82Ñ\96лÑ\96н Ó©Ð·Ð³ÐµÑ\80Ñ\82Ñ\83",
        "pagelang-name": "Бет",
        "pagelang-language": "Тіл",
        "pagelang-use-default": "Әдепкі тілді қолдану",
        "pagelang-submit": "Жөнелту",
        "right-pagelang": "Бет тілін аудару",
        "action-pagelang": "бет тілін аудару",
-       "log-name-pagelang": "Тіл журналын өзгерту",
+       "log-name-pagelang": "Тіл өзгерту журналы",
        "log-description-pagelang": "Бұл бет тілдерін өзгерту журналы.",
        "logentry-pagelang-pagelang": "$1 $3 беті үшін $4 дегеннен $5 дегенге бет тілін {{GENDER:$2|өзгертті}}.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (ендірілген)",
index 993f8de..a090015 100644 (file)
        "yourname": "ನಿಮ್ಮ ಬಳಕೆಯ ಹೆಸರು",
        "userlogin-yourname": "ಬಳಕೆದಾರ ಹೆಸರು",
        "userlogin-yourname-ph": "ನಿಮ್ಮ ಸದಸ್ಯನಾಮ ಬರೆಯಿರಿ",
-       "createacct-another-username-ph": "ಸದಸà³\8dಯನಾಮ (\"ಯà³\8bಸರà³\8dನà³\87ಮà³\8d\") à²¬à²°ಿರಿ",
+       "createacct-another-username-ph": "ಬಳà²\95à³\86ದಾರರ à²¹à³\86ಸರà³\81 à²¬à²°à³\86ಯಿರಿ",
        "yourpassword": "ನಿಮ್ಮ ಪ್ರವೇಶಪದ",
        "userlogin-yourpassword": "ಪ್ರವೇಶಪದ",
        "userlogin-yourpassword-ph": "ನಿಮ್ಮ ಪ್ರವೇಶಪದ ನಮೂದಿಸಿ",
        "createacct-realname": "ನಿಜವಾದ ಹೆಸರು (ಐಚ್ಛಿಕ)",
        "createaccountreason": "ಕಾರಣ:",
        "createacct-reason": "ಕಾರಣ",
-       "createacct-reason-ph": "ನà³\80ವà³\81 à²¯à²¾à²\95à³\86 à²\87ನà³\8dನà³\81 à²\92à²\82ದà³\81 à²\96ಾತ à²®à²¾à²¡à³\81ತ à²\87ದà³\8dದà³\80ರಿ ?",
+       "createacct-reason-ph": "ನà³\80ವà³\81 à²¯à²¾à²\95à³\86 à²\87ನà³\8dನà³\8aà²\82ದà³\81 à²\96ಾತà³\86 à²¤à³\86ರà³\86ಯà³\81ತà³\8dತಿದà³\8dದà³\80ರಿ",
        "createacct-submit": "ಖಾತೆಯನ್ನು ಸೃಷ್ಟಿಸಿ",
        "createacct-another-submit": "ಇನ್ನು ಒಂದು ಖಾತ ಮಾಡಿ",
-       "createacct-benefit-heading": "{{SITENAME}} à²¨à²¿à²®à³\8dಮನà³\8dತವà³\86 à²\9cನರಿà²\82ದ à²®à²¾à²¡à²¿à²¦à³\81",
+       "createacct-benefit-heading": "{{SITENAME}} à²¨à²¿à²®à³\8dಮà²\82ತಹ à²\9cನರಿà²\82ದಲà³\87 à²®à²¾à²¡à²¿à²¦à³\8dದà³\81.",
        "createacct-benefit-body1": "{{PLURAL:$1|ಸಂಪಾದನೆ|ಸಂಪಾದನೆಗಳು}}",
        "createacct-benefit-body2": "{{PLURAL:$1|ಪುಟ|ಪುಟಗಳು}}",
        "createacct-benefit-body3": "{{PLURAL:$1|ಕೊಡುಗೆ|ಕೊಡುಗೆಗಳು}}",
index 7ab3abb..b8106eb 100644 (file)
        "nocookieslogin": "{{SITENAME}}에서는 로그인을 위해 쿠키를 사용합니다.\n쿠키가 비활성되어 있습니다.\n쿠키 사용을 활성화한 다음 다시 시도하세요.",
        "nocookiesfornew": "요청의 출처를 확인할 수 없기 때문에 사용자 계정이 만들어지지 않았습니다.\n쿠키를 활성화한 것을 확인하고, 이 문서를 새로 고치고 나서 다시 시도하세요.",
        "noname": "사용자 계정 이름이 올바르지 않습니다.",
-       "loginsuccesstitle": "로그인 성공",
+       "loginsuccesstitle": "로그인",
        "loginsuccess": "<strong>{{SITENAME}}에 \"$1\" 계정으로 로그인했습니다.</strong>",
-       "nosuchuser": "\"$1\" 사용자가 존재하지 않습니다.\n사용자 계정 이름은 대소문자를 구별합니다.\n철자가 맞는지 확인해주세요. [[Special:UserLogin/signup|새 계정을 만들 수도 있습니다]].",
+       "nosuchuser": "이름이 \"$1\"인 사용자는 없습니다.\n사용자 계정 이름은 대소문자를 구별합니다.\n철자가 맞는지 확인해주세요. [[Special:UserLogin/signup|새 계정을 만들 수도 있습니다]].",
        "nosuchusershort": "이름이 \"$1\"인 사용자는 없습니다.\n철자가 맞는지 확인하세요.",
        "nouserspecified": "사용자 계정 이름을 입력하지 않았습니다.",
        "login-userblocked": "이 사용자는 차단되었습니다. 로그인할 수 없습니다.",
        "newpassword": "새 비밀번호:",
        "retypenew": "새 비밀번호 다시 입력:",
        "resetpass_submit": "비밀번호를 설정하고 로그인하기",
-       "changepassword-success": "비밀번호가 성공적으로 바뀌었습니다!",
+       "changepassword-success": "비밀번호가 바뀌었습니다!",
        "changepassword-throttled": "최근 너무 많이 로그인을 시도했습니다.\n$1 뒤에 다시 시도하세요.",
        "botpasswords": "봇 비밀번호",
        "botpasswords-disabled": "봇 비밀번호가 비활성화되었습니다.",
        "botpasswords-insert-failed": "\"$1\" 봇 이름을 추가하는데 실패했습니다. 이미 등록되지 않았는지 확인하기 바랍니다.",
        "botpasswords-update-failed": "\"$1\" 봇 이름을 갱신하는데 실패했습니다. 이미 삭제되지 않았는지 확인하기 바랍니다.",
        "botpasswords-created-title": "봇 비밀번호 생성",
-       "botpasswords-created-body": "\"$1\"의 봇 비밀번호가 성공적으로 만들어졌습니다.",
+       "botpasswords-created-body": "사용자 \"$2\"의 \"$1\"라는 이름의 봇 비밀번호가 만들어졌습니다.",
        "botpasswords-updated-title": "봇 비밀번호 갱신",
-       "botpasswords-updated-body": "\"$1\"의 봇 비밀번호가 성공적으로 갱신되었습니다.",
+       "botpasswords-updated-body": "사용자 \"$2\"의 \"$1\"라는 이름의 봇 비밀번호가 업데이트되었습니다.",
        "botpasswords-deleted-title": "봇 비밀번호 제거",
-       "botpasswords-deleted-body": "\"$1\"의 봇 비밀번호가 제거되었습니다.",
+       "botpasswords-deleted-body": "사용자 \"$2\"의 \"$1\"라는 이름의 봇 비밀번호가 삭제되었습니다.",
        "botpasswords-newpassword": "<strong>$1</strong> 계정의 비밀번호가 <strong>$2</strong>로 변경되었습니다. <em>잊어버리지 않도록 기록해두시기 바랍니다.</em>",
        "botpasswords-no-provider": "'BotPasswordsSessionProvider'는 이용할 수 없습니다.",
        "botpasswords-restriction-failed": "봇 비밀번호 제한으로 인해 로그인할 수 없습니다.",
        "resetpass-no-info": "이 특수 문서에 직접 접근하려면 반드시 로그인해야 합니다.",
        "resetpass-submit-loggedin": "비밀번호 바꾸기",
        "resetpass-submit-cancel": "취소",
-       "resetpass-wrong-oldpass": "비밀번호가 잘못되었거나 현재의 비밀번호와 같습니다.\n이미 비밀번호를 성공적으로 바꾸었거나 새 임시 비밀번호를 요청했을 수 있습니다.",
+       "resetpass-wrong-oldpass": "비밀번호가 잘못되었거나 현재의 비밀번호와 같습니다.\n이미 비밀번호를 바꾸었거나 새 임시 비밀번호를 요청했을 수 있습니다.",
        "resetpass-recycled": "현재 비밀번호와 다른 비밀번호로 재설정해주세요.",
        "resetpass-temp-emailed": "임시 이메일 코드로 로그인되어 있습니다.\n로그인을 마치려면, 여기서 새 비밀번호를 설정해야 합니다:",
        "resetpass-temp-password": "임시 비밀번호:",
        "previewerrortext": "변경사항을 미리보기하는 도중 오류가 발생했습니다.",
        "blockedtitle": "사용자가 차단됨",
        "blockedtext": "'''사용자 계정 또는 IP 주소가 차단되었습니다.'''\n\n차단한 사람은 $1입니다.\n차단한 이유는 다음과 같습니다: $2\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n[[Special:Preferences|계정 환경 설정]]에 올바른 이메일 주소가 있어야만 '이메일 보내기' 기능을 사용할 수 있습니다. 또 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n현재 당신의 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
-       "autoblockedtext": "당신의 IP 주소는 $1 사용자가 차단한 사용자가 사용했던 IP이기 때문에 자동으로 차단되었습니다.\n차단된 이유는 다음과 같습니다:\n\n:$2\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n\n[[Special:Preferences|계정 환경 설정]]에 올바른 이메일 주소가 있어야만 \"이메일 보내기\" 기능을 사용할 수 있습니다. 또한 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n\n현재 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
+       "autoblockedtext": "당신의 IP 주소는 $1님이 차단한 사용자가 사용했던 IP이기 때문에 자동으로 차단되었습니다.\n차단된 이유는 다음과 같습니다:\n\n:$2\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n\n[[Special:Preferences|계정 환경 설정]]에 올바른 이메일 주소가 있어야만 \"이메일 보내기\" 기능을 사용할 수 있습니다. 또한 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n\n현재 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
        "blockednoreason": "이유를 입력하지 않음",
        "whitelistedittext": "문서를 편집하기 전에 $1해야 합니다.",
        "confirmedittext": "문서를 고치려면 이메일 인증 절차가 필요합니다.\n[[Special:Preferences|사용자 환경 설정]]에서 이메일 주소를 입력하고 이메일 주소 인증을 해주시기 바랍니다.",
        "previewnote": "'''이 화면은 미리 보기입니다.'''\n편집한 내용은 아직 저장하지 않았습니다!",
        "continue-editing": "편집 영역으로 가기",
        "previewconflict": "이 미리 보기는 저장할 때의 모습으로 위쪽 편집창의 문서를 반영합니다.",
-       "session_fail_preview": "세션 데이터가 없어져 편집을 저장하지 못했습니다.\n\n로그아웃 되었는지도 모릅니다. '''아직 로그인 상태인지 확인하고 다시 시도해주세요.'''\n다시 시도해도 되지 않으면 [[Special:UserLogout|로그아웃]]한 다음 다시 로그인하세요. 그리고 브라우저 설정에서 쿠키 사용을 허용하는지 확인하세요.",
+       "session_fail_preview": "세션 데이터가 없어져 편집을 저장하지 못했습니다.\n\n로그아웃 되었는지도 모릅니다. <strong>아직 로그인 상태인지 확인하고 다시 시도해주세요</strong>.\n다시 시도해도 되지 않으면 [[Special:UserLogout|로그아웃]]한 다음 다시 로그인하세요. 그리고 브라우저 설정에서 쿠키 사용을 허용하는지 확인하세요.",
        "session_fail_preview_html": "세션 데이터가 없어져 편집을 저장하지 못했습니다.\n\n<em>{{SITENAME}}에서 HTML 입력을 허용하기 때문에, 자바스크립트 공격을 막기 위해 미리 보기는 숨겨져 있습니다.</em>\n\n<strong>적합하게 편집을 시도했다면 다시 시도해주세요.</strong>\n다시 시도해도 되지 않으면 [[Special:UserLogout|로그아웃]]한 다음 다시 로그인하고, 브라우저가 이 사이트에서 쿠키를 허용하는지 확인하세요.",
        "token_suffix_mismatch": "'''저장하려는 내용의 문장 부호가 망가져 있습니다.'''\n문서 보호를 위해 해당 내용을 저장하지 않습니다.\n버그가 있는 익명 프록시 서비스 등을 사용할 때 이런 문제가 발생할 수 있습니다.",
        "edit_form_incomplete": "'''편집의 일부 내용이 서버에 전달되지 않았습니다. 편집이 손상되지 않았는지 확인하고 다시 시도해 주십시오.'''",
        "copyrightwarning2": "{{SITENAME}}에서의 모든 기여는 다른 사용자가 편집, 수정, 삭제할 수 있다는 점을 유의해 주세요.\n만약 여기에 동의하지 않는다면, 문서를 저장하지 말아 주세요.<br />\n또한, 직접 작성했거나 퍼블릭 도메인과 같은 자유 문서에서 가져왔다는 것을 보증해야 합니다 (자세한 내용에 대해서는 $1 문서를 읽어 주세요).\n'''저작권이 있는 내용을 허가 없이 저장하지 마세요!'''",
        "editpage-cannot-use-custom-model": "이 문서의 콘텐츠 모델은 변경될 수 없습니다.",
        "longpageerror": "'''오류: 문서의 크기가 {{PLURAL:$1|$1킬로바이트}}로 최대 크기인 {{PLURAL:$2|$2킬로바이트}}보다 큽니다.'''\n저장할 수 없습니다.",
-       "readonlywarning": "<strong>경고: 데이터베이스가 관리를 위해 잠겨 있습니다. 따라서 문서를 편집한 내용을 지금 저장할 수 없습니다.</strong>\n편집 내용을 복사하여 붙여넣기 등을 사용하여 일단 다른 곳에 저장한 후, 나중에 다시 시도해 주세요.\n\n잠근 관리자가 남긴 설명은 다음과 같습니다: $1",
+       "readonlywarning": "<strong>경고: 데이터베이스가 관리를 위해 잠겨 있습니다. 따라서 문서를 편집한 내용을 지금 저장할 수 없습니다.</strong>\n편집 내용을 복사하여 붙여넣기 등을 사용하여 일단 다른 곳에 저장한 후, 나중에 다시 시도해 주세요.\n\n데이터베이스를 잠근 시스템 관리자가 남긴 설명은 다음과 같습니다: $1",
        "protectedpagewarning": "<strong>경고: 이 문서는 관리자 권한이 있는 사용자만 편집할 수 있도록 보호되어 있습니다.</strong>\n이 문서의 최근 기록을 참조하십시오:",
        "semiprotectedpagewarning": "<strong>참고:</strong> 이 문서는 계정을 등록한 사용자만이 편집할 수 있도록 보호되어 있습니다.\n이 문서의 최근 기록을 참조하십시오:",
        "cascadeprotectedwarning": "<strong>경고:</strong> 이 문서는 보호되어 있어 관리자만 편집할 수 있습니다. 연쇄적 보호가 걸린 다음 {{PLURAL:$1|문서}}에서 이 문서를 사용하고 있습니다:",
        "revdelete-unsuppress": "되살린 판에 대한 제한을 해제",
        "revdelete-log": "이유:",
        "revdelete-submit": "선택한 {{PLURAL:$1|판}}에 적용",
-       "revdelete-success": "'''판의 보이기 설정을 성공적으로 바꾸었습니다.'''",
+       "revdelete-success": "판의 보이기 설정을 바꾸었습니다.",
        "revdelete-failure": "'''특정 판 보기 설정을 바꾸지 못했습니다:'''\n$1",
-       "logdelete-success": "'''기록 보이기 설정을 성공적으로 바꾸었습니다.'''",
+       "logdelete-success": "기록 보이기를 설정했습니다.",
        "logdelete-failure": "'''기록 보이기 설정을 바꾸지 못했습니다:'''\n$1",
        "revdel-restore": "보이기 설정 바꾸기",
        "pagehist": "문서 역사",
        "userrights-changeable-col": "바꿀 수 있는 권한",
        "userrights-unchangeable-col": "바꿀 수 없는 권한",
        "userrights-conflict": "사용자 권한 바꾸기가 충돌합니다! 바뀜을 검토하고 확인하세요.",
-       "userrights-removed-self": "ì\9e\90ì\8b ì\9d\98 ê¶\8cí\95\9cì\9d\84 ì \9cê±°í\95\98ë\8a\94 ë\8d° ì\84±ê³µí\96\88ì\8aµë\8b\88ë\8b¤. ë\94°ë\9d¼ì\84\9c ë\8d\94 ì\9d´ì\83\81 ì\9d´ ë¬¸ì\84\9cì\97\90 ì \91ê·¼í\95  ì\88\98 ì\97\86ì\8aµë\8b\88ë\8b¤.",
+       "userrights-removed-self": "자신의 권한을 제거했습니다. 따라서 더 이상 이 문서에 접근할 수 없습니다.",
        "group": "그룹:",
        "group-user": "사용자",
        "group-autoconfirmed": "자동 인증된 사용자",
        "foreign-structured-upload-form-label-own-work": "자작입니다",
        "foreign-structured-upload-form-label-infoform-categories": "분류",
        "foreign-structured-upload-form-label-infoform-date": "날짜",
-       "foreign-structured-upload-form-label-not-own-work-message-shared": "이 파일의 저작권을 소유하지 않거나 다른 라이선스로 배포하고 싶다면 [https://commons.wikimedia.org/wiki/Special:UploadWizard 공용 파일 올리기 마법사]를 이용해 보세요.",
+       "foreign-structured-upload-form-label-own-work-message-shared": "나는 이 파일에 대한 저작권을 소유하고 있음을 입증하고, 영구히 위키미디어 공용에 이 파일을 [https://creativecommons.org/licenses/by-sa/4.0/ 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0]에 따라 배포하는 데 동의하며, [https://wikimediafoundation.org/wiki/Terms_of_Use 이용 약관]에 동의합니다.",
+       "foreign-structured-upload-form-label-not-own-work-message-shared": "이 파일의 저작권을 소유하지 않거나 다른 라이선스로 배포하고 싶다면 [https://commons.wikimedia.org/wiki/Special:UploadWizard 공용 파일 올리기 마법사]를 사용하는 것을 고려해보세요.",
        "backend-fail-stream": "\"$1\" 파일을 스트림할 수 없습니다.",
        "backend-fail-backup": "\"$1\" 파일을 백업할 수 없습니다.",
        "backend-fail-notexists": "$1 파일이 존재하지 않습니다.",
        "backend-fail-read": "\"$1\" 파일을 읽을 수 없습니다.",
        "backend-fail-create": "\"$1\" 파일을 저장할 수 없습니다.",
        "backend-fail-maxsize": "{{PLURAL:$2|1 바이트|$2 바이트}}보다 커서 \"$1\" 파일을 저장하지 못했습니다.",
-       "backend-fail-readonly": "\"$1\" 저장 백엔드가 읽기 전용입니다. 자세한 이유는 다음과 같습니다: \"$2\"",
+       "backend-fail-readonly": "\"$1\" 저장 백엔드가 읽기 전용입니다. 자세한 이유는 다음과 같습니다: <em>$2</em>",
        "backend-fail-synced": "\"$1\" 파일은 내부 저장 백엔드에 불안정한 상태로 있습니다",
        "backend-fail-connect": "\"$1\" 저장 백엔드에 접속하지 못했습니다.",
        "backend-fail-internal": "\"$1\" 저장 백엔드에 알 수 없는 오류가 발생했습니다.",
        "lockmanager-fail-deletelock": "\"$1\"에 대한 잠금 파일을 삭제하지 못했습니다.",
        "lockmanager-fail-acquirelock": "\"$1\"에 대한 잠금이 실패했습니다.",
        "lockmanager-fail-openlock": "\"$1\"에 대한 잠금 파일을 열지 못했습니다.",
-       "lockmanager-fail-releaselock": "\"$1\"ì\97\90 ë\8c\80í\95\9c ì\9e ê¸\88ì\9d\84 í\95´ì \9cí\95\98지 못했습니다.",
+       "lockmanager-fail-releaselock": "\"$1\"ì\97\90 ë\8c\80í\95\9c ì\9e ê¸\88ì\9d\84 í\92\80지 못했습니다.",
        "lockmanager-fail-db-bucket": "데이터베이스의 버킷 $1의 잠금을 풀지 못했습니다.",
        "lockmanager-fail-db-release": "데이터베이스 $1의 잠금을 풀지 못했습니다.",
        "lockmanager-fail-svr-acquire": "서버 $1의 잠금을 걸지 못했습니다.",
        "uploadstash-summary": "이 문서는 위키에 등록되지는 않았지만 올리는 과정 중에 있는 파일을 접근할 수 있습니다. 이 파일은 올린이 외에는 볼 수 없습니다.",
        "uploadstash-clear": "임시 저장한 파일 제거하기",
        "uploadstash-nofiles": "임시 저장한 파일이 없습니다.",
-       "uploadstash-badtoken": "ì\9d´ ë\8f\99ì\9e\91ì\9d\84 ì\88\98í\96\89í\95\98ë\8a\94 ë\8d° ì\8b¤í\8c¨í\96\88ì\8aµë\8b\88ë\8b¤. í\8e¸ì§\91 í\86 í\81°ì\9d´ ë§\8cë£\8cë\90\98ì\97\88ì\9d\84 ê°\80ë\8a¥ì\84±ì\9d´ ì\9e\88ì\8aµë\8b\88ë\8b¤. ë\8b¤ì\8b\9c ì\8b\9cë\8f\84í\95\98세요.",
-       "uploadstash-errclear": "í\8c\8cì\9d¼ì\9d\84 ì \9cê±°í\95\98는 데 실패했습니다.",
+       "uploadstash-badtoken": "ì\9d´ ë\8f\99ì\9e\91ì\9d\84 ì\88\98í\96\89í\95\98ë\8a\94 ë\8d° ì\8b¤í\8c¨í\96\88ì\8aµë\8b\88ë\8b¤. í\8e¸ì§\91 í\86 í\81°ì\9d´ ë§\8cë£\8cë\90\98ì\97\88ì\9d\84 ê°\80ë\8a¥ì\84±ì\9d´ ì\9e\88ì\8aµë\8b\88ë\8b¤. ë\8b¤ì\8b\9c ì\8b\9cë\8f\84í\95´ì£¼세요.",
+       "uploadstash-errclear": "í\8c\8cì\9d¼ì\9d\84 ì§\80ì\9a°는 데 실패했습니다.",
        "uploadstash-refresh": "파일 목록을 새로 고침",
        "invalid-chunk-offset": "청크 오프셋이 잘못되었습니다.",
        "img-auth-accessdenied": "접근이 거부됨",
        "apihelp-no-such-module": "\"$1\" 모듈을 찾을 수 없습니다.",
        "apisandbox": "API 실험실",
        "apisandbox-api-disabled": "이 사이트에서는 API가 꺼져 있습니다.",
-       "apisandbox-intro": "'''미디어위키 웹 서비스 API'''를 시험해보려면 이 페이지를 이용해보세요. API 용법에 대해서는 [//www.mediawiki.org/wiki/API:Main_page API 문서]을 참고하십시오. 예: [//www.mediawiki.org/wiki/API#A_simple_example 대문의 내용 요청하기]. 더 많은 예를 보려면 액션을 선택하세요.\n\n여기가 연습장이라도 이 페이지에서 실행하는 동작때문에 위키를 변경할 수도 있다는 점에 유의하십시오.",
+       "apisandbox-intro": "<strong>미디어위키 웹 서비스 API</strong>를 시험해보려면 이 페이지를 이용해보세요. API 용법에 대해서는 [[mw:API:Main page|API 문서]]을 참고하십시오. 예: [//www.mediawiki.org/wiki/API#A_simple_example 대문의 내용 요청하기]. 더 많은 예를 보려면 액션을 선택하세요.\n\n여기가 연습장이라도 이 페이지에서 실행하는 동작때문에 위키를 변경할 수도 있다는 점에 유의하십시오.",
        "apisandbox-fullscreen": "패널 늘리기",
        "apisandbox-fullscreen-tooltip": "브라우저 창에 맞도록 샌드박스 패널 늘리기",
        "apisandbox-unfullscreen": "페이지 보기",
        "listgrouprights-namespaceprotection-namespace": "이름공간",
        "listgrouprights-namespaceprotection-restrictedto": "사용자가 편집할 수 있는 권한",
        "listgrants": "부여",
-       "listgrants-summary": "다음은 사용자 권한에 관련된 접근 권한을 통해 부여된 OAuth 부여 목록입니다. 사용자는 자신의 계정에 대해 권한을 부여 할 수 있지만, 사용자가 응용 프로그램에 부여한 권한 설정에 따라 제한이 있습니다. 사용자를 대신하여 동작하는 응용 프로그램은 사용자가 갖고 있지 않은 권한은 사용할 수 없습니다. \n각각의 권한에 대한 [[{{MediaWiki:Listgrouprights-helppage}}|추가 정보]]가 있습니다.",
+       "listgrants-summary": "다음은 사용자 권한에 관련된 접근 권한을 통해 부여된 부여 목록입니다. 사용자는 자신의 계정에 대해 권한을 부여 할 수 있지만, 사용자가 애플리케이션에 부여한 권한 설정에 따라 제한이 있습니다. 사용자를 대신하여 동작하는 애플리케이션은 사용자가 갖고 있지 않은 권한은 사용할 수 없습니다. \n각각의 권한에 대한 [[{{MediaWiki:Listgrouprights-helppage}}|추가 정보]]가 있습니다.",
        "listgrants-grant": "부여",
        "listgrants-rights": "권한",
        "trackingcategories": "추적용 분류",
        "emailccsubject": "$1에게 보낸 메시지의 복사본: $2",
        "emailsent": "이메일 보냄",
        "emailsenttext": "이메일을 보냈습니다.",
-       "emailuserfooter": "이 이메일은 {{SITENAME}}의 $1 사용자가 $2 사용자에게 \"{{int:emailuser}}\" 기능을 통해 보냈습니다.",
+       "emailuserfooter": "이 이메일은 {{SITENAME}}의 $1님이 $2 사용자에게 \"{{int:emailuser}}\" 기능을 통해 보냈습니다.",
        "usermessage-summary": "시스템 메시지 남기기",
        "usermessage-editor": "시스템 메신저",
        "usermessage-template": "MediaWiki:UserMessage",
        "delete-toobig": "이 문서에는 {{PLURAL:$1|편집 역사}}가 $1개 이상 있습니다.\n{{SITENAME}}에 의도하지 않은 혼란을 줄 수 있기 때문에 이런 문서의 삭제는 제한됩니다.",
        "delete-warning-toobig": "이 문서에는 {{PLURAL:$1|편집 역사}}가 $1개 있습니다.\n편집 역사가 긴 문서를 삭제하면 {{SITENAME}} 데이터베이스 동작에 큰 영향을 줄 수 있습니다.\n주의해 주세요.",
        "deleteprotected": "이 문서가 보호되어 있기 때문에 삭제할 수 없습니다.",
-       "deleting-backlinks-warning": "'''경고:''' 삭제하려는 문서가 [[Special:WhatLinksHere/{{FULLPAGENAME}}|다른 문서]]에 링크되어 있거나 끼워져 있습니다.",
+       "deleting-backlinks-warning": "<strong>경고:</strong> 삭제하려는 문서가 [[Special:WhatLinksHere/{{FULLPAGENAME}}|다른 문서]]에 링크되어 있거나 끼워져 있습니다.",
        "rollback": "편집 되돌리기",
        "rollbacklink": "되돌리기",
        "rollbacklinkcount": "{{PLURAL:$1|편집}} $1회 되돌리기",
        "changecontentmodel-title-label": "문서 제목",
        "changecontentmodel-model-label": "새 콘텐츠 모델",
        "changecontentmodel-reason-label": "이유:",
+       "changecontentmodel-submit": "바꾸기",
        "changecontentmodel-success-title": "콘텐츠 모델이 변경되었습니다",
        "changecontentmodel-success-text": "[[:$1]]의 콘텐츠 종류가 변경되었습니다.",
        "changecontentmodel-cannot-convert": "[[:$1]]의 콘텐츠 모델이 $2의 모델로 전환될 수 없습니다.",
        "changecontentmodel-nodirectediting": "$1 콘텐츠 모델은 직접 편집을 지원하지 않습니다",
        "log-name-contentmodel": "콘텐츠 모델 변경 기록",
        "log-description-contentmodel": "페이지의 콘텐츠 모델과 관련된 행위",
-       "logentry-contentmodel-change": "$1 사용자가 $3 의 콘텐츠 모델을 \"$4\"에서 \"$5\"로 {{GENDER:$2|변경하였습니다}}.",
+       "logentry-contentmodel-new": "$1님이 비 기본값 \"$5\" 콘텐츠 모델을 사용해  $3 문서를 {{GENDER:$2|만들었습니다}}",
+       "logentry-contentmodel-change": "$1님이 $3 문서의 콘텐츠 모델을 \"$4\"에서 \"$5\"로 {{GENDER:$2|바꾸었습니다}}",
        "logentry-contentmodel-change-revertlink": "되돌리기",
        "logentry-contentmodel-change-revert": "되돌리기",
        "protectlogpage": "문서 보호 기록",
        "tooltip-namespace_association": "선택한 이름공간과 관련된 토론이나 본문 이름공간을 포함하려면 이 상자를 선택하세요",
        "blanknamespace": "(일반)",
        "contributions": "{{GENDER:$1|사용자}} 기여",
-       "contributions-title": "$1 사용자의 기여",
+       "contributions-title": "$1의 사용자 기여",
        "mycontris": "기여",
        "anoncontribs": "기여",
        "contribsub2": "{{GENDER:$3|$1}}($2)의 기여",
        "change-blocklink": "차단 설정 바꾸기",
        "contribslink": "기여",
        "emaillink": "이메일 보내기",
-       "autoblocker": "당신의 IP 주소는 최근에 \"[[User:$1|$1]]\" 사용자가 사용하였기 때문에 자동으로 차단되었습니다.\n$1 사용자가 차단된 이유는 다음과 같습니다: \"$2\"",
+       "autoblocker": "당신의 IP 주소는 최근에 \"[[User:$1|$1]]\" 사용자가 사용하였기 때문에 자동으로 차단되었습니다.\n$1님이 차단된 이유는 다음과 같습니다: \"$2\"",
        "blocklogpage": "차단 기록",
        "blocklog-showlog": "이 사용자는 과거에 차단된 기록이 있습니다.\n해당 사용자의 차단 기록은 다음과 같습니다:",
        "blocklog-showsuppresslog": "이 사용자는 과거에 차단된 적이 있으며, 그 기록이 숨겨져 있습니다.\n해당 사용자의 차단 기록은 다음과 같습니다:",
-       "blocklogentry": "사용자가 [[$1]] 사용자를 $2 차단했습니다 $3",
-       "reblock-logentry": "사용자가 [[$1]] 사용자의 차단 기간을 $2(으)로 바꾸었습니다 $3",
+       "blocklogentry": "님이 [[$1]]님을 $2 차단했습니다 $3",
+       "reblock-logentry": "님이 [[$1]]님의 차단 기간을 $2(으)로 바꾸었습니다 $3",
        "blocklogtext": "이 목록은 사용자 차단/차단 해제 기록입니다.\n자동으로 차단된 IP 주소는 여기에 나오지 않습니다.\n[[Special:BlockList|여기]]에서 현재 차단된 사용자 목록을 볼 수 있습니다.",
-       "unblocklogentry": "사용자가 $1 사용자를 차단 해제했습니다",
+       "unblocklogentry": "님이 $1님을 차단 해제했습니다",
        "block-log-flags-anononly": "IP만 막음",
        "block-log-flags-nocreate": "계정 만들기 금지됨",
        "block-log-flags-noautoblock": "자동 차단 비활성화됨",
        "ipb_expiry_old": "기한을 과거로 입력했습니다.",
        "ipb_expiry_temp": "사용자 이름을 숨기는 차단은 반드시 무기한이어야 합니다.",
        "ipb_hide_invalid": "해당 계정은 막을 수 없습니다. {{PLURAL:$1|1회|$1회}} 이상 편집했습니다.",
-       "ipb_already_blocked": "\"$1\" 사용자는 이미 차단되었습니다",
-       "ipb-needreblock": "$1 사용자는 이미 차단되었습니다. 차단 설정을 바꾸시겠습니까?",
+       "ipb_already_blocked": "\"$1\"님은 이미 차단되었습니다.",
+       "ipb-needreblock": "$1님은 이미 차단되었습니다. 차단 설정을 바꾸시겠습니까?",
        "ipb-otherblocks-header": "다른 {{PLURAL:$1|차단}} 기록",
        "unblock-hideuser": "이 사용자 이름이 숨겨져 있기 때문에 이 사용자를 차단 해제할 수 없습니다.",
        "ipb_cant_unblock": "오류: $1 차단 ID가 존재하지 않습니다. 이미 차단 해제되었을 수 있습니다.",
        "import-nonewrevisions": "가져온 판 없음(모든 판이 이미 존재하거나 오류로 인해 건너뛰었을 수도 있습니다.)",
        "xml-error-string": "$3단 $2줄 (바이트 $4)에서 $1: $5",
        "import-upload": "XML 데이터 올리기",
-       "import-token-mismatch": "세션 데이터가 손실되었습니다.\n다시 시도하세요.",
+       "import-token-mismatch": "세션 데이터가 손실되었습니다.\n\n로그아웃 되었는지도 모릅니다. <strong>아직 로그인 상태인지 확인하고 다시 시도해주세요</strong>.\n다시 시도해도 되지 않으면 [[Special:UserLogout|로그아웃]]한 다음 다시 로그인하세요. 그리고 브라우저 설정에서 쿠키 사용을 허용하는지 확인하세요.",
        "import-invalid-interwiki": "해당 위키에서 문서를 가져올 수 없습니다.",
        "import-error-edit": "문서를 편집할 수 없기 때문에 \"$1\" 문서를 가져올 수 없었습니다.",
        "import-error-create": "문서를 만들 수 없기 때문에 \"$1\" 문서를 가져올 수 없었습니다.",
        "import-logentry-upload-detail": "{{PLURAL:$1|판}} $1개를 가져왔습니다",
        "import-logentry-interwiki-detail": "$2에서 {{PLURAL:$1|판}} $1개를 가져왔습니다",
        "javascripttest": "자바스크립트 테스트",
-       "javascripttest-pagetext-noframework": "이 문서는 자바스크립트 테스트를 실행하기 위한 용도로 할당되어 있습니다.",
-       "javascripttest-pagetext-unknownframework": "실험용 프레임워크 \"$1\"를 알 수 없습니다.",
        "javascripttest-pagetext-unknownaction": "알 수 없는 동작 \"$1\".",
-       "javascripttest-pagetext-frameworks": "다음 실험용 프레임워크 중 하나를 선택하세요: $1",
-       "javascripttest-pagetext-skins": "실험할 스킨을 선택하세요:",
        "javascripttest-qunit-intro": "mediawiki.org의 [$1 테스트 설명서]를 참고하세요.",
        "tooltip-pt-userpage": "{{GENDER:|내 사용자}} 문서",
        "tooltip-pt-anonuserpage": "현재 사용하는 IP 주소의 사용자 문서",
        "pageinfo-visiting-watchers": "이 문서를 최근에 방문한 주시하는 사용자 수",
        "pageinfo-few-watchers": "{{PLURAL:$1|주시하는 사용자}} $1명보다 적음",
        "pageinfo-redirects-name": "이 문서의 넘겨주기 수",
-       "pageinfo-redirects-value": "$1",
+       "pageinfo-redirects-value": "$1",
        "pageinfo-subpages-name": "이 문서의 하위 문서 수",
        "pageinfo-subpages-value": "$1개 ({{PLURAL:$2|넘겨주기}} $2개, {{PLURAL:$3|넘겨주기 아님}} $3개)",
        "pageinfo-firstuser": "문서 작성자",
        "exif-compression-32946": "수축 (PKZIP)",
        "exif-copyrighted-true": "저작권의 보호를 받음",
        "exif-copyrighted-false": "저작권 상태를 설정하지 않음",
+       "exif-photometricinterpretation-0": "흑백 (백은 0)",
        "exif-photometricinterpretation-1": "검은색과 흰색 (검은색이 0)",
+       "exif-photometricinterpretation-3": "팔레트",
+       "exif-photometricinterpretation-4": "투명 마스크",
+       "exif-photometricinterpretation-5": "분리 (아마도 CMYK)",
+       "exif-photometricinterpretation-9": "CIE L*a*b* (ICC 인코딩)",
+       "exif-photometricinterpretation-10": "CIE L*a*b* (ITU 인코딩)",
+       "exif-photometricinterpretation-32803": "컬러 필터 어레이",
        "exif-unknowndate": "날짜를 알 수 없음",
        "exif-orientation-1": "일반",
        "exif-orientation-2": "수평으로 뒤집음",
        "autoredircomment": "[[$1]] 문서로 넘겨주기",
        "autosumm-new": "새 문서: $1",
        "autosumm-newblank": "빈 문서를 만듦",
+       "size-bytes": "$1 {{PLURAL:$1|바이트}}",
+       "size-pixel": "$1 {{PLURAL:$1|픽셀}}",
        "lag-warn-normal": "최근 $1{{PLURAL:$1|초}} 안에 바뀐 문서는 이 목록에서 빠졌을 수 있습니다.",
        "lag-warn-high": "데이터베이스 서버의 과도한 부하 때문에 최근 $1{{PLURAL:$1|초}} 안에 바뀐 문서 목록은 보이지 않을 수 있습니다.",
        "watchlistedit-normal-title": "주시문서 목록 편집하기",
        "version-libraries-description": "설명",
        "version-libraries-authors": "저자",
        "redirect": "파일, 사용자 ID, 문서 ID, 판 ID나 로그 ID로 넘겨주기",
-       "redirect-legend": "파일이나 문서로 넘겨주기",
        "redirect-summary": "이 특수 문서는 파일(파일 이름이 주어짐), 문서(판 ID나 문서 ID가 주어짐), 사용자 문서(숫자로 표시된 사용자 ID가 주어짐)나 로그 항목(로그 ID가 주어짐)으로 넘겨줍니다. 사용법: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], 또는 [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "보기",
        "redirect-lookup": "찾을 종류:",
        "tags-edit-revision-legend": "{{PLURAL:$1|이 판|$1개 판 모두}}에 태그를 추가하거나 제거",
        "tags-edit-logentry-legend": "{{PLURAL:$1|이 기록|$1개 기록 모두}}에 태그를 추가하거나 제거",
        "tags-edit-existing-tags": "기존 태그:",
-       "tags-edit-existing-tags-none": "''없음''",
+       "tags-edit-existing-tags-none": "<em>없음</em>",
        "tags-edit-new-tags": "새 태그:",
        "tags-edit-add": "다음 태그를 추가:",
        "tags-edit-remove": "다음 태그를 제거:",
        "tags-edit-chosen-no-results": "일치하는 태그를 찾을 수 없습니다",
        "tags-edit-reason": "이유:",
        "tags-edit-revision-submit": "{{PLURAL:$1|이 판|$1개 판}}에 수정 사항을 적용",
-       "tags-edit-logentry-submit": "{{PLURAL:$1|이 기록|$1개 기록}}에 수정 사항을 적용",
-       "tags-edit-success": "수정사항이 성공적으로 적용되었습니다.",
+       "tags-edit-logentry-submit": "{{PLURAL:$1|이 기록 항목|$1개 기록 항목}}에 수정 사항을 적용",
+       "tags-edit-success": "바뀜이 적용되었습니다.",
        "tags-edit-failure": "수정 사항이 적용될 수 없습니다: $1",
        "tags-edit-nooldid-title": "대상 판이 잘못되었습니다",
        "tags-edit-nooldid-text": "이 기능을 수행할 특정 판을 제시하지 않았거나 해당 판이 없습니다.",
        "htmlform-user-not-valid": "<strong>$1</strong>은 올바른 사용자 이름이 아닙니다.",
        "sqlite-has-fts": "$1 (본문 전체 검색 지원)",
        "sqlite-no-fts": "$1 (본문 전체 검색 지원 제외)",
-       "logentry-delete-delete": "$1 사용자가 $3 문서를 {{GENDER:$2|삭제했습니다}}",
-       "logentry-delete-restore": "$1 사용자가 $3 문서를 {{GENDER:$2|되살렸습니다}}",
-       "logentry-delete-event": "$1 사용자가 $3의 {{PLURAL:$1|기록 $5개}}에 대해 보이기 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
-       "logentry-delete-revision": "$1 사용자가 $3 문서의 {{PLURAL:$5|$5개 편집}}의 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
-       "logentry-delete-event-legacy": "$1 사용자가 $3 문서 기록의 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
-       "logentry-delete-revision-legacy": "$1 사용자가 $3 문서 편집의 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
-       "logentry-suppress-delete": "$1 사용자가 $3 문서를 {{GENDER:$2|숨겼습니다}}",
-       "logentry-suppress-event": "$1 사용자가 비공개적으로 $3의 {{PLURAL:$5|기록 $5개}}에 대해 보이기 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
-       "logentry-suppress-revision": "$1 사용자가 비공개적으로 $3 문서의 {{PLURAL:$5|판 $5개}}에 대해 보이기 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
-       "logentry-suppress-event-legacy": "$1 사용자가 비공개적으로 $3의 항목에 대한 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
-       "logentry-suppress-revision-legacy": "$1 사용자가 비공개적으로 $3 문서의 특정 판에 대한 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
+       "logentry-delete-delete": "$1님이 $3 문서를 {{GENDER:$2|삭제했습니다}}",
+       "logentry-delete-restore": "$1님이 $3 문서를 {{GENDER:$2|되살렸습니다}}",
+       "logentry-delete-event": "$1님이 $3의 {{PLURAL:$1|기록 $5개}}에 대해 보이기 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
+       "logentry-delete-revision": "$1님이 $3 문서의 {{PLURAL:$5|$5개 편집}}의 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
+       "logentry-delete-event-legacy": "$1님이 $3 문서 기록의 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
+       "logentry-delete-revision-legacy": "$1님이 $3 문서 편집의 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
+       "logentry-suppress-delete": "$1님이 $3 문서를 {{GENDER:$2|숨겼습니다}}",
+       "logentry-suppress-event": "$1님이 비공개적으로 $3의 {{PLURAL:$5|기록 $5개}}에 대해 보이기 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
+       "logentry-suppress-revision": "$1님이 비공개적으로 $3 문서의 {{PLURAL:$5|판 $5개}}에 대해 보이기 설정을 {{GENDER:$2|바꾸었습니다}}: $4",
+       "logentry-suppress-event-legacy": "$1님이 비공개적으로 $3의 항목에 대한 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
+       "logentry-suppress-revision-legacy": "$1님이 비공개적으로 $3 문서의 특정 판에 대한 보이기 설정을 {{GENDER:$2|바꾸었습니다}}",
        "revdelete-content-hid": "내용 숨겨짐",
        "revdelete-summary-hid": "편집 요약 숨겨짐",
        "revdelete-uname-hid": "사용자 이름 숨겨짐",
        "revdelete-uname-unhid": "사용자 이름 숨김 해제됨",
        "revdelete-restricted": "관리자에게 제한을 적용함",
        "revdelete-unrestricted": "관리자에 대한 제한을 해제함",
-       "logentry-block-block": "$1 {{GENDER:$2|사용자가}} {{GENDER:$4|$3}} 사용자를 $5 $6 설정으로 차단했습니다.",
-       "logentry-block-unblock": "$1 {{GENDER:$2|사용자가}} {{GENDER:$4|$3}} 사용자의 차단을 해제했습니다.",
-       "logentry-block-reblock": "$1 {{GENDER:$2|사용자가}} {{GENDER:$4|$3}} 사용자의 차단을 $5 $6 설정으로 변경했습니다.",
-       "logentry-suppress-block": "$1 {{GENDER:$2|사용자가}} {{GENDER:$4|$3}} 사용자를 $5 $6 설정으로 차단했습니다.",
-       "logentry-suppress-reblock": "$1 {{GENDER:$2|사용자가}} {{GENDER:$4|$3}} 사용자의 차단을 $5 $6 설정으로 변경했습니다.",
-       "logentry-import-upload": "$1 사용자가 $3 문서를 파일 올리기로 {{GENDER:$2|가져왔습니다}}",
-       "logentry-import-interwiki": "$1 사용자가 $3을 다른 위키에서 {{GENDER:$2|가져왔습니다}}",
-       "logentry-merge-merge": "$1 사용자가 $3 문서를 $4 안에 {{GENDER:$2|병합했습니다}} (판은 $5까지)",
-       "logentry-move-move": "$1 사용자가 $3 문서를 $4 문서로 {{GENDER:$2|이동했습니다}}",
-       "logentry-move-move-noredirect": "$1 사용자가 $3 문서를 넘겨주기를 만들지 않고 $4 문서로 {{GENDER:$2|옮겼습니다}}",
-       "logentry-move-move_redir": "$1 사용자가 $3 문서를 $4 문서로 {{GENDER:$2|이동하면서}} 넘겨주기를 덮어썼습니다",
-       "logentry-move-move_redir-noredirect": "$1 사용자가 $3 문서를 $4 문서로 넘겨주기를 남기지 않고 {{GENDER:$2|이동하면서}} 이동할 대상에 있던 넘겨주기를 덮어썼습니다",
-       "logentry-patrol-patrol": "$1 사용자가 $3 문서의 $4판을 점검한 것으로 {{GENDER:$2|표시했습니다}}",
-       "logentry-patrol-patrol-auto": "$1 사용자가 자동적으로 $3 문서의 $4판을 점검한 것으로 {{GENDER:$2|표시했습니다}}",
+       "logentry-block-block": "$1님이 {{GENDER:$4|$3}}님을 $5 {{GENDER:$2|차단했습니다}} $6",
+       "logentry-block-unblock": "$1님이 {{GENDER:$4|$3}} 사용자의 {{GENDER:$2|차단을 해제했습니다}}",
+       "logentry-block-reblock": "$1님이 {{GENDER:$4|$3}} 사용자의 차단 기간을 $5 설정으로 {{GENDER:$2|바꾸었습니다}} $6",
+       "logentry-suppress-block": "$1님이 {{GENDER:$4|$3}} 사용자를 $5 {{GENDER:$2|차단했습니다}} $6",
+       "logentry-suppress-reblock": "$1님이 {{GENDER:$4|$3}} 사용자의 차단 기간을 $5 설정으로 {{GENDER:$2|바꾸었습니다}} $6",
+       "logentry-import-upload": "$1님이 $3 문서를 파일 올리기로 {{GENDER:$2|가져왔습니다}}",
+       "logentry-import-upload-details": "$1님이 $3 문서 ({{PLURAL:$4|판}} $4개)를 파일 올리기로 {{GENDER:$2|가져왔습니다}}",
+       "logentry-import-interwiki": "$1님이 $3 문서를 다른 위키에서 {{GENDER:$2|가져왔습니다}}",
+       "logentry-import-interwiki-details": "$1님이 $3 문서 ({{PLURAL:$4|판}} $4개)를 다른 위키에서 {{GENDER:$2|가져왔습니다}}",
+       "logentry-merge-merge": "$1님이 $3 문서를 $4 안에 {{GENDER:$2|병합했습니다}} (판은 $5까지)",
+       "logentry-move-move": "$1님이 $3 문서를 $4 문서로 {{GENDER:$2|이동했습니다}}",
+       "logentry-move-move-noredirect": "$1님이 $3 문서를 넘겨주기를 만들지 않고 $4 문서로 {{GENDER:$2|이동했습니다}}",
+       "logentry-move-move_redir": "$1님이 $3 문서를 $4 문서로 {{GENDER:$2|이동하면서}} 넘겨주기를 덮어썼습니다",
+       "logentry-move-move_redir-noredirect": "$1님이 $3 문서를 $4 문서로 넘겨주기를 남기지 않고 {{GENDER:$2|이동하면서}} 이동할 대상에 있던 넘겨주기를 덮어썼습니다",
+       "logentry-patrol-patrol": "$1님이 $3 문서의 $4판을 점검한 것으로 {{GENDER:$2|표시했습니다}}",
+       "logentry-patrol-patrol-auto": "$1님이 자동적으로 $3 문서의 $4판을 점검한 것으로 {{GENDER:$2|표시했습니다}}",
        "logentry-newusers-newusers": "$1 사용자 계정을 {{GENDER:$2|만들었습니다}}",
        "logentry-newusers-create": "$1 사용자 계정을 {{GENDER:$2|만들었습니다}}",
-       "logentry-newusers-create2": "$1 사용자가 $3 사용자 계정을 {{GENDER:$2|만들었습니다}}",
+       "logentry-newusers-create2": "$3 사용자 계정을 $1님이 {{GENDER:$2|만들었습니다}}",
        "logentry-newusers-byemail": "$3 사용자 계정을 $1님이 {{GENDER:$2|만들었고}} 비밀번호는 이메일로 보냈습니다",
        "logentry-newusers-autocreate": "$1 사용자 계정을 자동으로 {{GENDER:$2|만들었습니다}}",
-       "logentry-protect-move_prot": "$1 사용자가 보호 설정을 $4에서 $3으로 {{GENDER:$2|이동했습니다}}",
-       "logentry-protect-unprotect": "$1 사용자가 $3 문서의 보호를 {{GENDER:$2|해제했습니다}}",
-       "logentry-protect-protect": "$1 사용자가 $3 문서를 {{GENDER:$2|보호했습니다}} $4",
-       "logentry-protect-protect-cascade": "$1 사용자가 $3 문서를 {{GENDER:$2|보호했습니다}} $4 [연쇄적]",
-       "logentry-protect-modify": "$1 사용자가 $3 문서의 보호 수준을 {{GENDER:$2|바꾸었습니다}} $4",
-       "logentry-protect-modify-cascade": "$1 사용자가 $3 문서의 보호 수준을 {{GENDER:$2|바꾸었습니다}} $4 [연쇄적]",
-       "logentry-rights-rights": "$1 사용자가 $3 사용자의 권한을 $4에서 $5(으)로 {{GENDER:$2|바꾸었습니다}}",
-       "logentry-rights-rights-legacy": "$1 사용자가 $3 사용자의 권한을 {{GENDER:$2|바꾸었습니다}}",
-       "logentry-rights-autopromote": "$1 사용자의 권한을 자동적으로 $4에서 $5으로 {{GENDER:$2|바꾸었습니다}}",
-       "logentry-upload-upload": "$1 사용자가 $3 파일을 {{GENDER:$2|올렸습니다}}",
-       "logentry-upload-overwrite": "$1 사용자가 $3의 새 판을 {{GENDER:$2|올렸습니다}}",
-       "logentry-upload-revert": "$1 사용자가 $3 파일을 {{GENDER:$2|올렸습니다}}",
+       "logentry-protect-move_prot": "$1님이 보호 설정을 $4에서 $3으로 {{GENDER:$2|이동했습니다}}",
+       "logentry-protect-unprotect": "$1님이 $3 문서의 보호를 {{GENDER:$2|해제했습니다}}",
+       "logentry-protect-protect": "$1님이 $3 문서를 {{GENDER:$2|보호했습니다}} $4",
+       "logentry-protect-protect-cascade": "$1님이 $3 문서를 {{GENDER:$2|보호했습니다}} $4 [연쇄적]",
+       "logentry-protect-modify": "$1님이 $3 문서의 보호 수준을 {{GENDER:$2|바꾸었습니다}} $4",
+       "logentry-protect-modify-cascade": "$1님이 $3 문서의 보호 수준을 {{GENDER:$2|바꾸었습니다}} $4 [연쇄적]",
+       "logentry-rights-rights": "$1님이 $3 사용자의 권한을 $4에서 $5(으)로 {{GENDER:$2|바꾸었습니다}}",
+       "logentry-rights-rights-legacy": "$1님이 $3 사용자의 권한을 {{GENDER:$2|바꾸었습니다}}",
+       "logentry-rights-autopromote": "$1님이 권한을 자동적으로 $4에서 $5으로 {{GENDER:$2|바꾸었습니다}}",
+       "logentry-upload-upload": "$1님이 $3 파일을 {{GENDER:$2|올렸습니다}}",
+       "logentry-upload-overwrite": "$1님이 $3의 새 판을 {{GENDER:$2|올렸습니다}}",
+       "logentry-upload-revert": "$1님이 $3 파일을 {{GENDER:$2|올렸습니다}}",
        "log-name-managetags": "태그 관리 기록",
        "log-description-managetags": "이 문서는 [[Special:Tags|태그]]에 관한 관리 작업의 목록입니다. 이 기록에는 관리자가 직접 실행한 동작만이 기록되며, 위키 소프트웨어에 의해 태그가 생성 및 삭제되는 경우는 기록되지 않습니다.",
-       "logentry-managetags-create": "$1 {{GENDER:$2|사용자가}} \"$4\" 태그를 만들었습니다",
-       "logentry-managetags-delete": "$1 {{GENDER:$2|사용자가}} \"$4\" 태그를 삭제하였습니다 ($5개 {{PLURAL:$5|판 및 기록}}에서 제거되었습니다)",
-       "logentry-managetags-activate": "$1 {{GENDER:$2|사용자가}} \"$4\" 태그를 사용자나 봇이 사용하도록 활성화시켰습니다",
-       "logentry-managetags-deactivate": "$1 {{GENDER:$2|사용자가}} \"$4\" 태그를 사용자나 봇이 사용하지 못하도록 비활성화시켰습니다",
+       "logentry-managetags-create": "$1님이 \"$4\" 태그를 {{GENDER:$2|만들었습니다}}",
+       "logentry-managetags-delete": "$1님이 \"$4\" 태그를 삭제하였습니다 ($5개 {{PLURAL:$5|판 및 기록}}에서 {{GENDER:$2|제거되었습니다}})",
+       "logentry-managetags-activate": "$1님이 \"$4\" 태그를 사용자나 봇이 사용하도록 {{GENDER:$2|활성화시켰습니다}}",
+       "logentry-managetags-deactivate": "$1님이 \"$4\" 태그를 사용자나 봇이 사용하지 못하도록 {{GENDER:$2|비활성화시켰습니다}}",
        "log-name-tag": "태그 기록",
        "log-description-tag": "이 문서는 사용자들이 특정 판이나 기록 항목에서 [[Special:Tags|태그]]를 추가하고 제거한 경우를 보여줍니다. 이 기록에는 편집이나 삭제, 이와 유사한 행위를 통해 태그가 붙는 경우는 기록되지 않습니다.",
-       "logentry-tag-update-add-revision": "$1 사용자가 $3 문서의 $4판에 $6 {{PLURAL:$7|태그}}를 {{GENDER:$2|추가했습니다}}",
-       "logentry-tag-update-add-logentry": "$1 사용자가 $3 문서의 기록 항목 $5에 $6 {{PLURAL:$7|태그}}를 {{GENDER:$2|추가했습니다}}",
-       "logentry-tag-update-remove-revision": "$1 사용자가 $3 문서의 $4판에서 $8 {{PLURAL:$9|태그}}를 {{GENDER:$2|제거했습니다}}",
-       "logentry-tag-update-remove-logentry": "$1 사용자가 $3 문서의 기록 항목 $5에서 $8 {{PLURAL:$9|태그}}를 {{GENDER:$2|제거했습니다}}",
-       "logentry-tag-update-revision": "$1 사용자가 $3 문서의 $4 판에서 태그를 {{GENDER:$2|수정했습니다}} ($6을(를) {{PLURAL:$7|추가함}}; $8을(를) {{PLURAL:$9|제거함}})",
+       "logentry-tag-update-add-revision": "$1님이 $3 문서의 $4판에 $6 {{PLURAL:$7|태그}}를 {{GENDER:$2|추가했습니다}}",
+       "logentry-tag-update-add-logentry": "$1님이 $3 문서의 기록 항목 $5에 $6 {{PLURAL:$7|태그}}를 {{GENDER:$2|추가했습니다}}",
+       "logentry-tag-update-remove-revision": "$1님이 $3 문서의 $4판에서 $8 {{PLURAL:$9|태그}}를 {{GENDER:$2|제거했습니다}}",
+       "logentry-tag-update-remove-logentry": "$1님이 $3 문서의 기록 항목 $5에서 $8 {{PLURAL:$9|태그}}를 {{GENDER:$2|제거했습니다}}",
+       "logentry-tag-update-revision": "$1님이 $3 문서의 $4 판에서 태그를 {{GENDER:$2|업데이트했습니다}} ($6 {{PLURAL:$7|추가함}}; $8 {{PLURAL:$9|제거함}})",
+       "logentry-tag-update-logentry": "$1님이 $3 문서의 기록 항목 $5에 있는 태그를 {{GENDER:$2|업데이트했습니다}} ($6 {{PLURAL:$7|추가함}}; $8 {{PLURAL:$9|제거함}})",
        "rightsnone": "(없음)",
        "revdelete-summary": "편집 요약",
        "feedback-adding": "문서에 피드백을 올리는 중...",
        "action-pagelang": "문서 언어 바꾸기",
        "log-name-pagelang": "언어 바꾸기 기록",
        "log-description-pagelang": "문서 언어를 바꾼 기록입니다.",
-       "logentry-pagelang-pagelang": "$1 사용자가 $3의 언어를 $4에서 $5로 {{GENDER:$2|바꾸었습니다}}.",
+       "logentry-pagelang-pagelang": "$1님이 $3의 언어를 $4에서 $5로 {{GENDER:$2|바꾸었습니다}}",
        "default-skin-not-found": "이런! 당신의 위키에 <code dir=\"ltr\">$wgDefaultSkin</code>에 <code>$1</code>(으)로 지정한 기본 스킨은 사용할 수 없습니다.\n\n설치에는 다음 {{PLURAL:$4|스킨}}이 포함된 것으로 보입니다. 스킨을 활성화{{PLURAL:$4||하고 기본값으로 선택}}하는 방법에 대한 정보에 대해서는 [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: 스킨 설정]을 보세요.\n\n$2\n\n; 미디어위키를 설치했다면:\n: 아마 git에서 설치했거나, 어떤 다른 방법을 사용하여 직접 설치했을 수 있을 것으로 봅니다. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org의 스킨 디렉터리]에서 어떤 스킨을 설치해보세요:\n:* 여러 스킨과 확장 기능이 들어 있는 [https://www.mediawiki.org/wiki/Download tarball 설치 관리자]를 다운로드하세요. 거기서 <code>skins/</code> 디렉터리를 복사하여 붙여 넣을 수 있습니다.\n:* [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org]에서 개별 스킨 tarball을 다운로드하세요.\n:* 미디어위키 설치의 <code dir=\"ltr\">skins/</code> 디렉터리 안에 git를 통해 <code>mediawiki/skins/*</code> 저장소 중 하나를 복제하세요.\n: 당신이 미디어위키 개발자이면 당신의 git 저장소를 방해하면 안됩니다.\n\n; 미디어위키를 업그레이드했다면:\n: 미디어위키 1.24와 새 버전은 더 이상 설치된 스킨을 자동으로 활성화하지 않습니다 ([https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual: 스킨 자동발견]을 보세요). 현재 설치된 {{PLURAL:$5|스킨|모든 스킨}}을 활성화하려면 <code>LocalSettings.php</code> 안에 다음 {{PLURAL:$5|줄}}을 붙여 넣을 수 있습니다:\n\n<pre dir=\"ltr\">$3</pre>\n\n; <code>LocalSettings.php</code>를 수정했다면:\n: 스킨 이름에 오타가 났는지 다시 확인하세요.",
        "default-skin-not-found-no-skins": "이런! 당신의 위키에 <code dir=\"ltr\">$wgDefaultSkin</code>에 <code>$1</code>(으)로 지정한 기본 스킨은 사용할 수 없습니다.\n\n설치된 스킨은 없습니다.\n\n; 미디어위키를 설치했거나 업그레이드했다면:\n: 아마 git에서 설치했거나, 어떤 다른 방법을 사용하여 직접 설치했을 수 있을 것으로 봅니다. 미디어위키 1.24와 새 버전은 주 저장소에 어떠한 스킨도 포함되어 있지 않습니다. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org의 스킨 디렉터리]에서 어떤 스킨을 설치해보세요:\n:* 여러 스킨과 확장 기능이 들어 있는 [https://www.mediawiki.org/wiki/Download tarball 설치 관리자]를 다운로드하세요. 거기서 <code>skins/</code> 디렉터리를 복사하여 붙여 넣을 수 있습니다.\n:* [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org]에서 개별 스킨 tarball을 다운로드하세요.\n:* 미디어위키 설치의 <code dir=\"ltr\">skins/</code> 디렉터리 안에 git를 통해 <code>mediawiki/skins/*</code> 저장소 중 하나를 복제하세요.\n: 당신이 미디어위키 개발자이면 당신의 git 저장소를 방해하면 안됩니다. 스킨을 활성화하고 기본값으로 선택하는 방법에 대한 정보에 대해서는 [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: 스킨 설정]을 보세요.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (활성화)",
        "mw-widgets-titleinput-description-new-page": "문서가 존재하지 않습니다",
        "mw-widgets-titleinput-description-redirect": "$1 문서로 넘겨주기",
        "api-error-blacklisted": "이 파일을 설명할 수 있는 다른 제목을 선택하세요.",
+       "sessionmanager-tie": "여러 요청 인증 유형 결합할 수 없습니다: $1.",
        "sessionprovider-generic": "$1 세션",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "쿠키 기반 세션",
        "sessionprovider-nocookies": "브라우저의 쿠키 기능이 꺼져 있는지 확인하십시오. 쿠키 기능을 켠 다음 다시 시작해야 합니다.",
index a78dfa2..61c64b7 100644 (file)
@@ -9,7 +9,8 @@
                        "לערי ריינהארט",
                        "아라",
                        "TTO",
-                       "Macofe"
+                       "Macofe",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Dun de Lengks ongerschtriische:",
        "june": "Juni",
        "july": "Juli",
        "august": "Aujuss",
-       "september": "September",
+       "september": "Septämber",
        "october": "Oktober",
-       "november": "November",
-       "december": "Dezember",
+       "november": "Novämber",
+       "december": "Dezämber",
        "january-gen": "Janewar",
        "february-gen": "Febrewar",
        "march-gen": "Määz",
        "june-gen": "Juni",
        "july-gen": "Juli",
        "august-gen": "Aujuss",
-       "september-gen": "September",
+       "september-gen": "Septämber",
        "october-gen": "Oktober",
-       "november-gen": "November",
-       "december-gen": "Dezember",
+       "november-gen": "Novämber",
+       "december-gen": "Dezämber",
        "jan": "Jan",
        "feb": "Feb",
        "mar": "Mäz",
        "virus-scanfailed": "Dat Söhke eß donevve jejange, dä Kood för dä Fähler es „$1“.",
        "virus-unknownscanner": "Dat Projamm fö noh Komjuterviere ze sööke kenne mer nit:",
        "logouttext": "'''Jäz bes de usjelogg'''\n\nKünnt sin, dat De de ein udder andere Sigg noch wigger aanjezeich kriß, wie wann de noch enjelogg wörs. Dun Dingem Brauser singe <i lang=\"en\">Cache</i> fottschmieße udder läddesch maache, öm uß dä Nommer erus ze kumme!",
+       "cannotlogoutnow-title": "Ußlogge jeiht jrahd nit",
+       "cannotlogoutnow-text": "Ußlogge jeiht jrahd nit wam_mer $1 bruch.",
        "welcomeuser": "Wellkumme $1!",
        "welcomecreation-msg": "Dinge Zohjang es enjerescht.\nWann De wells, künnts De Ding [[Special:Preferences|Enschtällonge aanpaße]].",
        "yourname": "Metmaacher_Naame:",
        "remembermypassword": "Op Duur aanmelde (hält {{PLURAL:$1|för eine Daach|bes op $1 Dääsch|bloß för hück}})",
        "userlogin-remembermypassword": "Op Duur enlogge",
        "userlogin-signwithsecure": "Verschlößeld enlogge",
+       "cannotloginnow-title": "Ennlogge jeiht jrahd nit",
+       "cannotloginnow-text": "Ennlogge jeiht jrahd nit wam_mer $1 bruche well.",
        "yourdomainname": "Ding Domain",
        "password-change-forbidden": "Do kanns en heh däm Wiki kein Paßwööter ändere.",
        "externaldberror": "Do wor ene Fähler en de externe Daatebank, oder Do darfs Ding extern Daate nit ändere. Dat Aanmelde jingk jedenfalls donevve.",
        "resetpass_submit": "E neu Zweschepasswood övvermeddele un aanmellde",
        "changepassword-success": "Et Paßwood es jeändert.",
        "changepassword-throttled": "Do häs zoh öff versöhk, enzelogge. Waat $1 Ih dat De es widder probeers.",
+       "botpasswords": "Bot-Paßwööter",
+       "botpasswords-disabled": "Bot-Paßwööter sin ußjeschallt",
+       "botpasswords-no-central-id": "Öm Bot-Paßwööter bruche ze künne, moß De övve en jemeinsamme Aanmälldong ennjelogg sin.",
+       "botpasswords-existing": "Vörhande Bot-Paßwööter",
+       "botpasswords-createnew": "Lääsch e neu Bot-Paßwööter aan",
+       "botpasswords-editexisting": "Verännder a Bot-Paßwööter",
+       "botpasswords-label-appid": "Däm Bot singe Nahme",
        "botpasswords-label-create": "Neu maache",
        "botpasswords-label-update": "Änndere",
        "botpasswords-label-cancel": "Ophüre",
        "botpasswords-label-delete": "Fottschmiiße",
        "botpasswords-label-resetpassword": "Paßwoot neu säze",
+       "botpasswords-label-restrictions": "Beschränkonge:",
+       "botpasswords-bad-appid": "„$1“ es keine jölltejje Nahme för ene Bot.",
+       "botpasswords-insert-failed": "Kunnt keine Bot mem Nahme „$1“ derbei donn. Wohr velleijsch ald doh.",
+       "botpasswords-update-failed": "Kunnt keine Bot mem Nahme „$1“ veränndere. Es velleijsch fottjeschmeße?",
+       "botpasswords-created-title": "Dat Bot-Paßwood es aanjelaat",
        "botpasswords-created-body": "Dat Bot-Paßwoot för dä Bot „$1“ {{GENDER:$2|vum|vum|vumm Metmaacher|vun dä|vum}} „$2“ wood ennjerescht.",
+       "botpasswords-updated-title": "Dat Bot-Paßwood es veränndert",
        "botpasswords-updated-body": "Dat Bot-Paßwoot för dä Bot „$1“ {{GENDER:$2|vum|vum|vumm Metmaacher|vun dä|vum}} „$2“ wood veränndert.",
+       "botpasswords-deleted-title": "Dat Bot-Paßwood es fott",
        "botpasswords-deleted-body": "Dat Bot-Paßwoot för dä Bot „$1“ {{GENDER:$2|vum|vum|vumm Metmaacher|vun dä|vum}} „$2“ wood fott jeschmeße.",
        "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",
        "mergehistory-empty": "Mer han kei Versione för zesammezeläje",
        "mergehistory-done": "{{PLURAL:$3|Ein Väsjohn es|$3 Väsjohn sen|Kei Väsjohn wood}} fun „$1“ noh „[[:$2]]“ övverdraare un domet zosamme jelaat.",
        "mergehistory-fail": "Dat Versione zesamme läje is nit müjjelisch. Don ens di Sigge un de Zigge pröfe!",
+       "mergehistory-fail-self-merge": "De Quell-Sigg un de Ziel-Sigg sin deselve Sigg.",
        "mergehistory-fail-toobig": "Mih wi {{PLURAL:$1|ein Väsjohn|$1 Väsjohne|kein Väsjohne}} wöödte zesamme jelaat. Esu vill künne mer nit, un maache mer nit.",
        "mergehistory-no-source": "En Ursprungssigg „$1“ jidd_et nit.",
        "mergehistory-no-destination": "En Zielsigg „$1“ jidd_et nit.",
        "userrights": "De Metmaacher ehr Rääschde verwallde",
        "userrights-lookup-user": "Metmaacherjruppe verwalde",
        "userrights-user-editname": "Däm Metmaacher singe Nahme:",
-       "editusergroup": "Metmaacher ier Jroppe un Räächde änndere",
+       "editusergroup": "{{GENDER:$1|Däm|Däm|Däm Metmaacher|Dä|Däm}} [[User:$1|$1]] {{GENDER:$1|sing|singe|sing|ier|sing}} Jroppe un Räächde änndere",
        "editinguser": "Heh deihs De däm {{GENDER:$1|däm|däm|däm Metmaacher|dä|däm}} '''[[User:$1|$1]]''' {{GENDER:$1|singe|singe|singe|iere|singe}} Rääschde änndere. $2",
        "userrights-editusergroup": "Metmaacher en Jroppe donn un uß Jroppe nämme",
-       "saveusergroups": "Metmaacherjruppe avspeichere",
+       "saveusergroups": "Donn {{GENDER:$1|däm|dem|däm Metmaacher|dä|däm}} [[User:$1|$1]] {{GENDER:$1|sing|singe|sing|ier|sing}} Jroppe faßhalle",
        "userrights-groupsmember": "Dä Metmaacher es en {{PLURAL:$1|dä Jropp:|dä Jroppe:|keine Jropp.}}",
        "userrights-groupsmember-auto": "Dä Metmaacher es automattesch en {{PLURAL:$1|dä Jropp:|dä Jroppe:|keine Jropp.}}",
        "userrights-groups-help": "Do kanns de Jroppe för dä Metmaacher heh änndere, ävver opjepaß:\n* E Käßje met Höksche bedüg, dat dä Metmaacher en dä Jropp es.\n* E Käßje ohne Höksche bedüg, dat dä Metmaacher nit en dä Jropp es.\n* E Käßje met Stähnsche donävve bedüg, dat De dat Rääsch zwa ändere, ävver de Änderong nit mih zeröck nämme kanns.",
        "recentchangeslinked-page": "Dä Sigg ier Övverschreff:",
        "recentchangeslinked-to": "Zeisch de Änderonge aan dä Sigge, woh Lengks op di aanjejovve Sigg drop sin",
        "recentchanges-page-added-to-category": "Di Sigg [[:$1]] wood en di Saachjrop jedonn",
-       "recentchanges-page-added-to-category-bundled": "Di Sigg [[:$1]] un {{PLURAL:$2|noch ein Sigg wood|$2 Sigge woodte|kein Sigg wood}} en di Saachjrop jedonn",
+       "recentchanges-page-added-to-category-bundled": "Di Sigg [[:$1]] un [[Special:WhatLinksHere/$1|{{PLURAL:$2|noch ein Sigg wood|$2 Sigge woodte|kein Sigg wood}}]] en di Saachjrop jedonn",
        "recentchanges-page-removed-from-category": "Di Sigg [[:$1]] wood uß dä Saachjrop jenumme",
        "recentchanges-page-removed-from-category-bundled": "Di Sigg [[:$1]] un {{PLURAL:$2|noch ein Sigg woodte|$2 Sigge woodte|kein Sigg wood}} uß dä Saachjrop jenumme",
        "autochange-username": "Automattesche Ännderong aam MediaWiki",
        "mostrevisions": "Atikkele met de mihste Änderonge",
        "prefixindex": "Alle Sigge, dänne ehr Nahme med enem beschtemmpte Wood udder Täx aanfängk",
        "prefixindex-namespace": "Alle Sigge med enem beschtemmpte Aanfang em Appachtemang „$1“",
+       "prefixindex-submit": "Lohß jonn!",
        "prefixindex-strip": "Donn der jemeinsamme Aanfang vun dä Tetelle en dä Leß fottlohße.",
        "shortpages": "Atikele zoteet vun koot noh lang",
        "longpages": "Atikele zoteet vun lang noh koot",
        "protectedpages-performer": "Jeschöz vum Metmaacher",
        "protectedpages-params": "De Zoot Schpär",
        "protectedpages-reason": "Der Jrond",
+       "protectedpages-submit": "Lohß jonn!",
        "protectedpages-unknown-timestamp": "Onbikannt",
        "protectedpages-unknown-performer": "Onbikannte Metmaacher",
        "protectedtitles": "Verbodde Titele för Sigge",
        "protectedtitles-summary": "Hee sin verbodde Sigge-Tittele opjeleß. Onger dä Name ka_mer kein neu Sigge aanläje.\nEn Leß met dä Sigge, di jäje et Verändere udder jäje et Ömnenne jeschötz sin, fengk mer op dä Sigg [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
        "protectedtitlesempty": "Op di Aat sin jrad kein Sigge jäje et neu Aanlääje jeschötz.",
+       "protectedtitles-submit": "Lohß jonn!",
        "listusers": "De Metmaacherleß",
        "listusers-editsonly": "Donn nor Metmaacher zeije, di och ens jät jeschrevve han.",
        "listusers-creationsort": "Noh em Dattum vum Aanmellde zoteere",
        "usereditcount": "{{PLURAL:$1|Ein Änderong|$1 Änderonge|Nix jedonn}}",
        "usercreated": "{{GENDER:$3|}}Aanjemelldt aam $1 öm $2 Uhr",
        "newpages": "Neu Sigge",
+       "newpages-submit": "Lohß jonn!",
        "newpages-username": "Metmaacher_Naame:",
        "ancientpages": "Atikele zoteet vun Ahl noh Neu",
        "move": "Ömnenne",
        "apihelp": "Hölp för de <i lang=\"en\" xml:lang=\"en\" title=\"Application Programmers Interface\">API</i>",
        "apihelp-no-such-module": "Et Moduhl „$1“ wood nit jefonge.",
        "apisandbox": "De <i lang=\"en\">API</i> ußprobeere",
+       "apisandbox-jsonly": "Der ohne JavaSkrepp kam_mer de <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Application Programming Interface\">API</i> för zom erömprobehre nit bruche.",
        "apisandbox-api-disabled": "Dat <i lang=\"en\">API</i> es en heh dämm Wiki afjeschalldt.",
-       "apisandbox-intro": "Op heh dä Sigg kanns De met dä '''MediaWiki web service <i lang=\"en\">API</i>''' eröm schpelle.\nBeloor Der de Einzelheite, wi di jebruch weed, op dä iere [//www.mediawiki.org/wiki/API:Main_page Sigg met de Verklieronge].\nE Beiscpell: [//www.mediawiki.org/wiki/API#A_simple_example De Houpsigg holle].\nSöhk ene {{int:Apisb-label-action}} uß, öm mieh Beishpell aanjezeisch ze krijje.\nOch wann dat heh nor zom Ußprobeere es, kann dat, wat De heh mähß, et Wiki verändere.",
+       "apisandbox-intro": "Op heh dä Sigg kanns De met dä <strong>MediaWiki web service <i lang=\"en\">API</i></strong> eröm schpelle.\nBeloor Der de Einzelheite, wi di jebruch weed, op dä iere [[mw:API:Main_page Sigg met de Verklieronge]].\nE Beiscpell: [//www.mediawiki.org/wiki/API#A_simple_example De Houpsigg holle].\nSöhk ene {{int:Apisb-label-action}} uß, öm mieh Beishpell aanjezeisch ze krijje.\nOch wann dat heh nor zom Ußprobeere es, kann dat, wat De heh mähß, et Wiki verändere.",
        "apisandbox-submit": "Lohß jonn!",
        "apisandbox-reset": "Läddesch maache",
-       "apisandbox-examples": "Bäijshpell",
+       "apisandbox-retry": "Norr_ens versöhke",
+       "apisandbox-examples": "Bäijshpelle",
        "apisandbox-dynamic-parameters": "Zohsäzlejje Parrameetere",
        "apisandbox-results": "Erus jekumme es",
        "apisandbox-request-url-label": "Dä <i lang=\"en\">URL</i> vun dä Aanfrooch:",
        "log-title-wildcard": "Sök noh Titelle, di aanfange met …",
        "showhideselectedlogentries": "Ußjesöhk Endrääsch verschteische udder zeije",
        "log-edit-tags": "Donn de Makehronge vun de ußjesöhk Enndrähsch em Logbohch beärbeide",
+       "checkbox-all": "Alle",
+       "checkbox-none": "Keine",
+       "checkbox-invert": "Ußwahl ömdrihje",
        "allpages": "Alle Sigge",
        "nextpage": "De nächste Sigg: „$1“",
        "prevpage": "Vörijje Sigg ($1)",
        "changecontentmodel-title-label": "Dä Sigg ier Övverschreff",
        "changecontentmodel-model-label": "Et neuje Modäll för der Enhalld",
        "changecontentmodel-reason-label": "Der Jrond:",
+       "changecontentmodel-submit": "Lohß jonn!",
        "changecontentmodel-success-title": "Et Modäll för der Enhalld wohd veränndert",
        "changecontentmodel-success-text": "Et Modäll för der Enhalld vun dä Sigg „[[:$1]]“ wohd veränndert",
        "logentry-contentmodel-change-revertlink": "retuhr_nämme",
        "whatlinkshere-hidelinks": "de nommahle Lengks $1",
        "whatlinkshere-hideimages": "$1 de Lengks op Datteihje",
        "whatlinkshere-filters": "Ußsööke",
+       "whatlinkshere-submit": "Lohß jonn!",
        "autoblockid": "Automattesche Sperr Nommer $1",
        "block": "Metmaacher udder en <i lang=\"en\">IP</i>-Addräß sperre",
        "unblock": "Don en Sperr för ene Metmaacher udder en <i lang=\"en\">IP</i>-Addräß ophävve",
        "ipb-unblock": "En IP-Addräß ov ene Metmaacher widder zohlohße",
        "ipb-blocklist": "All de Sperre för Metmaacher un <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„de eläktrohnesche Poß“\">e-mail</i>-Adräße aanzeije, di jrad beschtonn",
        "ipb-blocklist-contribs": "{{GENDER:$1|Däm|Däm|Däm Metmaacher|Dä|Däm}} $1 {{GENDER:$1|sing|singe|sing|iere|sing}} Bäjdrähsch",
+       "ipb-blocklist-duration-left": "noch $1",
        "unblockip": "Dä Medmacher widder maache looße",
        "unblockiptext": "Heh kanns De vörher jesperrte IP_Adresse oder Metmaacher widder freijevve, un dänne esu dat Rääch för ze Schrieve heh em Wiki widder jevve.",
        "ipusubmit": "Sperr ophevve!",
        "import-logentry-upload-detail": "{{PLURAL:$1|ein Väsjohn|$1 Väsjohne|kein Väsjohn}} woodt emportehrt.",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|ein Väsjohn|$1 Väsjohne|kein VVäsjohnersion}} woodt empottehrt vun „$2“",
        "javascripttest": " JavaSkrepte ußprobeere.",
-       "javascripttest-pagetext-noframework": "Heh di Sigg es för JavaSkrepte ußzeprobeere.",
-       "javascripttest-pagetext-unknownframework": "Dä Prööfrahme „$1“ es onbikannt.",
        "javascripttest-pagetext-unknownaction": "„$1“ es ene onbikannte Opdracht.",
-       "javascripttest-pagetext-frameworks": "Bes esu jood un söök eine vun dä Prööfömjävvonge us: $1",
-       "javascripttest-pagetext-skins": "Sööke en Bovverfläsch udder et Ußsinn uß, öm di Prööfonge domet ze maache:",
        "javascripttest-qunit-intro": "Loor noh dä [$1 Dokemäntation övver et Prööfe] op mediawiki.org.",
        "tooltip-pt-userpage": "Don Ding eije Metmaachersigg aanzeije{{GENDER:|}}",
        "tooltip-pt-anonuserpage": "Metmaachersigg för di <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Internet Protocol\">IP</i>-Adräß, vun wo uß De jraad Ding Ännderonge un Äjännzonge aam Wiki am maache bes",
        "scarytranscludefailed-httpstatus": "[De Schablohn „$1“ enzebenge hät nit jeflupp. Dä HTTP-Fähler es: $2]",
        "scarytranscludetoolong": "[Schad, de URL es ze lang]",
        "deletedwhileediting": "<strong>Opjepaß:</strong> De Sigg wood fottjeschmeße, nohdäm Do ald aanjefange häs, draan ze Ändere.\nEm <span class=\"plainlinks\">[{{fullurl:Special:Log|type=delete&page=}}{{FULLPAGENAMEE}} Logbohch vum Sigge-Fottschmiiße]</span> künnt der Jrond schtonn.\nWann De de Sigg avschpeischere deis, weed se widder aanjelaat.",
-       "confirmrecreate": "Dä Metmaacher [[User:$1|$1]] ([[User talk:$1|Klaaf]]) hät di Sigg fottjeschmeße, nohdäm Do do dran et Ändere aanjefange häs. Dä Jrond:\n: „<i>$2</i>“\nWells Do jetz met en neu Väsjohn di Sigg widder neu aanläje?",
-       "confirmrecreate-noreason": "Dä [[User:$1|$1]] ([[User talk:$1|Klaaf]]) hät heh di Sigg fottjeschmeße, nohdämm Do aanjefange häs, draan ze ändere. Bes esu jood un donn beshtääteje, dat De di Sigg widder neu aanjelaat han wells.",
+       "confirmrecreate": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} [[User:$1|$1]] ([[User talk:$1|Klaaf]]) hät di Sigg fottjeschmeße, nohdäm Do do dran et Ändere aanjefange häs. Dä Jrond:\n: „<i>$2</i>“\nWells Do jäz medd en neuje Väsjohn di Sigg widder neu aanläje?",
+       "confirmrecreate-noreason": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} [[User:$1|$1]] ([[User talk:$1|Klaaf]]) hät heh di Sigg fottjeschmeße, nohdämm Do aanjefange häs, draan ze ändere. Bes esu jood un donn beschtähteje, dat De di Sigg widder neu aanjelaat han wells.",
        "recreate": "Widder neu aanlääje",
        "unit-pixel": "px",
        "confirm_purge_button": "Jo — loss jonn!",
        "version-libraries-description": "Wat se deiht",
        "version-libraries-authors": "Schrihver",
        "redirect": "Ömleide op en Dattei, ene Metmaacher udder de Väsjohn vun ener Sigg",
-       "redirect-legend": "Ömleide ob_en Dattei udder Sigg",
        "redirect-summary": "Heh di {{int:specialpage}} leidt öm ob_en Dattei — doh mößd_Er ene Nahme aanjävve, för e Beischpell:[[{{#Special:Redirect}}/file/Example.jpg]] — udder en Sigg — doh mößd_Er en Kännong för, udder en Väsjuhn aanjävve, för e Beischpell esu: [[{{#Special:Redirect}}/page/64308]] udder [[{{#Special:Redirect}}/revision/328429]] — udder en Metmaachersigg — doh mößd_Er enem Metmaacher sing Kännong aanjävve, för e Beischpell: [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Lohß Jonn!",
        "redirect-lookup": "Söhk noh:",
        "mw-widgets-titleinput-description-new-page": "di Sigg jidd_et noch nit",
        "mw-widgets-titleinput-description-redirect": "ömleijde op „$1“",
        "api-error-blacklisted": "Söhk Der ene anndere Nahme uß, dä mih drövver säht.",
-       "randomrootpage": "Zofällige Aanfangs-Sigg"
+       "randomrootpage": "Zofällige Aanfangs-Sigg",
+       "log-action-filter-delete-delete": "En Sigg wohd fott jeschmeße"
 }
index 848de91..8be49c9 100644 (file)
        "tog-extendwatchlist": "In indice paginarum observandarum non solum recentissimas, verum omnes mutationes ostendere",
        "tog-usenewrc": "Indices per paginas redigere",
        "tog-numberheadings": "Subtituli numeris adornandi",
-       "tog-showtoolbar": "Affigere trabem redigentem",
+       "tog-showtoolbar": "Trabem editoriam affigere",
        "tog-editondblclick": "Duplici ictu liceat paginam recensere",
        "tog-editsectiononrightclick": "Titulis a dextra tactis liceat paginarum partes recensere",
        "tog-watchcreations": "Paginas, quas creavero, et fasciculos, quos imposuero, observare",
        "tog-watchdefault": "Paginas et fasciculos, quos recensuero, observare",
        "tog-watchmoves": "Paginas et fasciculos, quos movero, observare",
        "tog-watchdeletion": "Paginas et fasciculos, quos delevero, paginarum observandarum indici addere",
-       "tog-minordefault": "Notare omnes recensiones quasi minores",
+       "tog-minordefault": "Omnes recensiones per se ut minores notare",
        "tog-previewontop": "Prospectum supra capsam recensoriam ostendere",
        "tog-previewonfirst": "Prospectum novae paginae perhibere",
        "tog-enotifwatchlistpages": "Mutata vel pagina vel fasciculo observando certior fiam",
        "tog-enotifminoredits": "Etiam de minoribus recensionibus certior fiam",
        "tog-enotifrevealaddr": "Ostendatur inscriptio mea electronica in nuntiis notificantibus",
        "tog-shownumberswatching": "Numerum usorum observantium monstrare",
-       "tog-oldsig": "Subscriptio, qua nunc uteris:",
+       "tog-oldsig": "Subscriptio, qua adhuc uteris:",
        "tog-fancysig": "Subscriptio vicitext (sine nexu automatico)",
        "tog-uselivepreview": "Prospectum viventem perhibere",
-       "tog-forceeditsummary": "Si recensionem non summatim descripsero, me roga si continuare velim",
+       "tog-forceeditsummary": "Cavere, ut recensionem summatim describam",
        "tog-watchlisthideown": "Recensiones meas in paginarum observandarum indice supprimere",
        "tog-watchlisthidebots": "Recensiones per automaton factas in paginarum observandarum indice supprimere",
        "tog-watchlisthideminor": "Minores recensiones in paginarum observandarum indice supprimere",
        "tog-diffonly": "Nihil nisi differentia in pagina facta ostendatur",
        "tog-showhiddencats": "Categorias celatas monstrare",
        "tog-norollbackdiff": "Post reversionem paginae differentia neglegatur",
+       "tog-useeditwarning": "Prohibere, ne paginam nondum servatam relinquam",
        "underline-always": "Semper",
        "underline-never": "Numquam",
        "underline-default": "Defalta navigatri interretialis",
+       "editfont-style": "Stilus:",
+       "editfont-default": "iuxta navigatrum",
        "sunday": "dies Solis",
        "monday": "dies Lunae",
        "tuesday": "dies Martis",
        "delete": "Delere",
        "deletethispage": "Delere hanc paginam",
        "undeletethispage": "Hanc paginam restituere",
-       "undelete_short": "Restituere {{PLURAL:$1|unam emendationem|$1 emendationes}}",
-       "viewdeleted_short": "Inspicere {{PLURAL:$1|unam emendationem deletam|$1 emendationes deletas}}",
+       "undelete_short": "{{PLURAL:$1|Unam recensionem|$1 recensiones}} restituere",
+       "viewdeleted_short": "{{PLURAL:$1|unam redactionem deletam|$1 redactiones deletas}} inspicere",
        "protect": "Protegere",
        "protect_change": "mutare",
        "protectthispage": "Protegere hanc paginam",
        "collapsible-expand": "Dilatare",
        "thisisdeleted": "Videre aut restituere $1?",
        "viewdeleted": "Visne conspicere $1?",
-       "restorelink": "{{PLURAL:$1|unam emendationem deletam|$1 emendationes deletas}}",
+       "restorelink": "{{PLURAL:$1|unam redactionem deletam|$1 redactiones deletas}}",
        "feedlinks": "Fluxus:",
        "feed-invalid": "Typus subscriptionis fluxus invalidus.",
        "feed-unavailable": "Fluxus syndicationis non praestiti",
        "error": "Erratum",
        "databaseerror": "Erratum in basi datorum",
        "readonly": "Basis datorum obstructa",
-       "missingarticle-rev": "(numerus emendationis: $1)",
+       "missingarticle-rev": "(ID numerus redactionis: $1)",
        "missingarticle-diff": "(Diss: $1, $2)",
        "internalerror": "Erratum internum",
        "internalerror_info": "Erratum internum: $1",
        "viewsource": "Fontem inspicere",
        "viewsource-title": "Fontem paginae $1 inspicere",
        "actionthrottled": "Actio strangulata",
-       "protectedpagetext": "Haec pagina protecta est, ut emendationes prohibeantur.",
+       "protectedpagetext": "Huic paginae protectio data est, ne redigatur neu aliter tractetur.",
        "viewsourcetext": "Fontem videas et exscribeas:",
        "protectedinterface": "Haec pagina dat textum interfaciei pro logiciali, et est protecta ad vandalismum vetandum.",
        "editinginterface": "'''Caveat censor:''' Emendas iam paginam quae textum interfaciei logicialem dat. Mutationes vultum {{grammar:genitive|{{SITENAME}}}} omnibus usoribus afficient. In nuntia MediaWiki vertendo, quaesumus te uti [//translatewiki.net/wiki/Main_Page?setlang=la translatewiki.net].",
        "gotaccountlink": "Nomen da",
        "userlogin-resetlink": "Num tesserae tuae oblitus es?",
        "userlogin-resetpassword-link": "Num tesserae oblitus es?",
+       "userlogin-helplink2": "auxilium dandi nominis",
        "createacct-emailrequired": "Inscriptio electronica",
        "createacct-emailoptional": "Inscriptio electronica (non necesse)",
        "createacct-email-ph": "Inscriptionem electronicam tuam inscribe",
        "resetpass-submit-loggedin": "Tesseram mutare",
        "resetpass-submit-cancel": "Dimittere",
        "resetpass-temp-password": "Tessera temporaria:",
+       "passwordreset": "Tesseram restituere",
        "passwordreset-username": "Nomen usoris:",
        "passwordreset-email": "Inscriptio electronica:",
        "passwordreset-emailelement": "Nomen usoris: \n$1\n\nMomentarius Tessera: \n$2",
        "newarticle": "(Nova)",
        "newarticletext": "Per nexum progressus es ad paginam quae nondum exsistit.\nNovam paginam si vis creare, in capsam infra praebitam scribe.\n(Vide [$1 paginam auxilii] si plura cognoscere vis.)\nSi hic es propter errorem, solum '''Retrorsum''' in navigatro tuo preme.",
        "anontalkpagetext": "----\n<em>Haec est pagina disputationis usoris anonymi vel potius loci IP cuiusdam.</em>\nMemento locos IP interdum mutari et ab usoribus vel pluribus adhiberi.\nSi ipse sis usor ignotus et ex improviso invenias querulas aliquas, nomen tibi [[Special:UserLogin/signup|impone]] vel [[Special:UserLogin|nomen tuum da]], ut decetero confusionem effugias!",
-       "noarticletext": "Hac in pagina non sunt litterae.\nPotes [[Special:Search/{{PAGENAME}}|hanc rem in aliis paginis quaerere]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} acta huius paginae videre]\naut [{{fullurl:{{FULLPAGENAME}}|action=edit}} hanc paginam creare]</span>.",
+       "noarticletext": "Hac in pagina non sunt litterae.\nLicet [[Special:Search/{{PAGENAME}}|hanc rem in aliis paginis quaerere]] vel\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} acta huius paginae inspicere]\nvel [{{fullurl:{{FULLPAGENAME}}|action=edit}} hanc paginam creare]</span>.",
        "noarticletext-nopermission": "Hac in pagina non sunt litterae.\nPotes [[Special:Search/{{PAGENAME}}|hanc rem in aliis paginis quaerere]] aut <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} acta huius paginae videre], sed tibi non licet hanc paginam creare.",
        "userpage-userdoesnotexist": "Usor \"<nowiki>$1</nowiki>\" non est. Visne re vera hanc paginam creare vel recensere?",
        "updated": "(Novata)",
        "editingcomment": "Recensens $1 (nova pars)",
        "editconflict": "Contentio recensionis: $1",
        "explainconflict": "Alius hanc paginam mutavit postquam eadem recensere incipiebas.\nCapsa superior paginae verba recentissima continet.\nMutationes tuae in capsa inferiore monstrantur.\nMutationes tuae in verba superiora adiungare debes.\n'''Solum''' verba capsae superioris servabuntur quando \"{{int:savearticle}}\" premes.",
-       "yourtext": "Sententia tua",
-       "storedversion": "Versio ante recensionem tuam novissime facta",
+       "yourtext": "Tua redactio",
+       "storedversion": "Redactio modo servata",
        "nonunicodebrowser": "'''CAVETO: Navigatorium retiale tuum systemati UNICODE morem non gerit. Modum habemus quo commentationes sine damno recenseas: litterae non-ASCII in capsa sub veste hexadecimali ostendentur.'''",
-       "editingold": "'''MONITIO: Emendationem obsoletam huius paginae mutas.\nSi eam servaveris, omnes mutationes recentiores obrogatae peribunt!'''",
+       "editingold": "'''CAVE, ne huius paginae redactionem recenses obsoletam!\nQua servata omnes recensiones abhinc factas peribunt.'''",
        "yourdiff": "Differentia",
        "copyrightwarning": "Nota bene omnia contributa divulgari sub ''$2'' (vide singula apud $1).\nNisi vis verba tua crudelissime recenseri, mutari, et ad libidinem redistribui, noli ea submittere.<br />\nNobis etiam spondes te esse ipsum horum verborum scriptorem primum, aut ex opere in \"dominio publico\" exscripsisse.\n'''NOLI OPERIBUS SUB IURE DIVULGANDI UTI SINE POTESTATE!'''",
        "copyrightwarning2": "Nota bene omnia contributa apud {{grammar:accusative|{{SITENAME}}}} ab aliis recenseri, mutari vel removi posse.\nNisi vis verba tua crudelissime recenseri, noli ea submittere.<br />\nNobis etiam spondes te esse ipsum horum verborum scriptorem primum, aut ex opere in \"dominio publico\" vel ex libere fonte simili exscripsisse (vide singula apud $1).\n'''NOLI OPERIBUS SUB IURE DIVULGANDI UTI SINE POTESTATE!'''",
        "cantcreateaccount-text": "Ex hoc loco IP ('''$1''') nomen sibi imponere ab usore [[User:$3|$3]] interdicitur.\nQui hanc causam dedit: ''$2''",
        "viewpagelogs": "Vide acta huius paginae",
        "nohistory": "Huic paginae non est historia.",
-       "currentrev": "Versio novissime facta",
-       "currentrev-asof": "Versio novissime (die $2, hora $3) facta",
-       "revisionasof": "Emendatio ex $1",
-       "revision-info": "Emendatio ex $1 ab $2$7",
-       "previousrevision": "← Emendatio senior",
-       "nextrevision": "Emendatio novior →",
-       "currentrevisionlink": "Emendatio currens",
+       "currentrev": "Redactio novissima",
+       "currentrev-asof": "Redactio novissime (die $2, hora $3) facta",
+       "revisionasof": "Redactio $1 facta",
+       "revision-info": "Redactio $1 a conlatore $2 facta$7",
+       "previousrevision": "← Redactio superior",
+       "nextrevision": "Redactio recentior →",
+       "currentrevisionlink": "Redactio novissima",
        "cur": "nov",
        "next": "seq",
        "last": "prox",
        "historysize": "({{PLURAL:$1|1 octetus|$1 octeti}})",
        "historyempty": "(vacua)",
        "history-feed-title": "Historia",
-       "history-feed-description": "Historia emendationum huius paginae",
+       "history-feed-description": "Historia redactionum huius paginae",
        "history-feed-item-nocomment": "$1 ad $2",
        "rev-deleted-comment": "(summarium celatum)",
        "rev-deleted-user": "(nomen usoris celatum est)",
        "rev-deleted-event": "(perscriptio celata)",
        "rev-delundel": "monstrare/celare",
        "rev-showdeleted": "monstrare",
-       "revisiondelete": "Emendationem delere",
-       "revdelete-nooldid-title": "Emendatio-scopus invalida",
+       "revisiondelete": "Redactiones delere vel restituere",
+       "revdelete-nooldid-title": "Redactio scopo invalida",
        "revdelete-show-file-submit": "Sic",
-       "revdelete-selected-text": "{{PLURAL:$1|Emendatio selecta|Emendationes selectae}} paginae [[:$2]]:",
-       "revdelete-selected-file": "{{PLURAL:$1|Emendatio selecta|Emendationes selectae}} fasciculi [[:$2]]:",
+       "revdelete-selected-text": "{{PLURAL:$1|Redactio selecta|Redactiones selectae}} paginae [[:$2]]:",
+       "revdelete-selected-file": "{{PLURAL:$1|Redactio selecta|Redactiones selectae}} fasciculi [[:$2]]:",
        "revdelete-legend": "Modificare cohibitiones visibilitatis",
-       "revdelete-hide-text": "Textus emendationis",
+       "revdelete-hide-text": "Textus redactionis",
        "revdelete-hide-image": "Celare contentum fasciculi",
-       "revdelete-hide-comment": "Summarium emendationis",
+       "revdelete-hide-comment": "Summarium recensionis",
        "revdelete-hide-user": "Nomen usoris/locus IP",
        "revdelete-radio-same": "non mutare",
        "revdelete-radio-set": "Celare",
        "revdelete-otherreason": "Causa alia vel explicatio:",
        "revdelete-reasonotherlist": "Causa alia",
        "revdelete-edit-reasonlist": "Causas deletionum recensere",
-       "revdelete-offender": "Auctor emendationis:",
+       "revdelete-offender": "Redegit:",
        "suppressionlog": "Acta suppressionum",
        "mergehistory": "Historias paginarum confundere",
-       "mergehistory-box": "Emendationes duarum paginarum confundere:",
+       "mergehistory-box": "Redactiones duarum paginarum conflare:",
        "mergehistory-from": "Pagina imponenda:",
        "mergehistory-into": "Pagina petita:",
        "mergehistory-list": "Historia recensionum confusibilis",
        "mergehistory-go": "Monstrare recensiones confusibiles",
-       "mergehistory-submit": "Confundere emendationes",
-       "mergehistory-empty": "Nullae emendationes confusibiles.",
+       "mergehistory-submit": "Redactiones conflare",
+       "mergehistory-empty": "Nullae redactiones, quae conflari possint.",
        "mergehistory-autocomment": "confundavit [[:$1]] cum [[:$2]]",
        "mergehistory-comment": "confundavit [[:$1]] cum [[:$2]]: $3",
        "mergehistory-reason": "Causa:",
        "mergelog": "Acta confundendi",
        "revertmerge": "Inconfundere",
        "history-title": "Historia paginae \"$1\"",
+       "difference-title": "Quantum redactiones paginae \"$1\" differant",
        "lineno": "Linea $1:",
        "compareselectedversions": "Redactiones selectas conferre",
-       "showhideselectedversions": "Monstrare/celare emendationes selectas",
+       "showhideselectedversions": "Redactiones selectas vel ostendi vel celari iubere",
        "editundo": "abrogare",
        "diff-empty": "(eadem)",
        "searchresults": "Eventum investigationis",
        "search-suggest": "Nonne dicere voluisti: $1",
        "search-rewritten": "Ostenduntur, quae per \"$1\" inveniuntur. Profecto scrutinari, ubi \"$2\" contineatur!",
        "search-interwiki-caption": "Alia incepta",
-       "search-interwiki-default": "$1 eventus:",
+       "search-interwiki-default": "Inventa apud $1:",
        "search-interwiki-more": "(plus)",
        "search-relatedarticle": "Relata",
        "searchrelated": "relata",
        "preferences": "Modi",
        "mypreferences": "Modi",
        "prefs-edits": "Numerus recensionum:",
-       "prefs-skin": "Aspectum",
+       "prefs-skin": "Formae delectus",
        "skin-preview": "Prospectus",
        "datedefault": "Modus nondum delectus",
        "prefs-user-pages": "Paginae usoris",
        "prefs-watchlist-days": "Quot dies index respiciat:",
        "prefs-watchlist-days-max": "Maximum spatium: $1 {{PLURAL:$1|dies|dies}}",
        "prefs-watchlist-edits": "Quot mutationes index summum respiciat:",
-       "prefs-watchlist-edits-max": "Numerus maximus: 1000",
+       "prefs-watchlist-edits-max": "Maximus numerus: 1000",
        "prefs-misc": "Misc",
        "prefs-resetpass": "Tesseram mutare",
        "prefs-email": "Modi ad litteras electronicas spectantes",
-       "prefs-rendering": "Conspectus",
+       "prefs-rendering": "Aspectus",
        "saveprefs": "Hos modos servare",
        "restoreprefs": "Omnes (diversi) modi in integrum restituantur",
-       "prefs-editing": "Mensura capsae verbi",
+       "prefs-editing": "Recensere",
        "rows": "Lineae:",
        "columns": "Columnae:",
        "searchresultshead": "Figuratio eventorum investigationis",
        "recentchangescount": "Quot mutationes index respiciat:",
        "prefs-help-recentchangescount": "Inclusis nuper mutatis, paginarum historiis, actis",
        "savedprefs": "Modi tui servati sunt.",
-       "timezonelegend": "Zona temporis:",
+       "timezonelegend": "Zona temporalis:",
        "localtime": "Hora indigena:",
        "timezoneuseoffset": "Alia (da dissimilitudinem cinguli horae)",
        "servertime": "Hora moderatri:",
        "prefs-info": "Generalia",
        "prefs-i18n": "Sermonis delectus",
        "prefs-signature": "Subscriptio",
+       "prefs-dateformat": "Forma temporalium",
+       "prefs-timeoffset": "Zona temporalis",
+       "prefs-advancedediting": "Generalia",
+       "prefs-editor": "Capsa editoria",
        "prefs-preview": "Prospectus",
        "prefs-advancedrc": "Modi speciales",
-       "prefs-advancedwatchlist": "Indicis modi speciales",
+       "prefs-advancedwatchlist": "Modi speciales",
        "prefs-displayrc": "Modi generales",
        "prefs-displaywatchlist": "Modi generales",
        "prefs-diffs": "Differentiae",
        "right-autoconfirmed": "Paginas semiprotectas recensere",
        "right-delete": "Paginas delere",
        "right-bigdelete": "Paginas magnarum historiarum delere",
-       "right-deleterevision": "Emendationes paginarum delere vel restituere",
+       "right-deleterevision": "Quasdam paginarum redactiones delere vel restituere",
        "right-browsearchive": "Paginas deletas quaerere",
        "right-undelete": "Paginam restituere",
-       "right-suppressrevision": "Emendationes magistratus celatas inspicere vel restituere",
+       "right-suppressrevision": "Quasvis redactiones cuiuscumque conlatoris inspicere nec non celare vel visibiles reddere",
        "right-suppressionlog": "Acta privata inspicere",
        "right-block": "Usores alios obstruere ne recensere possunt",
        "right-blockemail": "Usorem obstruere ne litteras electronicas mittere potest",
        "action-upload_by_url": "hunc fasciculum imponere ex inscriptione URL",
        "action-writeapi": "API scripturae usere",
        "action-delete": "hanc paginam delere",
-       "action-deleterevision": "hanc emendationem delere",
+       "action-deleterevision": "hanc redactionem delere",
        "action-browsearchive": "paginas deletas quaerere",
        "action-undelete": "hanc paginam restituere",
-       "action-suppressrevision": "hanc emendationem magistratus celatam inspicere vel restituere",
+       "action-suppressrevision": "hanc redactionem celatam inspicere neu restituere",
        "action-suppressionlog": "haec acta privata inspicere",
        "action-block": "hunc usorem obstruere ne recensere potest",
        "action-protect": "protectionem huius paginae mutare",
        "rcshowhidemine": "$1 conlationes meas",
        "rcshowhidemine-show": "Monstrare",
        "rcshowhidemine-hide": "Celare",
+       "rcshowhidecategorization": "$1 classificationes",
+       "rcshowhidecategorization-show": "Ostendere",
+       "rcshowhidecategorization-hide": "Supprimere",
        "rclinks": "Monstrare $1 nuperrime mutata in $2 diebus proximis.<br />$3",
-       "diff": "diss",
+       "diff": "diff",
        "hist": "hist",
        "hide": "celare",
        "show": "monstrare",
        "listfiles_user": "Usor",
        "listfiles_size": "Magnitudo",
        "listfiles_description": "Descriptio",
-       "listfiles_count": "Emendationes",
+       "listfiles_count": "Redactiones",
        "file-anchor-link": "Fasciculus",
        "filehist": "Historia fasciculi",
-       "filehist-help": "Ad emendationem fasciculi inspiciendum, preme in diem/tempus.",
-       "filehist-deleteall": "delere omnes emendationes",
+       "filehist-help": "Presso die vel tempore fasciculum videbis, sicut tunc temporis apparuit.",
+       "filehist-deleteall": "omnes redactiones delere",
        "filehist-deleteone": "delere",
        "filehist-revert": "revertere",
        "filehist-current": "recentissima",
        "filehist-datetime": "Dies/Tempus",
        "filehist-thumb": "Minutio",
-       "filehist-thumbtext": "Minutio emendationis ex $1",
+       "filehist-thumbtext": "Minutum speculum redactionis $1 factae",
        "filehist-nothumb": "Nulla minutio",
        "filehist-user": "Usor",
        "filehist-dimensions": "Dimensiones",
        "sharedupload-desc-create": "Hic fasciculus apud {{grammar:accusative|$1}} iacet; in aliis inceptis adhiberi potest.\nFortasse [$2 paginam descriptionis fasciculi] ibi sitam recensere vis.",
        "filepage-nofile": "Fasciculus huius nominis non est.",
        "filepage-nofile-link": "Fasciculus huius nominis non est, sed [$1 fasciculum imponere] potes.",
-       "uploadnewversion-linktext": "Emendationem novam huius fasciculi imponere",
+       "uploadnewversion-linktext": "Novam huius fasciculi redactionem imponere",
        "shared-repo-from": "apud {{grammar:accusative|$1}}",
        "shared-repo": "repositorium commune",
        "shared-repo-name-wikimediacommons": "Vicimedia Communia",
        "filerevert": "Revertere $1",
        "filerevert-legend": "Reverti fasciculum",
-       "filerevert-intro": "Reverteris '''[[Media:$1|$1]]''' ad [emendationem $4 ex $3, $2].",
+       "filerevert-intro": "Reversurus es '''[[Media:$1|$1]]''' ad [$4 redactionem quae $2, $3 facta erat].",
        "filerevert-comment": "Causa:",
-       "filerevert-defaultcomment": "Reverti ad emendationem ex $2, $1 ($3)",
+       "filerevert-defaultcomment": "Reverti ad redactionem die $1, hora $2 ($3) factam",
        "filerevert-submit": "Revertere",
-       "filerevert-success": "'''[[Media:$1|$1]]''' reversum est ad [emendationem $4 ex $3, $2].",
+       "filerevert-success": "'''[[Media:$1|$1]]''' reversum est ad [$4 redactionem quae $2, $3 facta erat].",
        "filedelete": "Delere $1",
        "filedelete-legend": "Fasciculum delere",
        "filedelete-intro": "Deles fasciculum '''[[Media:$1|$1]]''' una cum tota eius historia.",
-       "filedelete-intro-old": "Deles fasciculi '''[[Media:$1|$1]]''' emendationem [$4 ex $3, $2].",
+       "filedelete-intro-old": "Delebis fasciculi '''[[Media:$1|$1]]''' redactionem [$4 die $2, hora $3 factam].",
        "filedelete-comment": "Causa:",
        "filedelete-submit": "Delere",
-       "filedelete-success": "'''$1''' deletum est.",
-       "filedelete-success-old": "Emendatio fasciculi '''[[Media:$1|$1]]''' ex $3, $2 deletum est.",
+       "filedelete-success": "Fasciculus '''$1''' deletus est.",
+       "filedelete-success-old": "Redactio fasciculi '''[[Media:$1|$1]]''', sicut $2, $3 facta erat, deleta est.",
        "filedelete-nofile": "'''$1''' non existit.",
        "filedelete-otherreason": "Causa alia vel explicatio:",
        "filedelete-reason-otherlist": "Causa alia",
        "ncategories": "$1 {{PLURAL:$1|categoria|categoriae}}",
        "nlinks": "$1 {{PLURAL:$1|nexus|nexus}}",
        "nmembers": "$1 {{PLURAL:$1|inest|insunt}}",
-       "nrevisions": "$1 {{PLURAL:$1|emendatio|emendationes}}",
+       "nrevisions": "$1 {{PLURAL:$1|redactio|redactiones}}",
        "lonelypages": "Paginae non annexae",
        "uncategorizedpages": "Paginae sine categoriis",
        "uncategorizedcategories": "Categoriae sine categoriis",
        "suppress": "Censura",
        "booksources": "Librorum fontes",
        "booksources-search-legend": "Fontes impressas quaerere",
+       "booksources-search": "Quaerere",
        "specialloguserlabel": "Usor:",
        "speciallogtitlelabel": "Destinatum (titulus aut usor):",
        "log": "Acta",
        "listusers-noresult": "Nullus usor inventus.",
        "listusers-blocked": "(obstructus)",
        "activeusers": "Index usorum activorum",
-       "activeusers-count": "{{PLURAL:$1|una recensio recens|$1 recensiones recentes}} {{PLURAL:$3|die proximo|in diebus $3 proximis}}",
+       "activeusers-count": "{{PLURAL:$1|una recensio {{PLURAL:$3|hodie|his $3 diebus}} facta|$1 recensiones {{PLURAL:$3|hodie|his $3 diebus}} factae}}",
        "activeusers-hidebots": "Celare automata",
        "activeusers-hidesysops": "Celare magistratus",
        "activeusers-noresult": "Nullus usor inventus.",
        "unwatch": "Non iam observare",
        "unwatchthispage": "Non iam observare",
        "notanarticle": "Res non est",
-       "notvisiblerev": "Emendatio deleta est",
+       "notvisiblerev": "Superior redactio ab alio conlatore facta deleta est",
        "watchlist-details": "{{PLURAL:$1|$1 paginam|$1 paginas}} observas.",
        "wlheader-enotif": "Mutationes si quae factae erunt, electronice tibi nuntiabuntur.",
        "wlheader-showupdated": "Paginae nondum a te inspectae <strong>typis crassioribus</strong> ostenduntur.",
        "wlshowhideliu": "a conlatoribus notis factas",
        "wlshowhideanons": "sine nomine factas",
        "wlshowhidemine": "meas",
+       "wlshowhidecategorization": "classificationes",
        "watchlist-options": "Huius indicis modi",
        "watching": "Custodiens...",
        "unwatching": "Decustodiens...",
        "enotif_impersonal_salutation": "Usor {{grammar:genitive|{{SITENAME}}}}",
        "enotif_lastdiff": "Vide $1 ad hanc recensionem inspiciendum.",
        "enotif_anon_editor": "usor ignotus $1",
-       "enotif_body": "\nSalve $WATCHINGUSERNAME,\n\nPagina {{grammar:genitive|{{SITENAME}}}} $PAGETITLE ab $PAGEEDITOR die $PAGEEDITDATE $CHANGEDORCREATED est, vide emendationem currentem apud $PAGETITLE_URL\n\n$NEWPAGE\n\nAuctor hunc summarium dedit: $PAGESUMMARY $PAGEMINOREDIT\n\nContact the editor:\nlitterae electronicae: $PAGEEDITOR_EMAIL\nvici: $PAGEEDITOR_WIKI\n\nThere will be no other notifications in case of further changes unless you visit this page.\nYou could also reset the notification flags for all your watched pages on your watchlist.\n\n             Your friendly {{SITENAME}} notification system\n\n--\nTo change your watchlist settings, visit\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nFeedback and further assistance:\n$HELPPAGE",
+       "enotif_body": "\nSalve $WATCHINGUSERNAME,\n\nPagina {{grammar:genitive|{{SITENAME}}}} $PAGETITLE ab $PAGEEDITOR die $PAGEEDITDATE $CHANGEDORCREATED est. Vide redactionem currentem apud $PAGETITLE_URL\n\n$NEWPAGE\n\nCuius auctor hoc summarium dedit: $PAGESUMMARY $PAGEMINOREDIT\n\nUt conlatorem adloquaris:\nlitterae electronicae: $PAGEEDITOR_EMAIL\nvici: $PAGEEDITOR_WIKI\n\nDe futuris recensionibus non certior fies nisi nomine dato paginam ipsam inspexeris. Praeterea licet omnes paginas non iam observandas notare.\n\n             Your friendly {{SITENAME}} notification system\n\n--\nUt paginarum observandarum modos spectes, ito ad\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nFeedback and further assistance:\n$HELPPAGE",
        "created": "creata",
        "changed": "mutata",
        "deletepage": "Delere paginam",
        "confirm": "Adfirmare",
-       "excontent": "contenta erant: '$1'",
-       "excontentauthor": "contenta erant: '$1' (et contributor unicus erat '[[Special:Contributions/$2|$2]]')",
-       "exbeforeblank": "contenta priusquam pagina facta vacua erant: '$1'",
+       "excontent": "contenta fuerant: \"$1\"",
+       "excontentauthor": "contenta fuerant: \"$1\", conlata a solo \"[[Special:Contributions/$2|$2]]\" ([[User talk:$2|Disputatio]])",
+       "exbeforeblank": "pagina rasa continuerat: \"$1\"",
        "delete-confirm": "Delere \"$1\"",
        "delete-legend": "Delere",
-       "historywarning": "'''Monitio:''' Pagina quam delere vis historiam {{PLURAL:$1|unius fere emendationis|$1 fere emendationum}} habet:",
+       "historywarning": "'''Cave:''' Paginae, quam deleturus es, historia est {{PLURAL:$1|unius redactionis|$1 redactionum}}:",
        "confirmdeletetext": "Paginam cum tota historia eius delebis.\nAdfirma quaesumus te paginam re vera delere velle, te consequentias intellere, et actionem tuam [[{{MediaWiki:Policy-url}}|consilio]] congruere.",
        "actioncomplete": "Actum perfectum",
        "actionfailed": "Actum non feliciter evenit",
        "dellogpage": "Index deletionum",
        "dellogpagetext": "Subter est index deletionum recentissimarum.",
        "deletionlog": "index deletionum",
-       "reverted": "Reversum ad emendationem proximam",
+       "reverted": "Reversa in superiorem redactionem",
        "deletecomment": "Causa:",
        "deleteotherreason": "Causa alia vel explicatio:",
        "deletereasonotherlist": "Causa alia",
        "rollbacklinkcount": "reverti {{PLURAL:$1|unam recensionem|$1 recensiones}}",
        "rollbacklinkcount-morethan": "reverti plus quam {{PLURAL:$1|unam recensionem|$1 recensiones}}",
        "rollbackfailed": "Reversum defecit",
-       "cantrollback": "Haec non potest reverti; conlator proximus solus auctor huius rei est.",
-       "alreadyrolled": "Ad emendationem proximam paginae [[:$1]] ab usore [[User:$2|$2]] ([[User talk:$2|Disputatio]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) reverti non potest; alius paginam iam recensuit vel revertit.\n\nEmendatio proxima ab usore [[User:$3|$3]] ([[User talk:$3|Disputatio]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) effecta est.",
+       "cantrollback": "Haec reverti non potest;\nhic conlator solus auctor huius paginae est.",
+       "alreadyrolled": "Ad superiorem redactionem paginae [[:$1]] a conlatore [[User:$2|$2]] ([[User talk:$2|Disputatio]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) facta reverti non potest;\nalius quisquam paginam iam recensuit vel revertit.\n\nQuae novissima redactio effecta est a conlatore [[User:$3|$3]] ([[User talk:$3|Disputatio]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Summarium erat: <em>$1</em>.",
-       "revertpage": "Reverti recensiones ab usore [[Special:Contributions/$2|$2]] ([[User talk:$2|Disputatio]]) ad emendationem proximam ab [[User:$1|$1]]",
-       "rollback-success": "Reverti recensiones ab usore $1\nad emendationem proximam ab $2.",
+       "revertpage": "Recensiones a conlatore [[Special:Contributions/$2|$2]] ([[User talk:$2|Disputatio]]) factas in superiorem redactionem a conlatore [[User:$1|$1]] factam restitui",
+       "rollback-success": "Redactiones a conlatore $1 factae reversae sunt;\nrestitutae in superiorem redactionem a conlatore $2 factam.",
        "protectlogpage": "Index protectionum",
        "protectlogtext": "Subter est index protectionum et deprotectionum paginarum. Vide [[Special:ProtectedPages|indicem paginarum nunc protectarum]].",
        "protectedarticle": "protegit \"[[$1]]\"",
        "undeletepage": "Videre et restituere paginas deletas",
        "viewdeletedpage": "Paginas deletas inspicere",
        "undeletepagetext": "{{PLURAL:$1|Pagina sequens deleta est sed tabulis manens restitui potest.|Paginae $1 sequentes deletae sunt sed tabulis manentes restitui possunt.}}\nTabulae nonnumquam deletae sunt.",
-       "undelete-fieldset-title": "Emendationes restituere",
-       "undeleterevisions": "$1 {{PLURAL:$1|emendatio servata|emendationes servatae}}",
-       "undeletehistory": "Si paginam restituis, omnes emendationes restituentur ad historiam.\nSi pagina nova cum ipso nomine post deletionem creata est, emendationes restitutae in historia priori apparebunt.",
-       "undelete-revision": "Emendatio deleta paginae $1 (ex $5, $4) ab usore $3:",
-       "undelete-nodiff": "Nulla emendatio prior inventa.",
+       "undelete-fieldset-title": "Redactiones restituere",
+       "undeleterevisions": "$1 {{PLURAL:$1|redactio deleta|redactiones deletae}}",
+       "undeletehistory": "Si paginam restitueris, omnes redactiones restituentur ad historiam.\nSi pagina nova eiusdem nominis post deletionem creata est, redactiones restitutae in historia priori apparebunt.",
+       "undelete-revision": "Redactio deletae paginae $1 (sicut $4, $5 a conlatore $3 facta erat):",
+       "undelete-nodiff": "Redactio prior non est.",
        "undeletebtn": "Restituere",
        "undeletelink": "inspicere/restituere",
        "undeleteviewlink": "inspicere",
        "undeleteinvert": "Selectionem invertere",
        "undeletecomment": "Causa:",
-       "undeletedrevisions": "{{PLURAL:$1|1 emendatio recuperata|$1 emendationes recuperatae}}",
-       "undeletedrevisions-files": "{{PLURAL:$1|1 emendatio recuperata|$1 emendationes recuperatae}} et {{PLURAL:1 fasciculus recuperatus|$2 fasciculi recuperati}}",
-       "undeletedfiles": "{{PLURAL:$1|1 fasciculus recuperatus|$1 fasciculi recuperati}}",
+       "undeletedrevisions": "{{PLURAL:$1|1 redactio restituta est|$1 redactiones restitutae sunt}}",
+       "undeletedrevisions-files": "{{PLURAL:$1|1 redactio restituta est|$1 redactiones restitutae sunt}} et {{PLURAL:1 fasciculus restitutus est|$2 fasciculi restituti sunt}}",
+       "undeletedfiles": "{{PLURAL:$1|1 fasciculus restitutus est|$1 fasciculi restituti sunt}}",
        "cannotundelete": "Abrogatio deletionis fefellit; fortasse aliquis iam paginam restituit.",
        "undelete-header": "Pro paginis nuper deletis, vide [[Special:Log/delete|indicem deletionum]].",
        "undelete-search-box": "Quaerere inter paginas iam deletas",
        "import-upload-filename": "Nomen fasciculi:",
        "import-comment": "Sententia:",
        "importstart": "Adportare paginas...",
-       "import-revision-count": "$1 {{PLURAL:$1|emendatio|emendationes}}",
+       "import-revision-count": "$1 {{PLURAL:$1|redactio|redactiones}}",
        "importbadinterwiki": "Nexus intervicius malus",
        "importsuccess": "Adportatio finita!",
        "import-noarticle": "Nulla pagina importanda!",
        "xml-error-string": "$1 in linea $2 et columna $3 (octetus $4): $5",
        "import-upload": "XML imponere et importare",
        "importlogpage": "Acta adportationum",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|emendatio|emendationes}}",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|emendatio|emendationes}} ex $2",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|redactio importata est|redactiones importatae sunt}}",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|redactio ex $2 importata est|redactiones ex $2 importatae sunt}}",
        "tooltip-pt-userpage": "Pagina usoris tua",
        "tooltip-pt-mytalk": "Pagina disputationis tuae",
        "tooltip-pt-anontalk": "Disputatio de recensionibus ex hoc loco IP factis",
        "tooltip-ca-history": "Superiores huius paginae versiones",
        "tooltip-ca-protect": "Protegere hanc paginam",
        "tooltip-ca-delete": "Delere hanc paginam",
-       "tooltip-ca-undelete": "Restituere emendationes huic paginae conlatas antequam haec pagina deleta esset",
+       "tooltip-ca-undelete": "Restituere recensiones ante paginam deletam factas",
        "tooltip-ca-move": "Movere hanc paginam",
        "tooltip-ca-watch": "Hanc paginam observandam habere",
        "tooltip-ca-unwatch": "Hanc paginam non iam observandam habere",
-       "tooltip-search": "Quaerere aliquid in {{grammar:ablative|{{SITENAME}}}}",
-       "tooltip-search-go": "I ad paginam cum hoc titulo exacto, si est",
-       "tooltip-search-fulltext": "Hunc textum in paginis quaerere",
+       "tooltip-search": "Aliquid in {{grammar:ablative|{{SITENAME}}}} quaerere",
+       "tooltip-search-go": "Si modo sit, paginam huius ipsius tituli invisere",
+       "tooltip-search-fulltext": "Hunc textum in paginis requirere",
        "tooltip-p-logo": "Ire ad paginam primam",
        "tooltip-n-mainpage": "Ire ad paginam primam",
        "tooltip-n-mainpage-description": "Ire ad paginam primam",
        "tooltip-t-upload": "Fasciculos imponere",
        "tooltip-t-specialpages": "Index paginarum specialium",
        "tooltip-t-print": "Forma impressibilis huius paginae",
-       "tooltip-t-permalink": "Nexus perpetuus ad hanc emendationem paginae",
+       "tooltip-t-permalink": "Nexus perpetuus ad hanc paginae redactionem",
        "tooltip-ca-nstab-main": "Videre paginam",
        "tooltip-ca-nstab-user": "Videre paginam usoris",
-       "tooltip-ca-nstab-special": "Haec est pagina specialis. Pagina ipsa recenseri non potest.",
+       "tooltip-ca-nstab-special": "Ea est pagina specialis, quin recenseatur.",
        "tooltip-ca-nstab-project": "Videre paginam inceptorum",
        "tooltip-ca-nstab-image": "Videre paginam fasciculi",
        "tooltip-ca-nstab-mediawiki": "Videre nuntium systematis",
        "pageinfo-firstuser": "Creator paginae",
        "pageinfo-firsttime": "Dies et tempus creationis paginae",
        "pageinfo-lastuser": "Usor qui ultimam recensionem fecit",
-       "pageinfo-lasttime": "Dies ultimae emendationis",
+       "pageinfo-lasttime": "Quando novissime recensita sit",
        "pageinfo-recent-edits": "Praesens numerus recensionum (intra praeterita $1)",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Categoria celata|Categoriae celatae}} ($1)",
        "pageinfo-toolboxlink": "De hac pagina",
        "markedaspatrolled": "Indicare hanc paginam qua circumita",
        "patrol-log-page": "Acta emendationum circumitarum",
        "log-show-hide-patrol": "$1 acta emendationum circumitarum",
-       "deletedrevision": "Delevit emendationem $1 veterem",
+       "deletedrevision": "Abolita redactio imaginis $1",
        "previousdiff": "← Differentia superior",
        "nextdiff": "Differentia proxima →",
        "imagemaxsize": "Magnitudo maxima fasciculorum:<br />\n''(in pagina descriptionis fasciculi)''",
        "file-info-size": "$1 × $2 elementa imaginalia, magnitudo fasciculi: $3, typus MIME: $4",
        "file-nohires": "Nulla maior resolutio exstat.",
        "svg-long-desc": "fasciculus SVG, nominale $1 × $2 elementa imaginalia, magnitudo fasciculi: $3",
-       "show-big-image": "Resolutio completa",
+       "show-big-image": "Sua resolutio",
        "show-big-image-size": "$1 × $2 elementa imaginalia",
        "file-info-gif-frames": "$1 {{PLURAL:$1|replum|repla}}",
        "newimages": "Fasciculi novi",
        "ilsubmit": "Quaerere",
        "bydate": "ex die",
        "hours": "{{PLURAL:$1|hanc horam|has $1 horas}}",
-       "days": "{{PLURAL:$1|$1 diem|$1 dies}}",
+       "days": "{{PLURAL:$1|hunc diem|hos $1 dies}}",
+       "hours-ago": "abhinc $1 {{PLURAL:$1|horam|horas}}",
        "metadata": "Metadata",
        "metadata-help": "Hic fasciculus alias res continet, saepius a machina originatore additas, et (si fasciculus postea recensus sit) fortasse corrigendas.",
        "metadata-expand": "Plura ostende",
        "exif-imagedescription": "Descriptio imaginis",
        "exif-model": "Typus photomachinae",
        "exif-artist": "Auctor",
-       "exif-exifversion": "Emendatio Exif",
+       "exif-exifversion": "Redactio modi \"Exif\"",
        "exif-colorspace": "Spatium colorimetricum",
        "exif-pixelydimension": "Amplitudo imaginis",
        "exif-pixelxdimension": "Altitudo imaginis",
        "tags-hitcount": "$1 {{PLURAL:$1|mutatum|mutata}}",
        "compare-page1": "Pagina 1",
        "compare-page2": "Pagina 2",
-       "compare-rev1": "Emendatio 1",
-       "compare-rev2": "Emendatio 2",
+       "compare-rev1": "Redactio una",
+       "compare-rev2": "Redactio altera",
        "htmlform-submit": "Submittere",
        "htmlform-reset": "Mutationes abrogare",
        "htmlform-selectorother-other": "Aliud",
index 60117ff..d9ba73a 100644 (file)
@@ -15,7 +15,8 @@
                        "VT98Fan",
                        "Zinneke",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Linken ënnersträichen:",
        "createaccount-title": "Opmaache vun engem Benotzerkont op {{SITENAME}}",
        "createaccount-text": "Et gouf e Benotzerkont \"$2\" fir Iech op {{SITENAME}} ($4) ugeluecht mat dem Passwuert \"$3\".\nDir sollt Iech aloggen an Äert Passwuert elo änneren.\n\nWann dëse Benotzerkont ongewollt ugeluecht gouf, kënnt Dir dës Noriicht einfach ignoréieren.",
        "login-throttled": "Dir hutt zevill dacks versicht Iech anzeloggen.\nWaart w.e.g. $1 ier Dir et nach eng Kéier probéiert.",
-       "login-abort-generic": "Dir sidd net ageloggt - Aloggen ofgebrach",
+       "login-abort-generic": "Äert Aloggen huet net funktionéiert - Ofgebrach",
        "login-migrated-generic": "Äre Benotzerkont gouf migréiert an Äre Benotzernumm gëtt et net méi op dëser Wiki.",
        "loginlanguagelabel": "Sprooch: $1",
        "suspicious-userlogout": "Är Ufro fir Iech auszeloggen gouf refuséiert well et sou ausgesäit wéi wa se vun engem futtise Browser oder Proxy-Tëschespäicher kënnt.",
        "botpasswords-label-resetpassword": "D'Passwuert zrécksetzen",
        "botpasswords-label-grants-column": "Accordéiert",
        "botpasswords-bad-appid": "Den Numm vum Bot \"$1\" ass net valabel.",
+       "botpasswords-created-body": "D'Botpasswuert fir de Bot-Numm \"$1\" vum Benotzer ''$2'' gouf ugeluecht.",
        "botpasswords-updated-title": "Botpasswuert aktualiséiert",
-       "botpasswords-updated-body": "D'Botpasswuert \"$1\" gouf aktualiséiert.",
+       "botpasswords-updated-body": "D'Botpasswuert fir de Bot-Numm \"$1\" vum Benotzer ''$2'' gouf aktualiséiert.",
        "botpasswords-deleted-title": "Botpasswuert geläscht",
-       "botpasswords-deleted-body": "D'Botpasswuert \"$1\" gouf geläscht.",
+       "botpasswords-deleted-body": "D'Botpasswuert fir de Bot-Numm \"$1\" vum Benotzer ''$2'' gouf geläscht.",
        "botpasswords-not-exist": "De Benotzer \"$1\" huet kee Botpasswuert mam Numm \"$2\".",
        "resetpass_forbidden": "Passwierder kënnen net geännert ginn.",
        "resetpass-no-info": "Dir musst ageloggt sinn, fir direkt op dës Säit ze kommen.",
        "newarticle": "(Nei)",
        "newarticletext": "Dir hutt op e Link vun enger Säit geklickt, déi et nach net gëtt. Fir déi Säit unzeleeën, gitt w.e.g. Ären Text an déi Këscht hei drënner an (kuckt d'[$1 Hëllef Säit] fir méi Informatiounen). Wann Dir duerch een Iertum heihi komm sidd, da klickt einfach op de Knäppchen '''Zréck''' vun Ärem Browser.",
        "anontalkpagetext": "---- ''Dëst ass d'Diskussiounssäit fir en anonyme Benotzer deen nach kee Kont opgemaach huet oder en net benotzt. Dowéinst musse mir d'IP Adress benotzen, fir de Benotzer z'identifizéieren.\nSou eng IP Adress ka vun e puer Benotzer gedeelt ginn.\nWann Dir en anonyme Benotzer sidd an Dir irrelevant Bemierkunge krut, [[Special:UserLogin/signup|maacht w.e.g. e Kont op]] oder [[Special:UserLogin|loggt Iech an]], fir weider Verwiesselunge mat aneren anonyme Benotzer ze verhënneren.''",
-       "noarticletext": "Dës Säit huet momentan keen Text.\nDir kënnt op anere Säiten no [[Special:Search/{{PAGENAME}}|dësem Säitentitel sichen]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} an den entspriechende Logbicher nokucken] oder [{{fullurl:{{FULLPAGENAME}}|action=edit}} sou eng Säit uleeën]</span>.",
+       "noarticletext": "Dës Säit huet elo keen Text.\nDir kënnt op anere Säiten no [[Special:Search/{{PAGENAME}}|dësem Säitentitel sichen]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} an den entspriechende Logbicher nokucken] oder [{{fullurl:{{FULLPAGENAME}}|action=edit}} dës Säit uleeën]</span>.",
        "noarticletext-nopermission": "Elo ass keen Text op dëser Säit.\nDir kënnt op anere Säiten [[Special:Search/{{PAGENAME}}|no dësem Säitentitel sichen]], oder <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} an de Logbicher sichen]</span>, mä Dir hutt net déi néideg Rechter fir dës Säit unzeleeën.",
        "missing-revision": "D'Versioun #$1 vun der Säit mam Numm \"{{FULLPAGENAME}}\" gëtt et net.\n\nDat geschitt normalerweis wann Dir op e vereelste Link vun enger Versioun vun enger Säit klickt déi geläscht ginn ass.\nDetailer fannt Dir am [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} Logbuch vum Läschen].",
        "userpage-userdoesnotexist": "De Benotzerkont \"<nowiki>$1</nowiki>\" ass net registréiert.\nIwwerpréift w.e.g. op Dir dës Säit uleeën/ännere wëllt.",
        "rev-delundel": "weisen/verstoppen",
        "rev-showdeleted": "Weisen",
        "revisiondelete": "Versioune läschen/restauréieren",
-       "revdelete-nooldid-title": "Ongülteg Zilversioun",
+       "revdelete-nooldid-title": "Ongëlteg Zilversioun",
        "revdelete-nooldid-text": "Dir hutt entweder keng Versioun ugi fir dës Funktioun ze benotzen, oder déi Versioun déi Dir uginn hutt gëtt et net, oder Dir versicht déi aktuell Versioun ze verstoppen.",
        "revdelete-no-file": "De Fichier deen ugi war gëtt et net.",
        "revdelete-show-file-confirm": "Sidd Dir sécher datt Dir déi geläschte Versioun vum Fichier \"<nowiki>$1</nowiki>\" vum $2 ëm $3 gesi wëllt?",
        "grant-createaccount": "Benotzerkonten opmaachen",
        "grant-createeditmovepage": "Säiten uleeën, änneren a réckelen",
        "grant-delete": "Säiten, Versiounen a Rubriken a Logbicher läschen",
-       "grant-editinterface": "MediaWiki-Nummraum a Benotzer CSS/JS änneren",
-       "grant-editmycssjs": "Ären eegene Benotzer CSS/JavaScript änneren",
+       "grant-editinterface": "MediaWiki-Nummraum a Benotzer CSS/JavaScript änneren",
+       "grant-editmycssjs": "Äre Benotzer CSS/JavaScript änneren",
        "grant-editmyoptions": "Ännert Är Benotzerastellungen",
        "grant-editmywatchlist": "Ännert Är Iwwerwaachungslëscht",
        "grant-editpage": "Säiten déi et gëtt änneren",
        "grant-editprotected": "Gespaart Säiten änneren",
        "grant-oversight": "Benotzer verstoppen a Versioune läschen",
-       "grant-patrol": "Ännerungen op Säiten iwwerwaachen",
+       "grant-patrol": "Ännerungen op Säiten kontrolléieren",
        "grant-protect": "Säite spären an entspären",
        "grant-rollback": "Ännerungen op Säiten zrécksetzen",
        "grant-sendemail": "Anere Benotzer E-Maile schécken",
        "recentchangeslinked-page": "Säitennumm:",
        "recentchangeslinked-to": "Weis Ännerungen zu de verlinkte Säiten aplaz vun der gefroter Säit",
        "recentchanges-page-added-to-category": "[[:$1]] an d'Kategorie derbäigesat",
-       "recentchanges-page-added-to-category-bundled": "{{PLURAL:$2|}}[[:$1]] a(n) {{PLURAL:$2|eng Säit|$2 Säiten}} an d'Kategorie derbäigesat",
+       "recentchanges-page-added-to-category-bundled": "{{PLURAL:$2|}}[[:$1]] a(n) [[Special:WhatLinksHere/$1|{{PLURAL:$2|eng Säit|$2 Säiten}}]] an d'Kategorie derbäigesat",
        "recentchanges-page-removed-from-category": "[[:$1]] erausgeholl aus der Kategorie",
-       "recentchanges-page-removed-from-category-bundled": "{{PLURAL:$2|}}[[:$1]] a(n) {{PLURAL:$2|eng Säit|$2 Säiten}} aus der Kategorie erausgeholl",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] a(n) [[Special:WhatLinksHere/$1|{{PLURAL:$2|eng Säit|$2 Säiten}}]] aus der Kategorie erausgeholl",
        "autochange-username": "Automatesch MediaWiki-Ännerung",
        "upload": "Eroplueden",
        "uploadbtn": "Fichier eroplueden",
        "uploadstash-badtoken": "D'Ausféiere vun dëser Aktioun huet net funktionéiert, vläicht well d'Informatiounen iwwer Är Rechter ofgelaf sinn. Probéiert et w.e.g. nach emol.",
        "uploadstash-errclear": "D'Läsche vun de Fichieren huet net funktionéiert.",
        "uploadstash-refresh": "Lëscht vun de Fichieren aktualiséieren",
+       "uploadstash-thumbnail": "Miniaturbild weisen",
        "img-auth-accessdenied": "Zougang refuséiert",
        "img-auth-nopathinfo": "PATH_INFO feelt.\nÄre Server ass net agestallt fir déi Informatioun weiderzeginn.\nEt kann u CGI leien an datt imag_auth net ënnerstëtzt gëtt.\nKuckt https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization",
        "img-auth-notindir": "De gefrote Pad ass net am Upload-Repertoire agestallt.",
        "alllogstext": "Dëst ass eng kombinéiert Lëscht vu Logbicher op {{SITENAME}}.\nDir kënnt d'Siche limitéieren wann Dir e Log-Typ, e Benotzernumm (case-senisitive) oder déi gefrote Säit (och case-senisitive) agitt.",
        "logempty": "Näischt fonnt.",
        "log-title-wildcard": "Titel fänkt mat dësem Text un",
-       "showhideselectedlogentries": "Déi erausgesichte Entréeën am Logbuch weisen/verstoppen",
+       "showhideselectedlogentries": "Déi erausgesicht Entréeën am Logbuch weisen/verstoppen",
        "checkbox-select": "Eraussichen:$1",
        "checkbox-all": "All",
        "checkbox-none": "Keen",
        "changecontentmodel-title-label": "Titel vun der Säit",
        "changecontentmodel-model-label": "Neie Modell vun enger Säit mat Inhalt",
        "changecontentmodel-reason-label": "Grond:",
+       "changecontentmodel-submit": "Änneren",
        "changecontentmodel-success-title": "De Modell vum Inhalt gouf geännert",
        "changecontentmodel-success-text": "Den Typ vum Inhalt vu(n) [[:$1]] gouf geännert.",
        "logentry-contentmodel-change-revertlink": "zrécksetzen",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|Versioun|Versiounen}} importéiert",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|Versioun|Versiounen}} importéiert vu(n) $2",
        "javascripttest": "JavaScript-Test",
-       "javascripttest-pagetext-noframework": "Dës Säit ass fir Java-Script-Tester reservéiert.",
-       "javascripttest-pagetext-unknownframework": "Onbekannten Test-Framework \"$1\".",
        "javascripttest-pagetext-unknownaction": "Onbekannt Aktioun \"$1\".",
-       "javascripttest-pagetext-frameworks": "Sicht w.e.g. eng vun dësen Test-Strukturen eraus: $1",
-       "javascripttest-pagetext-skins": "Sicht en Interface (skin) eraus fir d'Tester ze maachen:",
        "javascripttest-qunit-intro": "Kuckt d'[$1 Dokumentatioun vun den Tester] op mediawiki.org",
        "tooltip-pt-userpage": "{{GENDER:|Är Benotzer}}säit",
        "tooltip-pt-anonuserpage": "Benotzersäit vun der IP-Adress vun där aus Dir den Ament Ännerunge maachtt",
        "version-libraries-description": "Beschreiwung",
        "version-libraries-authors": "Auteuren",
        "redirect": "Viruleedung duerch e Fichier, e Benotzer, eng Säit, eng Versiouns-ID oder eng Logbuch-ID",
-       "redirect-legend": "Viruleedung op ee Fichier oder eng Säit",
        "redirect-summary": "Dës Spezialsäit ass eng Viruleedung op e Fichier (Fichiersnumm uginn), eng Säit (Versiounsnummer uginn), eng Benotzersäit (numeresch Benotzeridentifikatiounsnummer uginn) oder eng Entrée an engem Logbuch (vum Logbuch mat der ID).\nGebrauch:\n[[{{#Special:Redirect}}/file/Example.jpg]],\n[[{{#Special:Redirect}}/page/64308]],\n[[{{#Special:Redirect}}/revision/328429]],\n[[{{#Special:Redirect}}/user/101]], oder\n[[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Lass",
        "redirect-lookup": "Nosichen:",
        "logentry-newusers-create2": "De Benotzerkont $3 gouf vum $1 {{GENDER:$2|ugeluecht}}",
        "logentry-newusers-byemail": "De Benotzerkont $3 gouf vum $1 {{GENDER:$2|ugeluecht}} an d'Passwuert gouf per E-Mail geschéckt.",
        "logentry-newusers-autocreate": "De Benotzerkont $1 gouf automatesch {{GENDER:$2|ugeluecht}}",
+       "logentry-protect-protect": "$1 {{GENDER:$2|huet}} d'Säit $3 $4 gespaart",
+       "logentry-protect-protect-cascade": "$1 {{GENDER:$2|huet}} d'Säit $3 $4 gepaart [Kaskadespär]",
        "logentry-rights-rights": "$1 {{GENDER:$2|huet}} d'Gruppen zou deenen de Benotzer $3 gehéiert vu(n) $4 op $5 geännert",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|huet}} d'Gruppen zou deenen de Benotzer $3 gehéiert geännert",
        "logentry-rights-autopromote": "De Benotzer $1 {{GENDER:$2|krut}} d'Benotzerrechter automatesch vu(n) $4 op $5 geännert",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "Symboler",
        "special-characters-group-greek": "Griichesch",
+       "special-characters-group-greekextended": "Griichesch erweidert",
        "special-characters-group-cyrillic": "Kyrillisch",
        "special-characters-group-arabic": "Arabesch",
        "special-characters-group-arabicextended": "Arabesch, erweidert",
        "mw-widgets-titleinput-description-redirect": "viruleeden op $1",
        "api-error-blacklisted": "Sicht w.e.g. en aneren Titel, dee méi iwwer de Sujet ausseet.",
        "sessionprovider-generic": "$1-Sessiounen",
-       "randomrootpage": "Zoufalls-Stammsäit"
+       "randomrootpage": "Zoufalls-Stammsäit",
+       "log-action-filter-block": "Typ vun der Spär:",
+       "log-action-filter-protect": "Typ vu Spär",
+       "log-action-filter-all": "All",
+       "log-action-filter-block-block": "Spären",
+       "log-action-filter-block-reblock": "Ännere vun enger Spär",
+       "log-action-filter-block-unblock": "Spär ophiewen",
+       "log-action-filter-delete-delete": "Säite läschen",
+       "log-action-filter-patrol-patrol": "Manuell Kontroll",
+       "log-action-filter-patrol-autopatrol": "Automatesch Kontroll",
+       "log-action-filter-protect-protect": "Spär",
+       "log-action-filter-protect-modify": "Spär-pÄnnerung",
+       "log-action-filter-upload-upload": "Neien Upload",
+       "log-action-filter-upload-overwrite": "Nees eroplueden"
 }
index 483b3a7..9ede18f 100644 (file)
@@ -11,7 +11,8 @@
                        "아라",
                        "V6rg",
                        "C.R.",
-                       "Macofe"
+                       "Macofe",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Sottolineâ i collegamenti",
        "recentchangeslinked-page": "Nómme da pàgina:",
        "recentchangeslinked-to": "Fanni védde sôlo i cangiaménti a-e pàgine colegæ a-a pàgina specificâ",
        "recentchanges-page-added-to-category": "[[:$1]] azonto a-a categoria",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] e {{PLURAL:$2|una paggina a l'è azonta|$2 paggine son azonte}} a-a categoria",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|una paggina a l'è azonta|$2 paggine son azonte}}]] a-a categoria",
        "recentchanges-page-removed-from-category": "[[:$1]] rimosso da-a categoria",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] e {{PLURAL:$2|una paggina a l'è rimossa|$2 paggine son rimosse}} da-a categoria",
        "autochange-username": "Modiffica aotomattica MediaWiki",
index 3026652..35c9724 100644 (file)
        "copyright": " محتوایۀل هانإ ژئرنظر اجازه‌نامهٔ $1 مۀگۀر یۀگإ خلاف یۀ بوشرئ/ذکر بو",
        "copyrightpage": "{{ns:project}}:حق تکثیر",
        "currentevents": "پێش هەتێەل ایسگە",
-       "currentevents-url": "Project:رویدادةل ایسة",
+       "currentevents-url": "پێش هەتێەل ایسگە(ایسە)",
        "disclaimers": "دروو نامه -تکذیب نامه",
        "disclaimerpage": "Project:تکذیب‌نامهٔ عمومی",
        "edithelp": "راهنمای دۀسکاری کردن",
index 1582bb3..3fd7e2f 100644 (file)
@@ -7,7 +7,8 @@
                        "Macofe",
                        "Mjbmr",
                        "Matma Rex",
-                       "Lakzon"
+                       "Lakzon",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "هوم پئیڤأند زیرخأط دار:",
        "protect-otherreason-op": "دألیل ھأنی",
        "protect-dropdown": "*دلیلیا جاافتائه سی پر و پیم کاری\n** خراوکاری گپ کلون\n** هرزه نیسی گپ کلون\n** جئن ویرایشتی وه درد نحور\n** بلگه فره تماشاکار دار",
        "protect-edit-reasonlist": "دلیلا پر و پیم بیین ویرایشت",
-       "protect-expiry-options": "۱ ساعأت:1 hour,۱ روٙز:1 day,۱ ھأفتە:1 week,۲ ھأفتە:2 weeks,۱ ما:1 month,۳ ما:3 months,۶ ما:6 months,۱ سال:1 year,بی حئسۉ:infinite",
+       "protect-expiry-options": "2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,indefinite:infinite",
        "restriction-type": "دسرسی:",
        "restriction-level": "ریتراز محدودیت:",
        "minimum-size": "انازه کمترونه",
        "ipbenableautoblock": "بستن خودانجوم آخری تیرنشون آی پی وه کار گرته بیه وه دس کاریار و تیرنشونیا هنی که که د ونو سی ویرایشت وه سعی می کن.",
        "ipbsubmit": "نهاگری ای کاریار",
        "ipbother": "وخت هنی:",
-       "ipboptions": "۱ ساعأت:1 hour,۱ روٙز:1 day,۱ ھأفتە:1 week,۲ ھأفتە:2 weeks,۱ ما:1 month,۳ ما:3 months,۶ ما:6 months,۱ سال:1 year,بی حئسۉ:infinite",
+       "ipboptions": "2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,indefinite:infinite",
        "ipbhidename": "نوم کاروری نه سی ویرایشت یا و نوم گه یا قام کو",
        "ipbwatchuser": "پی گری بلگه کاریاری و بلگه چک چنه ای کاریار",
        "ipb-disableusertalk": "نها ای کاریار نه اوسه که میها د بلگه چک چنه ش ویرایشت بکه و وه قلف بیه بئر",
index ad93163..c0b33b8 100644 (file)
@@ -34,7 +34,8 @@
                        "Albertas",
                        "Macofe",
                        "Zygimantus",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Nuorodos pabraukimas:",
        "botpasswords-insert-failed": "Nepavyko pridėti boto vardo \"$1\". Gal jis jau pridėtas?",
        "botpasswords-update-failed": "Nepavyko atnaujinti boto vardo \"$1\". Gal jis buvo ištrintas?",
        "botpasswords-created-title": "Boto slaptažodis sukurtas",
-       "botpasswords-created-body": "Boto slaptažodis \"$1\" buvo sukurtas sėkmingai.",
+       "botpasswords-created-body": "Naudotojo $2 boto „$1“ slaptažodis buvo sukurtas.",
        "botpasswords-updated-title": "Boto slaptažodis atnaujintas",
-       "botpasswords-updated-body": "Boto slaptažodis \"$1\" buvo atnaujintas sėkmingai.",
+       "botpasswords-updated-body": "Naudotojo $2 boto „$1“ slaptažodis buvo atnaujintas.",
        "botpasswords-deleted-title": "Boto slaptažodis ištrintas",
-       "botpasswords-deleted-body": "Boto slaptažodis \"$1\" buvo ištrintas.",
+       "botpasswords-deleted-body": "Naudotojo $2 boto „$1“ slaptažodis buvo ištrintas.",
        "botpasswords-newpassword": "Naujas slaptažodis prisijungimui su <strong>$1</strong> yra <strong>$2</strong>. <em>Prašome įsiminti jį naudojimui ateityje.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider nėra prieinamas.",
        "botpasswords-restriction-failed": "Boto slaptažodžio apribojimai draudžia šį prisijungimą.",
        "newarticle": "(Naujas)",
        "newarticletext": "Jūs patekote į dar neegzistuojantį puslapį.\nNorėdami sukurti puslapį, pradėkite rašyti žemiau esančiame įvedimo lauke\n(plačiau [$1 pagalbos puslapyje]).\nJei patekote čia per klaidą, paprasčiausiai spustelkite  naršyklės mygtuką '''atgal'''.",
        "anontalkpagetext": "----''Tai yra anoniminio naudotojo, nesusikūrusio arba nenaudojančio paskyros, aptarimų puslapis.\nDėl to naudojamas IP adresas jo identifikavimui.\nŠis IP adresas gali būti dalinamas keliems naudotojams.\nJeigu Jūs esate anoniminis naudotojas ir atrodo, kad komentarai nėra skirti Jums, [[Special:UserLogin/signup|sukurkite paskyrą]] arba [[Special:UserLogin|prisijunkite]], ir nebūsite tapatinamas su kitais anoniminiais naudotojais.''",
-       "noarticletext": "Šiuo metu šiame puslapyje nėra jokio teksto.\nJūs galite [[Special:Search/{{PAGENAME}}|ieškoti šio puslapio pavadinimo]] kituose puslapiuose,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ieškoti susijusių įrašų],\narba [{{fullurl:{{FULLPAGENAME}}|action=edit}} redaguoti šį puslapį]</span>.",
+       "noarticletext": "Šiuo metu šiame puslapyje nėra jokio teksto.\nJūs galite [[Special:Search/{{PAGENAME}}|ieškoti šio puslapio pavadinimo]] kituose puslapiuose,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ieškoti susijusių įrašų] arba [{{fullurl:{{FULLPAGENAME}}|action=edit}} sukurti šį puslapį]</span>.",
        "noarticletext-nopermission": "Šiuo metu šiame puslapyje nėra jokio teksto.\nJūs galite [[Special:Search/{{PAGENAME}}|ieškoti šio puslapio pavadinimo]] kituose puslapiuose,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ieškoti susijusių įrašų]</span>, bet jūs neturite teisės sukurti šį puslapį.",
        "missing-revision": "Puslapio peržiūra #$1 pavadinto „{{FULLPAGENAME}}“ neegzistuoja.\n\nTai paprastai atsitinka kai pasenusi nuoroda veda į puslapį, kuris buvo ištrintas.\nInformaciją galima rasti [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
        "userpage-userdoesnotexist": "Naudotojo paskyra „<nowiki>$1</nowiki>“ yra neužregistruota. Prašom patikrinti, ar jūs norite kurti/redaguoti šį puslapį.",
        "recentchangeslinked-page": "Puslapio pavadinimas:",
        "recentchangeslinked-to": "Rodyti su duotuoju puslapiu susijusių puslapių pakeitimus",
        "recentchanges-page-added-to-category": "[[:$1]] pridėta prie kategorijos",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] ir {{PLURAL:$2|vienas puslapis|$2 puslapiai}} pridėti prie kategorijos",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] ir [[Special:WhatLinksHere/$1|{{PLURAL:$2|vienas puslapis|$2 puslapiai}}]] pridėti prie kategorijos",
        "recentchanges-page-removed-from-category": "[[:$1]] pašalinta iš kategorijos",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] ir {{PLURAL:$2|vienas puslapis|$2 puslapiai}} pašalinti iš kategorijos",
        "autochange-username": "MediaWiki automatinis pakeitimas",
        "uploadstash-badtoken": "Scenos šį ieškinį, buvo nesėkmingas, galbūt todėl, kad jūsų redagavimo įgaliojimai pasibaigė. Bandykite dar kartą.",
        "uploadstash-errclear": "Kliringo failai buvo nesėkmingas.",
        "uploadstash-refresh": "Atnaujinti failų sąrašą",
+       "uploadstash-thumbnail": "rodyti miniatiūrą",
        "invalid-chunk-offset": "Neleistinas segmento poslinkis",
        "img-auth-accessdenied": "Prieiga uždrausta",
        "img-auth-nopathinfo": "Trūksta PATH_INFO.\nJūsų serveris nenustatytas perduoti šią informaciją.\nTai gali būti CGI paremta ir negali palaikyti img_auth.\nDaugiau informacijos https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization. žr.",
        "changecontentmodel-title-label": "Puslapio pavadinimas",
        "changecontentmodel-model-label": "Naujas turinio modelis",
        "changecontentmodel-reason-label": "Priežastis:",
+       "changecontentmodel-submit": "Keisti",
        "changecontentmodel-success-title": "Turinio modelis buvo atnaujintas",
        "changecontentmodel-success-text": "Turinys, kurio tipas [[:$1]], buvo atnaujintas.",
        "changecontentmodel-cannot-convert": "Turinys [[:$1]] negali būti konvertuotas į $2 tipą.",
index 7437611..c6ee2aa 100644 (file)
@@ -30,6 +30,7 @@
        "tog-hideminor": "Paslēpt maznozīmīgus labojumus pēdējo izmaiņu lapā",
        "tog-hidepatrolled": "Slēpt apstiprinātās izmaņas pēdējo izmaiņu sarakstā",
        "tog-newpageshidepatrolled": "Paslēpt pārbaudītās lapas jauno lapu sarakstā",
+       "tog-hidecategorization": "Paslēpt lapu kategorizēšanu",
        "tog-extendwatchlist": "Izvērst uzraugāmo lapu sarakstu, lai parādītu visas veiktās izmaiņas (ne tikai pašas svaigākās)",
        "tog-usenewrc": "Grupēt izmaiņas pēc lapas pēdējās izmaiņās un uzraugāmo lapu sarakstā",
        "tog-numberheadings": "Automātiski numurēt virsrakstus",
@@ -59,6 +60,7 @@
        "tog-watchlisthideliu": "Paslēpt reģistrēto dalībnieku labojumus uzraugāmo lapu sarakstā",
        "tog-watchlisthideanons": "Paslēpt anonīmo dalībnieku labojumus uzraugāmo lapu sarakstā",
        "tog-watchlisthidepatrolled": "Paslēpt pārbaudītās lapas uzraugāmo lapu sarakstā",
+       "tog-watchlisthidecategorization": "Paslēpt lapu kategorizēšanu",
        "tog-ccmeonemails": "Sūtīt sev citiem dalībniekiem nosūtīto epastu kopijas",
        "tog-diffonly": "Nerādīt lapu saturu zem izmaiņām",
        "tog-showhiddencats": "Rādīt slēptās kategorijas",
        "logout": "Iziet",
        "userlogout": "Iziet",
        "notloggedin": "Neesi iegājis",
+       "userlogin-noaccount": "Nav dalībnieka konta?",
        "userlogin-joinproject": "Pievienojieties {{SITENAME}}",
        "nologin": "Nav lietotājvārda? $1.",
        "nologinlink": "Reģistrējies",
        "sessionfailure-title": "sesijas kļūda",
        "sessionfailure": "Ir radusies problēma ar sesijas autentifikāciju;\nšī darbība ir atcelta, lai novērstu lietotājvārda iespējami ļaunprātīgu izmantošanu.\nLūdzu, spied \"''back''\" un atjaunini iepriekšējo lapu. Tad mēģini vēlreiz.",
        "changecontentmodel-reason-label": "Iemesls:",
+       "changecontentmodel-submit": "Mainīt",
        "protectlogpage": "Aizsargāšanas reģistrs",
        "protectedarticle": "aizsargāja \"[[$1]]\"",
        "modifiedarticleprotection": "izmainīja aizsardzības līmeni \"[[$1]]\"",
index 08b5740..f1a6561 100644 (file)
@@ -19,7 +19,8 @@
                        "Davidzdh",
                        "Nemo bis",
                        "飞舞回堂前",
-                       "Macofe"
+                       "Macofe",
+                       "Bowleerin"
                ]
        },
        "tog-underline": "鏈墊線:",
        "october-date": "十月$1日",
        "november-date": "十一月$1日",
        "december-date": "十二月$1日",
+       "period-am": "晨",
+       "period-pm": "午後",
        "pagecategories": "$1類",
        "category_header": "「$1」中之頁",
        "subcategories": "次類",
        "morenotlisted": "列未成。",
        "mypage": "寒舍",
        "mytalk": "書房",
-       "anontalk": "è\88\87ï¼\88IPï¼\89ç§\81è­°",
+       "anontalk": "議",
        "navigation": "導",
        "and": "與",
        "qbfind": "尋",
        "disclaimers": "免責宣",
        "disclaimerpage": "Project:免責宣",
        "edithelp": "助纂塾",
+       "helppage-top-gethelp": "助",
        "mainpage": "卷首",
        "mainpage-description": "卷首",
        "policy-url": "Project:策",
        "gotaccount": "已有簿矣?惠往$1。",
        "gotaccountlink": "登簿",
        "userlogin-resetlink": "汝忘登簿所需?",
-       "userlogin-resetpassword-link": "輸子符節",
+       "userlogin-resetpassword-link": "亡子符節?",
        "userlogin-helplink2": "助以登簿",
+       "userlogin-createanother": "增另一簿",
        "createacct-emailrequired": "電郵",
        "createacct-emailoptional": "電郵(可選)",
+       "createacct-email-ph": "書君郵址",
        "createaccountmail": "同郵",
        "createacct-realname": "實名(可選)",
        "createaccountreason": "因:",
        "createacct-reason": "因:",
        "createacct-reason-ph": "汝另立一簿者何哉?",
        "createacct-submit": "增簿",
-       "createacct-another-submit": "復ç«\8bä¸\80簿",
+       "createacct-another-submit": "å¢\9e簿",
        "createacct-benefit-heading": "吾等立{{SITENAME}}者,或黔首,或專戶。",
        "createacct-benefit-body1": "纂",
        "createacct-benefit-body2": "頁",
        "noname": "缺簿名,或不格也。",
        "loginsuccesstitle": "登簿成矣",
        "loginsuccess": "'''$1'''登{{SITENAME}}矣",
-       "nosuchuser": "查無此人。惠請更名,查大小寫或立此簿。",
+       "nosuchuser": "查無此人。惠請更名,查大小寫或[[Special:UserLogin/signup|立此簿]]。",
        "nosuchusershort": "查無\"$1\",惠核之。",
        "nouserspecified": "簿名必須",
        "login-userblocked": "此簿見錮矣。是之登未見許可。",
        "resetpass_submit": "設符再登",
        "changepassword-success": "汝之符節已改!",
        "changepassword-throttled": "爾嘗登簿甚矣。\n請候 $1 再試之。",
+       "botpasswords": "僕之符節",
+       "botpasswords-label-appid": "僕名:",
+       "botpasswords-label-create": "立",
+       "botpasswords-label-update": "更",
+       "botpasswords-label-cancel": "棄",
+       "botpasswords-label-delete": "刪",
+       "botpasswords-label-resetpassword": "重設符節",
+       "botpasswords-deleted-title": "僕之符節已刪",
+       "botpasswords-deleted-body": "\"$2\"所執之僕\"$1\"之符節已刪也。",
        "resetpass_forbidden": "符節之更也不可。",
        "resetpass-no-info": "欲入此頁,爾須登簿。",
        "resetpass-submit-loggedin": "改符節",
        "resetpass-submit-cancel": "消",
        "resetpass-wrong-oldpass": "無效之臨符或現符。\n爾或改符,或求新臨符。",
+       "resetpass-recycled": "請君更至與原符節相異之符節。",
        "resetpass-temp-password": "臨時符節:",
        "resetpass-abort-generic": "符節不可更",
        "passwordreset": "重設符節",
        "passwordreset-username": "簿名:",
        "passwordreset-domain": "域:",
        "passwordreset-email": "電郵址",
-       "changeemail": "更郵址",
+       "changeemail": "更或刪郵址",
        "changeemail-oldemail": "當前郵驛:",
        "changeemail-newemail": "添新郵驛:",
        "changeemail-none": "(無)",
        "changeemail-password": "汝 {{SITENAME}} 之符節",
+       "changeemail-submit": "更郵址",
        "changeemail-throttled": "汝嘗登簿甚矣。\n請候 $1 而試之。",
        "bold_sample": "粗體",
        "bold_tip": "粗體",
        "edit-gone-missing": "無更頁。\n刪之也。",
        "edit-conflict": "纂突。",
        "edit-no-change": "爾之纂已略,由字無改也。",
+       "postedit-confirmation-created": "其頁已建。",
        "postedit-confirmation-saved": "汝之纂已成",
        "edit-already-exists": "不建新頁。\n已存也。",
        "defaultmessagetext": "慣話文",
        "revdelete-confirm": "爾確作之,解之果焉,合之[[{{MediaWiki:Policy-url}}|策]]矣。",
        "revdelete-suppress-text": "'''限'''於此壓:\n* 無適之個訊\n*: ''地、號、保等之。''",
        "revdelete-legend": "見,規之以",
-       "revdelete-hide-text": "審文",
+       "revdelete-hide-text": "審文",
        "revdelete-hide-image": "藏檔容",
-       "revdelete-hide-comment": "摘",
+       "revdelete-hide-comment": "摘",
        "revdelete-hide-user": "簿、IP址以藏",
        "revdelete-hide-restricted": "廢有秩與簿之事",
        "revdelete-radio-same": "(無改)",
        "compareselectedversions": "辨二擇",
        "showhideselectedversions": "示/藏之擇",
        "editundo": "悔",
+       "diff-empty": "(無異)",
        "diff-multi-manyusers": "($2多作未示之審有$1)",
        "searchresults": "得尋",
        "searchresults-title": "\"$1\"得尋",
        "notextmatches": "無文合",
        "prevn": "前{{PLURAL:$1|$1}}",
        "nextn": "次{{PLURAL:$1|$1}}",
+       "prev-page": "前頁",
+       "next-page": "次頁",
        "prevn-title": "前$1之尋",
        "nextn-title": "後$1之尋",
        "shown-title": "每頁示 $1",
        "prefs-personal": "概簿",
        "prefs-rc": "近易",
        "prefs-watchlist": "哨站",
+       "prefs-editwatchlist": "治哨站",
+       "prefs-editwatchlist-clear": "清哨站",
        "prefs-watchlist-days": "哨報有日",
        "prefs-watchlist-days-max": "Maximum $1 {{PLURAL:$1|day|days}}",
        "prefs-watchlist-edits": "哨站有易",
        "prefs-misc": "雜",
        "prefs-resetpass": "更符節",
        "prefs-changeemail": "更郵址",
+       "prefs-setemail": "設電郵址",
        "prefs-email": "傳書",
        "prefs-rendering": "觀",
        "saveprefs": "儲",
        "columns": "列數:",
        "searchresultshead": "尋",
        "stub-threshold": "<a href=\"#\" class=\"stub\">短頁連</a>格式門檻(位元組):",
+       "stub-threshold-sample-link": "例",
        "stub-threshold-disabled": "禁",
        "recentchangesdays": "近易示日:",
        "recentchangesdays-max": "最大有$1",
        "right-siteadmin": "鎖與解鎖資料庫",
        "right-override-export-depth": "出有五層深之頁",
        "right-sendemail": "擬書傳予他簿",
+       "grant-group-email": "遞電郵",
+       "grant-createaccount": "立簿",
+       "grant-editmywatchlist": "纂哨站",
+       "grant-viewmywatchlist": "閱哨站",
        "newuserlogpage": "誌簿",
        "newuserlogpagetext": "此為誌簿之記也",
        "rightslog": "職權志",
        "action-userrights": "纂全權",
        "action-userrights-interwiki": "纂他wiki上之權",
        "action-siteadmin": "鎖及解鎖其庫",
+       "action-editmywatchlist": "纂爾哨站",
+       "action-viewmywatchlist": "閱爾哨站",
        "nchanges": "$1易",
        "enhancedrc-since-last-visit": "$1未示",
        "enhancedrc-history": "誌",
        "recentchanges-label-bot": "此乃機纂",
        "recentchanges-label-unpatrolled": "是纂未巡",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}([[Special:NewPages|新灶]])",
+       "recentchanges-submit": "示",
        "rcnotefrom": "下為自'''$2'''至'''$1'''之易也。",
        "rclistfrom": "自$3 $2起之易也",
        "rcshowhideminor": "$1校",
        "upload-proto-error": "協訂錯誤",
        "upload-too-many-redirects": "網址含多轉",
        "upload-http-error": "發一HTTP之錯:$1",
+       "upload-dialog-button-cancel": "捨",
+       "upload-dialog-button-done": "成",
+       "upload-dialog-button-save": "存",
+       "upload-dialog-button-upload": "貢",
+       "upload-form-label-infoform-title": "細事",
+       "upload-form-label-infoform-name": "名",
+       "upload-form-label-infoform-description": "述",
        "backend-fail-notexists": "無檔 $1 。",
        "backend-fail-alreadyexists": "$1 已含。",
        "backend-fail-read": "\"$1\"不可見。",
index b2b5974..dbcd528 100644 (file)
                        "Macofe"
                ]
        },
-       "tog-underline": "लिंककेँ रेखांकित करू:",
-       "tog-hideminor": "सन्निकट परिवर्त्तनमे छोट परिवर्त्तन नुकाऊ",
-       "tog-hidepatrolled": "सन्निकट परिवर्त्तनमे छोट परिवर्त्तन नुकाऊ",
-       "tog-newpageshidepatrolled": "नियंत्रित सम्पादनकेँ नव पन्ना सूचीसँ नुकाऊ",
-       "tog-extendwatchlist": "सन्निकट परिवर्तन नै,अखन ध्यानसूचीमे रहल सभ परिवर्तन देखाऊ",
-       "tog-usenewrc": "नीक सन्निकट परिवर्तन प्रयोग करू (जावास्क्रिप्ट चाही)",
-       "tog-numberheadings": "शीर्षक स्वयं-क्रमांकित करू",
-       "tog-showtoolbar": "संपादन ओजारपेटी देखाऊ (जावास्क्रीप्ट)",
-       "tog-editondblclick": "दू बेर क्लीक कए पन्ना संपादित करू (जावास्क्रीप्ट)",
-       "tog-editsectiononrightclick": "ऐ खण्डक सम्पादन खण्डक शीर्षकेँ दहिन क्लिक कऽ सम्भव (जावास्क्रिप्ट चाही)",
-       "tog-watchcreations": "हमर बनाओल पृष्ठ हमर साकांक्ष सूचीमे राखू",
-       "tog-watchdefault": "हमर संपादित पृष्ठ हमर साकांक्ष सूचीमे देखाऊ",
-       "tog-watchmoves": "हमरा द्वारा हटाओल पृष्ठ हमर साकांक्ष सूचीमे राखू",
-       "tog-watchdeletion": "हमरा द्वारा हटाओल पृष्ठ हमर साकांक्ष सूचीमे राखू",
-       "tog-watchrollback": "हमरा द्वारा जोडलगेल पृष्ठ हमार सांकक्ष सूचीमे राखू",
-       "tog-minordefault": "हमर सभ सम्पादन पूर्वन्यस्त रूपेँ मामूली कहू",
-       "tog-previewontop": "संपादन पेटीक ऊपर दृश्य देखाऊ",
-       "tog-previewonfirst": "पहिल संपादनक बाद पूर्वावलोकन देखाउ",
-       "tog-enotifwatchlistpages": "जौं हमर ध्यानसूचीक कोनो पन्नामे परिवर्तन हुअए तँ हमरा ई-पत्र पठाउ",
-       "tog-enotifusertalkpages": "हमर सदस्य वार्ता पृष्ठ पर भेल परिवर्त्तनक हेतु हमरा ई-मेल करथि",
-       "tog-enotifminoredits": "छोट परिवर्त्तनक हेतु सेहो हमरा ई-मेल पठाऊ",
-       "tog-enotifrevealaddr": "हमर ई-पत्र संकेत सूचना ई-पत्रमे देखाउ",
-       "tog-shownumberswatching": "ध्यान राखैबला प्रयोक्ताक संख्या",
+       "tog-underline": "लिङ्कके रेखाङ्कित करी:",
+       "tog-hideminor": "सन्निकट परिवर्तनमे छोट परिवर्तन नुकाबी",
+       "tog-hidepatrolled": "सन्निकट परिवर्तनमे नियन्त्रित कएल सम्पादन नुकाबी",
+       "tog-newpageshidepatrolled": "नियन्त्रित सम्पादनक नव पन्ना सूचीसँ नुकाबी",
+       "tog-hidecategorization": "पृष्ठसभक श्रेणीकरण हटाबी",
+       "tog-extendwatchlist": "सन्निकट परिवर्तन नै,अखन ध्यानसूचीमे रहल सभ परिवर्तन देखाबी",
+       "tog-usenewrc": "नीक सन्निकट परिवर्तन प्रयोग करी (जावास्क्रिप्ट चाही)",
+       "tog-numberheadings": "शीर्षक स्वयं-क्रमाङ्कित करी",
+       "tog-showtoolbar": "सम्पादन ओजारपेटी देखाबी",
+       "tog-editondblclick": "दू बेर क्लीक कए पन्ना सम्पादित करी",
+       "tog-editsectiononrightclick": "अनुभाग शीर्षक पर दाहिन क्लिक करै पर अनुभाग सम्पादित करी",
+       "tog-watchcreations": "हमर बनाओल पृष्ठ हमर साकांक्ष सूचीमे राखी",
+       "tog-watchdefault": "हमर सम्पादित पृष्ठ हमर साकांक्ष सूचीमे देखाबी",
+       "tog-watchmoves": "हमराद्वारा घस्काओल पृष्ठ हमर साकांक्ष सूचीमे राखी",
+       "tog-watchdeletion": "हमराद्वारा मेटाओल पृष्ठ हमर साकांक्ष सूचीमे राखी",
+       "tog-watchrollback": "हमराद्वारा रोलब्याक कएल पृष्ठ हमर सांकक्ष सूचीमे राखी",
+       "tog-minordefault": "हमर सभ सम्पादन पूर्वन्यस्त रूपमे मामूली कही",
+       "tog-previewontop": "सम्पादन पेटीक ऊपर दृश्य देखाबी",
+       "tog-previewonfirst": "पहिल सम्पादनक बाद पूर्वावलोकन देखाबी",
+       "tog-enotifwatchlistpages": "जौं हमर ध्यानसूचीक कोनो पन्नामे परिवर्तन हुअए तँ हमरा इमेल पठाबी",
+       "tog-enotifusertalkpages": "हमर वार्ता पृष्ठ परिवर्तित भेला पर हमरा इमेल करी",
+       "tog-enotifminoredits": "छोट परिवर्तनक हेतु सेहो हमरा इमेल भेजी",
+       "tog-enotifrevealaddr": "अधिसूचना इमेलमे हमर इमेल पता देखाबी",
+       "tog-shownumberswatching": "ध्यान राखैबला प्रयोगकर्ताक सङ्ख्या",
        "tog-oldsig": "अखुनका दस्खत:",
-       "tog-fancysig": "दस्खतकें विकिटेक्सटक रूपमे देखू (स्वचालित श्रृंखला हीन)",
+       "tog-fancysig": "दस्खतक विकिटेक्सटक समान मानी (स्वचालित श्रृङ्खला हीन)",
        "tog-uselivepreview": "पूर्वावलोकनके उपयोग करी",
-       "tog-forceeditsummary": "हमरा à¤¸à¤\9aà¥\87त à¤\95रà¥\82 à¤\9cà¤\96न à¤¹à¤® à¤\96ालà¥\80 à¤¸à¤®à¥\8dपादम à¤¸à¤¾à¤°à¤¾à¤\82शमà¥\87 à¤\9cाà¤\87",
-       "tog-watchlisthideown": "हमर à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤¹à¤®à¤° à¤¸à¤®à¥\8dपादन à¤¨à¥\81à¤\95ाà¤\89",
-       "tog-watchlisthidebots": "हमर à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤¸à¥\8dवà¤\9aालित à¤¸à¤®à¥\8dपादन à¤¹à¤\9fाà¤\89",
-       "tog-watchlisthideminor": "हमर à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤®à¤¾à¤®à¥\82लà¥\80 à¤¸à¤®à¥\8dपादन à¤¨à¥\81à¤\95ाà¤\89",
-       "tog-watchlisthideliu": "साà¤\95ाà¤\82à¤\95à¥\8dषसà¥\82à¤\9aà¥\80सà¤\81 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87शित à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dताà¤\95 à¤¸à¤®à¥\8dपादन à¤¹à¤\9fाà¤\89",
-       "tog-watchlisthideanons": "साà¤\95ाà¤\82à¤\95à¥\8dषसà¥\82à¤\9aà¥\80सà¤\81 à¤\85नाम à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dताà¤\95 à¤¸à¤®à¥\8dपादन à¤¹à¤\9fाà¤\89",
-       "tog-watchlisthidepatrolled": "साà¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤¸à¤\82à¤\9aालित à¤¸à¤®à¥\8dपादन à¤¨à¥\81à¤\95ाà¤\89",
-       "tog-ccmeonemails": "हमरा à¤¦à¥\8dवारा à¤¦à¥\8bसर à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dताà¤\95à¥\87à¤\81 à¤ªà¤ à¤¾à¤\93ल à¤\88-पतà¥\8dरà¤\95 à¤\95à¥\89पà¥\80 à¤ªà¤ à¤¾à¤\89",
-       "tog-diffonly": "फाà¤\87ल-à¤\85नà¥\8dतर à¤ªà¥\8dरणालà¥\80à¤\95 à¤¨à¥\80à¤\9aाà¤\81 à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¤¾à¤®à¤¿à¤\97à¥\8dरà¥\80 à¤¨à¥\88 à¤¦à¥\87à¤\96ाà¤\89",
-       "tog-showhiddencats": "नà¥\81à¤\95ाà¤\8fल à¤¸à¤\82वरà¥\8dà¤\97 à¤¦à¥\87à¤\96ाà¤\89",
-       "tog-norollbackdiff": "प्रत्यावर्तनक बाद फाइल-अन्तर प्रणालीकेँ बिसरू",
-       "tog-useeditwarning": "à¤\9cब à¤¹à¤® à¤\95à¥\8bनà¥\8b à¤¸à¤\82पादन à¤ªà¥\83षà¥\8dठà¤\95à¥\87 à¤¬à¤¿à¤¨à¤¾ à¤¸à¥\81रà¤\95à¥\8dषित à¤\95à¥\87नà¥\88 à¤¬à¤¦à¤²à¤¾à¤µ à¤¸à¤\82à¤\97 à¤\9bà¥\8bà¤\87ड à¤¦à¤¿ à¤¤ à¤¹à¤®à¤°à¤¾ à¤¸à¥\82à¤\9aित à¤\95रà¥\81 ।",
-       "tog-prefershttps": "समà¥\8dपà¥\8dरवà¥\87शित à¤\95रलाà¤\95 à¤¬à¤¾à¤¦ à¤¸à¤¦à¥\88व à¤¸à¥\81रà¤\95à¥\8dषित à¤\95नà¥\87à¤\95à¥\8dशनà¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\81",
+       "tog-forceeditsummary": "यदि à¤¸à¤®à¥\8dपादन à¤¸à¤¾à¤°à¤¾à¤\82श à¤¨à¥\88 à¤¦à¥\87ल à¤\97à¥\87ल à¤¹à¥\8bà¤\8f à¤¤à¤¹à¤¨ à¤¹à¤®à¤°à¤¾ à¤¸à¥\82à¤\9aित à¤\95रà¥\80",
+       "tog-watchlisthideown": "हमर à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤¹à¤®à¤° à¤¸à¤®à¥\8dपादन à¤¨à¥\81à¤\95ाबà¥\80",
+       "tog-watchlisthidebots": "हमर à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤¸à¥\8dवà¤\9aालित à¤¸à¤®à¥\8dपादन à¤¹à¤\9fाबà¥\80",
+       "tog-watchlisthideminor": "हमर à¤¸à¤¾à¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤®à¤¾à¤®à¥\82लà¥\80 à¤¸à¤®à¥\8dपादन à¤¨à¥\81à¤\95ाबà¥\80",
+       "tog-watchlisthideliu": "साà¤\95ाà¤\82à¤\95à¥\8dषसà¥\82à¤\9aà¥\80सà¤\81 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87शित à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dताà¤\95 à¤¸à¤®à¥\8dपादन à¤¹à¤\9fाबà¥\80",
+       "tog-watchlisthideanons": "साà¤\95ाà¤\82à¤\95à¥\8dषसà¥\82à¤\9aà¥\80सà¤\81 à¤\85नाम à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dताà¤\95 à¤¸à¤®à¥\8dपादन à¤¹à¤\9fाबà¥\80",
+       "tog-watchlisthidepatrolled": "साà¤\95ाà¤\82à¤\95à¥\8dष à¤¸à¥\82à¤\9aà¥\80सà¤\81 à¤¸à¤\82à¤\9aालित à¤¸à¤®à¥\8dपादन à¤¨à¥\81à¤\95ाबà¥\80",
+       "tog-ccmeonemails": "हमरदà¥\8dवारा à¤¦à¥\8bसर à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dताà¤\95 à¤ªà¤ à¤¾à¤\93ल à¤\88-पतà¥\8dरà¤\95 à¤\95पà¥\80 à¤ªà¤ à¤¾à¤¬à¥\80",
+       "tog-diffonly": "फाà¤\87ल-à¤\85नà¥\8dतर à¤ªà¥\8dरणालà¥\80à¤\95 à¤¨à¥\80à¤\9aाà¤\81 à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¤¾à¤®à¤¿à¤\97à¥\8dरà¥\80 à¤¨à¥\88 à¤¦à¥\87à¤\96ाबà¥\80",
+       "tog-showhiddencats": "नà¥\81à¤\95ाà¤\8fल à¤¶à¥\8dरà¥\87णà¥\80 à¤¦à¥\87à¤\96ाबà¥\80",
+       "tog-norollbackdiff": "प्रत्यावर्तनक बाद फाइल-अन्तर प्रणालीक बिसरी",
+       "tog-useeditwarning": "à¤\9cब à¤¹à¤® à¤\95à¥\8bनà¥\8b à¤¸à¤®à¥\8dपादन à¤ªà¥\83षà¥\8dठà¤\95à¥\87 à¤¬à¤¿à¤¨à¤¾ à¤¸à¥\81रà¤\95à¥\8dषित à¤\95à¥\87नà¥\88 à¤¬à¤¦à¤²à¤¾à¤µ à¤¸à¤\82à¤\97 à¤\9bà¥\8bडि à¤¦à¤¿ à¤¤ à¤¹à¤®à¤°à¤¾ à¤¸à¥\82à¤\9aित à¤\95रà¥\80 ।",
+       "tog-prefershttps": "समà¥\8dपà¥\8dरवà¥\87शित à¤\95रलाà¤\95 à¤¬à¤¾à¤¦ à¤¸à¤¦à¥\88व à¤¸à¥\81रà¤\95à¥\8dषित à¤\95नà¥\87à¤\95à¥\8dशनà¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\80",
        "underline-always": "सदिखन",
        "underline-never": "कखनो नै",
        "underline-default": "पूर्वन्यस्त गवेषक",
        "march-gen": "मार्च",
        "april-gen": "अप्रैल",
        "may-gen": "मई",
-       "june-gen": "à¤\9cà¥\82न",
+       "june-gen": "à¤\9cà¥\81न",
        "july-gen": "जुलाई",
        "august-gen": "अगस्त",
-       "september-gen": "सितà¤\82बर",
-       "october-gen": "à¤\85à¤\95à¤\9fà¥\82बर",
-       "november-gen": "नवà¤\82बर",
-       "december-gen": "दिसà¤\82बर",
+       "september-gen": "सितमà¥\8dबर",
+       "october-gen": "à¤\85à¤\95à¤\9fà¥\81बर",
+       "november-gen": "नवमà¥\8dबर",
+       "december-gen": "दिसमà¥\8dबर",
        "jan": "जन.",
        "feb": "फर.",
        "mar": "मा.",
        "march-date": "मार्च $1",
        "april-date": "अप्रैल $1",
        "may-date": "मई $1",
-       "june-date": "à¤\9cà¥\82न $1",
+       "june-date": "à¤\9cà¥\81न $1",
        "july-date": "जुलाई $1",
        "august-date": "अगस्त $1",
        "september-date": "सितम्बर $1",
-       "october-date": "à¤\85à¤\95à¥\8dà¤\9fà¥\82बर $1",
+       "october-date": "à¤\85à¤\95à¥\8dà¤\9fà¥\81बर $1",
        "november-date": "नवम्बर $1",
        "december-date": "दिसम्बर $1",
+       "period-am": "पूर्वाह्न",
+       "period-pm": "अपराह्न",
        "pagecategories": "{{PLURAL:$1|श्रेणी|कएटा श्रेणी}}",
-       "category_header": "सà¤\82वरà¥\8dà¤\97 \"$1\" मे पन्ना सभ",
-       "subcategories": "à¤\89पसà¤\82वरà¥\8dà¤\97",
-       "category-media-header": "सà¤\82वरà¥\8dà¤\97 \"$1\" मे मीडिया",
-       "category-empty": "''ऐ संवर्गमे अखन कोनो पन्ना वा मीडिया नै अछि।''",
-       "hidden-categories": "{{PLURAL:$1|नà¥\81à¤\95ाà¤\8fल à¤µà¤°à¥\8dà¤\97|नà¥\81à¤\95ाà¤\8fल à¤µà¤°à¥\8dà¤\97सभ}}",
-       "hidden-category-category": "नà¥\81à¤\95ाà¤\8fल à¤¸à¤\82वरà¥\8dà¤\97 सभ",
-       "category-subcat-count": "{{PLURAL:$2| ऐ संवर्गक खाली ई सभ उप संवर्ग अछिइ।.|ऐ संवर्गमे ई सभ {{PLURAL:$1| उपसंवर्ग|$1 उपसंवर्ग सभ}}, ऐमे सँ $2 सभटा।}}",
-       "category-subcat-count-limited": "à¤\90 à¤¸à¤\82वरà¥\8dà¤\97मà¥\87 à¤\85à¤\9bि {{PLURAL:$1|à¤\89पसà¤\82वरà¥\8dà¤\97|$1à¤\89पसà¤\82वरà¥\8dà¤\97 à¤¸à¤­}}",
-       "category-article-count": "{{PLURAL:$2|à¤\90 à¤¸à¤\82वरà¥\8dà¤\97मà¥\87 à¤\96ालà¥\80 à¤\88 à¤ªà¤¨à¥\8dना à¤\85à¤\9bि।| à¤\88 {{PLURAL:$1|पनà¥\8dना à¤\85à¤\9bि|$1 à¤ªà¤¨à¥\8dना à¤¸à¤­ à¤\85à¤\9bि}} à¤\90 à¤¸à¤\82वरà¥\8dà¤\97मà¥\87, à¤\9cाà¤\87मà¥\87 à¤¸à¤\81 $2 à¤¸à¤­à¥¤}}",
-       "category-article-count-limited": "à¤\88 {{PLURAL:$1|पनà¥\8dना à¤\85à¤\9bि|$1 à¤ªà¤¨à¥\8dना à¤¸à¤­ à¤\85à¤\9bि}}",
-       "category-file-count": "{{PLURAL:$2| ऐ संवर्गमे मातर ई फाइल अछि।| ई {{PLURAL:$1|फाइल अछि|$1 फाइल सभ अछि}} ऐ संवर्गमे, कुल $2 सँ।}}",
-       "category-file-count-limited": "ई {{PLURAL:$1|पन्ना अछि|$1 पन्ना सभ अछि}} ऐ संवर्गमे।",
+       "category_header": "शà¥\8dरà¥\87णà¥\80 \"$1\" मे पन्ना सभ",
+       "subcategories": "à¤\89पशà¥\8dरà¥\87णà¥\80",
+       "category-media-header": "शà¥\8dरà¥\87णà¥\80 \"$1\" मे मीडिया",
+       "category-empty": "<em>ई श्रेणीमे ई समय कोनो पृष्ठ या मिडिया नै अछि।</em>",
+       "hidden-categories": "{{PLURAL:$1|नà¥\81à¤\95ाà¤\8fल à¤¶à¥\8dरà¥\87णà¥\80|नà¥\81à¤\95ाà¤\8fल à¤¶à¥\8dरà¥\87णà¥\80सभ}}",
+       "hidden-category-category": "नà¥\81à¤\95ाà¤\8fल à¤¶à¥\8dरà¥\87णà¥\80सभ",
+       "category-subcat-count": "{{PLURAL:$2|ई श्रेणीमे मात्र निम्नलिखित उपश्रेणी अछि।|ई श्रेणीक कुल $2 मेसँ {{PLURAL:$1|उपश्रेणी निम्नलिखित अछि।|$1 उपश्रेणीसभ निम्नलिखित अछि।}}}}",
+       "category-subcat-count-limited": "à¤\88 à¤¶à¥\8dरà¥\87णà¥\80मà¥\87 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित {{PLURAL:$1|à¤\89पशà¥\8dरà¥\87णà¥\80 à¤\85à¤\9bि|$1 à¤\89पशà¥\8dरà¥\87णà¥\80 à¤\85à¤\9bि}}।",
+       "category-article-count": "{{PLURAL:$2|à¤\88 à¤¶à¥\8dरà¥\87णà¥\80मà¥\87 à¤®à¤¾à¤¤à¥\8dर à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित à¤ªà¥\83षà¥\8dठ à¤\85à¤\9bि।|à¤\88 à¤¶à¥\8dरà¥\87णà¥\80मà¥\87 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित {{PLURAL:$1|पà¥\83षà¥\8dठ à¤\85à¤\9bि|$1 à¤ªà¥\83षà¥\8dठ à¤\85à¤\9bि}}, à¤\95à¥\81ल à¤ªà¥\83षà¥\8dठ $2}}",
+       "category-article-count-limited": "निमà¥\8dनलिà¤\96ित {{PLURAL:$1|पà¥\83षà¥\8dठ|$1 à¤ªà¥\83षà¥\8dठ}} à¤\88 à¤¶à¥\8dरà¥\87णà¥\80मà¥\87 à¤\85à¤\9bि।",
+       "category-file-count": "{{PLURAL:$2|ई श्रेणीमे मात्र निम्नलिखित फाइल अछि।|ई श्रेणीमे निम्नलिखित {{PLURAL:$1|फाइल|$1 फाइलसभ}} अछि, कुल फाइलसभ $2}}",
+       "category-file-count-limited": "ई श्रेणीमे निम्नलिखित {{PLURAL:$1|फाइल अछि।|फाइलसभ अछि।}}",
        "listingcontinuesabbrev": "शेष आगाँ।",
        "index-category": "क्रम कएल पन्ना सभ",
-       "noindex-category": "क्रम नै कएल पन्ना सभ",
-       "broken-file-category": "पन्ना सभ जाइमे फाइल लिंक सभ टूटल हुअए",
-       "about": "विषयमे",
-       "article": "विषय à¤¸à¥\82à¤\9aà¥\80 à¤ªà¤¨à¥\8dना",
-       "newwindow": "(नव à¤\96िड़à¤\95à¥\80सà¤\81 à¤\96à¥\81à¤\9cà¥\88à¤\9b)",
+       "noindex-category": "क्रम नै कएल पन्नासभ",
+       "broken-file-category": "पन्नासभ जाइमे फाइल लिङ्कसभ टूटल हुअए",
+       "about": "à¤\95à¥\87 à¤µà¤¿à¤·à¤¯à¤®à¥\87",
+       "article": "सामà¤\97à¥\8dरà¥\80 à¤²à¥\87à¤\96",
+       "newwindow": "(नव खिडकीसँ खुजैछ)",
        "cancel": "समाप्त",
        "moredotdotdot": "आर...",
-       "morenotlisted": "à¤\88 à¤ªà¥\81रा à¤¸à¥\82à¤\9aà¥\80 à¤¨à¥\88 à¤\85à¤\9bà¥\80 ।",
+       "morenotlisted": "à¤\88 à¤ªà¥\81रा à¤¸à¥\82à¤\9aà¥\80 à¤¨à¥\88 à¤\9bà¥\80।",
        "mypage": "पन्ना",
-       "mytalk": "वारà¥\8dतà¥\8dता",
-       "anontalk": "à¤\90 à¤\85निà¤\95à¥\87त à¤ªà¤¤à¤¾ à¤²à¥\87ल à¤µà¤¿à¤®à¤°à¥\8dश",
+       "mytalk": "वार्ता",
+       "anontalk": "वारà¥\8dता",
        "navigation": "सञ्चार",
        "and": "&#32;आर",
        "qbfind": "ताकू",
        "qbbrowse": "गवेषण करू",
        "qbedit": "सम्पादन करू",
        "qbpageoptions": "ई पृष्ठ",
-       "qbmyoptions": "हमर पृष्ठ सभ",
+       "qbmyoptions": "हमर पृष्ठसभ",
        "faq": "त्वरित प्रश्नोत्तरी",
        "faqpage": "Project: त्वरित प्रश्नोत्तरी",
-       "actions": "क्रिया सभ",
+       "actions": "क्रियासभ",
        "namespaces": "चेन्हासी समूहसभ",
        "variants": "प्रकारसभ",
        "navigation-heading": "दिक्चालन सूची",
        "help": "मदति",
        "search": "ताकी",
        "searchbutton": "ताकी",
-       "go": "à¤\9cाà¤\8a",
-       "searcharticle": "à¤\9cाà¤\87",
+       "go": "à¤\9cाà¤\8f",
+       "searcharticle": "à¤\9cाà¤\8f",
        "history": "पन्नाक इतिहास",
        "history_short": "इतिहास",
        "updatedmarker": "हमर अन्तिम आगमनसँ पहिने अद्यतन कएल",
        "printableversion": "प्रिन्ट करबा योग्य",
        "permalink": "स्थायी लिङ्क",
-       "print": "à¤\9bापà¥\82",
+       "print": "à¤\9bापà¥\80",
        "view": "देखी",
-       "view-foreign": "$1 à¤ªà¤° à¤¦à¥\87à¤\96à¥\81",
+       "view-foreign": "$1 à¤ªà¤° à¤¦à¥\87à¤\96à¥\80",
        "edit": "सम्पादन",
-       "edit-local": "सà¥\8dथानà¥\80य à¤µà¤¿à¤µà¤°à¤£ à¤¸à¤\82पादन",
-       "create": "बनाà¤\89",
+       "edit-local": "सà¥\8dथानà¥\80य à¤µà¤¿à¤µà¤°à¤£ à¤¸à¤®à¥\8dपादन",
+       "create": "बनाबà¥\80",
        "create-local": "स्थानीय विवरण निर्माण",
-       "editthispage": "à¤\8fहि à¤ªà¥\83षà¥\8dठà¤\95 à¤¸à¤\82पादन",
-       "create-this-page": "à¤\88 à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¾à¤\89",
-       "delete": "मà¥\87à¤\9fाà¤\89",
-       "deletethispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤®à¥\87à¤\9fाà¤\89",
-       "undeletethispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤®à¥\87à¤\9fाà¤\89",
-       "undelete_short": "आपस आनू  {{PLURAL:$1|एक सम्पादनt|$1 सम्पादन सभ}}",
-       "viewdeleted_short": "दà¥\87à¤\96à¥\82 {{PLURAL:$1|एकटा मेटाएल सम्पादन|$1 मेटाएल सम्पादन सभ}}",
-       "protect": "बà¤\9aाà¤\89",
-       "protect_change": "बदलà¥\82",
-       "protectthispage": "à¤\90 à¤ªà¤¨à¥\8dनाà¤\95 à¤°à¤\95à¥\8dषा à¤\95रà¥\82",
-       "unprotect": "रà¤\95à¥\8dषा à¤\95वà¤\9a à¤¬à¤¦à¤²à¥\82",
-       "unprotectthispage": "à¤\90 à¤ªà¤¨à¥\8dनाà¤\95 à¤°à¤\95à¥\8dषा à¤\95वà¤\9a à¤¬à¤¦à¤²à¥\82",
+       "editthispage": "à¤\88 à¤ªà¥\83षà¥\8dठ à¤¸à¤®à¥\8dपादन à¤\95रà¥\80",
+       "create-this-page": "à¤\88 à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¾à¤¬à¥\80",
+       "delete": "मà¥\87à¤\9fाबà¥\80",
+       "deletethispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤®à¥\87à¤\9fाबà¥\80",
+       "undeletethispage": "à¤\88 à¤ªà¥\83षà¥\8dठà¤\95à¥\87 à¤ªà¥\81नरà¥\8dसà¥\8dथापित à¤\95रà¥\80।",
+       "undelete_short": "{{PLURAL:$1|एक हटाएल गएल|$1 हटाएल गएल}} परिवर्तन आपस आनी",
+       "viewdeleted_short": "दà¥\87à¤\96à¥\80 {{PLURAL:$1|एकटा मेटाएल सम्पादन|$1 मेटाएल सम्पादन सभ}}",
+       "protect": "सà¥\81रà¤\95à¥\8dषित à¤\95रà¥\80",
+       "protect_change": "बदलà¥\80",
+       "protectthispage": "à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¥\81रà¤\95à¥\8dषित à¤\95रà¥\80",
+       "unprotect": "à¤\85सà¥\81रà¤\95à¥\8dषित",
+       "unprotectthispage": "à¤\88 à¤ªà¥\83षà¥\8dठà¤\95 à¤¸à¥\81रà¤\95à¥\8dषा à¤¸à¥\8dतर à¤¬à¤¦à¤²à¥\80",
        "newpage": "नवका पन्ना",
-       "talkpage": "à¤\8fहि à¤ªà¥\83षà¥\8dठ à¤ªà¤° à¤µà¤¾à¤°à¥\8dतà¥\8dतालाप",
+       "talkpage": "à¤\88 à¤ªà¥\83षà¥\8dठà¤\95 à¤¬à¤¾à¤°à¥\87मà¥\87 à¤\9aरà¥\8dà¤\9aा à¤\95रà¥\80",
        "talkpagelinktext": "वार्ता",
        "specialpage": "विशेष पन्ना",
        "personaltools": "व्यक्तिगत उपकरणसभ",
-       "articlepage": "विषय-सà¥\82à¤\9aà¥\80 à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\82",
+       "articlepage": "विषय-सà¥\82à¤\9aà¥\80 à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\80",
        "talk": "वार्तालाप",
-       "views": "दà¥\83षà¥\8dà¤\9fिसभ",
-       "toolbox": "उपकरणसभ",
-       "userpage": "पà¥\8dरयà¥\8bà¤\95à¥\8dता à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\82",
-       "projectpage": "परियà¥\8bà¤\9cना à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\82",
-       "imagepage": "पनà¥\8dनाà¤\95 à¤ªà¥\83षà¥\8dठ à¤¦à¥\87à¤\96à¥\82",
-       "mediawikipage": "सनà¥\8dदà¥\87श à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\82",
-       "templatepage": "नमà¥\82ना à¤ªà¥\83षà¥\8dठ à¤¦à¥\87à¤\96à¥\82",
-       "viewhelppage": "सहायता à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\82",
-       "categorypage": "सà¤\82वरà¥\8dà¤\97 à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\82",
-       "viewtalkpage": "à¤\97पशप à¤¦à¥\87à¤\96à¥\82",
-       "otherlanguages": "दà¥\8bसर à¤­à¤¾à¤·à¤¾मे",
-       "redirectedfrom": "(एतयसँ बहटारल $1)",
-       "redirectpagesub": "पनà¥\8dनाà¤\95à¥\87à¤\81 à¤ªà¤ à¤¾à¤\89",
-       "redirectto": "मà¥\87 à¤ªà¥\81नरà¥\8dनिरà¥\8dदà¥\87श:",
-       "lastmodifiedat": "à¤\88 à¤ªà¤¨à¥\8dना à¤\85नà¥\8dतिम à¤¬à¥\87र à¤¸à¤\82वरà¥\8dधित à¤­à¥\87ल $1, à¤\95à¥\87à¤\81  $2 à¤¬à¤\9cà¥\87।",
-       "viewcount": "à¤\88 à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96ल à¤\97à¥\87ल {{PLURAL:$1|à¤\8fà¤\95 à¤¬à¥\87र|$1 à¤\8fतà¥\87à¤\95 à¤¬à¥\87र}}",
-       "protectedpage": "सà¤\82रà¤\95à¥\8dषित à¤ªà¤¨à¥\8dना",
-       "jumpto": "à¤\9cाà¤\8a:",
-       "jumptonavigation": "हà¥\87लà¥\82",
-       "jumptosearch": "ताà¤\95à¥\80",
-       "view-pool-error": "दà¥\81à¤\96à¥\80 à¤\9bà¥\80, à¤µà¤¿à¤¤à¤°à¤\95 à¤¸à¤­ à¤\8fà¤\96न à¤µà¥\8dयसà¥\8dत à¤\85à¤\9bि।\nबडà¥\8dड à¤¬à¥\87शà¥\80 à¤²à¥\8bà¤\95 à¤\90 à¤ªà¤¨à¥\8dनाà¤\95à¥\87à¤\81 à¤¦à¥\87à¤\96बामà¥\87 à¤²à¤¾à¤\97ल à¤\9bथि।\nà¤\90 à¤ªà¤¨à¥\8dनाà¤\95à¥\87à¤\81 फेरसँ देखबा लेल कनी बिलमू। \n$1",
-       "generic-pool-error": "दà¥\81à¤\96à¥\80 à¤\9bà¥\80, à¤µà¤¿à¤¤à¤°à¤\95 à¤¸à¤­ à¤\8fà¤\96न à¤µà¥\8dयसà¥\8dत à¤\85à¤\9bि।\nबडà¥\8dड à¤¬à¥\87शà¥\80 à¤²à¥\8bà¤\95 à¤\90 à¤ªà¤¨à¥\8dनाà¤\95à¥\87à¤\81 à¤¦à¥\87à¤\96बामà¥\87 à¤²à¤¾à¤\97ल à¤\9bथि।\nà¤\90 à¤ªà¤¨à¥\8dनाà¤\95à¥\87à¤\81 à¤«à¥\87रसà¤\81 à¤¦à¥\87à¤\96बा à¤²à¥\87ल à¤\95नà¥\80 à¤¬à¤¿à¤²à¤®à¥\82। \n$1",
+       "views": "दरà¥\8dशाव",
+       "toolbox": "उपकरण",
+       "userpage": "पà¥\8dरयà¥\8bà¤\95à¥\8dता à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\80",
+       "projectpage": "परियà¥\8bà¤\9cना à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\80",
+       "imagepage": "फाà¤\87ल à¤ªà¥\83षà¥\8dठ à¤¦à¥\87à¤\96à¥\80",
+       "mediawikipage": "सनà¥\8dदà¥\87श à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\80",
+       "templatepage": "नमà¥\82ना à¤ªà¥\83षà¥\8dठ à¤¦à¥\87à¤\96à¥\80",
+       "viewhelppage": "सहायता à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\80",
+       "categorypage": "शà¥\8dरà¥\87णà¥\80 à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\80",
+       "viewtalkpage": "à¤\97पशप à¤¦à¥\87à¤\96à¥\80",
+       "otherlanguages": "à¤\85नà¥\8dय à¤­à¤¾à¤·à¤¾à¤¸à¤­मे",
+       "redirectedfrom": "($1 सँ पुनर्निर्देशित)",
+       "redirectpagesub": "पà¥\83षà¥\8dठ à¤ªà¥\81नरà¥\8dनिरà¥\8dदà¥\87शित à¤\95रà¥\80",
+       "redirectto": "à¤\95 à¤\85नà¥\81पà¥\8dरà¥\87षित:",
+       "lastmodifiedat": "à¤\88 à¤ªà¥\83षà¥\8dठà¤\95 à¤ªà¤¹à¤¿à¤¨à¥\81à¤\95ा à¤¬à¤¦à¤²à¤¾à¤µ $1 à¤\95à¥\87 $2 à¤¬à¤\9cà¥\87 à¤­à¤\8fल à¤\9bल।",
+       "viewcount": "à¤\88 à¤ªà¥\83षà¥\8dठ {{PLURAL:$1|à¤\8fà¤\95|$1}} à¤¬à¥\87र à¤¦à¥\87à¤\96ल à¤\97à¥\87ल à¤\9bल।",
+       "protectedpage": "सà¥\81रà¤\95à¥\8dषित à¤ªà¥\83षà¥\8dठ",
+       "jumpto": "à¤\8fतय à¤\9cाà¤\8f:",
+       "jumptonavigation": "भà¥\8dरमण",
+       "jumptosearch": "à¤\96à¥\8bà¤\9c",
+       "view-pool-error": "à¤\95à¥\8dषमा à¤\95रà¥\80, à¤µà¤¿à¤¤à¤°à¤\95सभ à¤\8fà¤\96न à¤µà¥\8dयसà¥\8dत à¤\85à¤\9bि।\nबडà¥\8dड à¤¬à¥\87शà¥\80 à¤²à¥\8bà¤\95 à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤¦à¥\87à¤\96बामà¥\87 à¤²à¤¾à¤\97ल à¤\9bथि।\nà¤\88 à¤ªà¤¨à¥\8dनाà¤\95 फेरसँ देखबा लेल कनी बिलमू। \n$1",
+       "generic-pool-error": "à¤\95à¥\8dषमा à¤\95रà¥\80, à¤µà¤¿à¤¤à¤°à¤\95सभ à¤\8fà¤\96न à¤µà¥\8dयसà¥\8dत à¤\85à¤\9bि।\nबडà¥\8dड à¤¬à¥\87शà¥\80 à¤²à¥\8bà¤\95 à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤¦à¥\87à¤\96बामà¥\87 à¤²à¤¾à¤\97ल à¤\9bथि।\nà¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤«à¥\87रसà¤\81 à¤¦à¥\87à¤\96बा à¤²à¥\87ल à¤\95नà¥\80 à¤¬à¤¿à¤²à¤®à¥\82।",
        "pool-timeout": "प्रतीक्षा निगृहीत कालावसान",
        "pool-queuefull": "प्रतीक्षा-पाँती पौती भरल",
        "pool-errorunknown": "अज्ञात भ्रम",
-       "pool-servererror": "पà¥\82ल à¤\95ाà¤\89à¤\82टर सेवा उपलब्ध नै अछि ($1)।",
+       "pool-servererror": "पà¥\81ल à¤\95ाà¤\89नà¥\8dटर सेवा उपलब्ध नै अछि ($1)।",
        "poolcounter-usage-error": "उपयोग त्रुटि: $1",
        "aboutsite": "विषयमे {{SITENAME}}",
        "aboutpage": "Project:विवरण",
-       "copyright": "$1à¤\95 à¤\85à¤\82तर्गत विषय सूची उपलब्ध अछि",
+       "copyright": "$1à¤\95 à¤\85नà¥\8dतर्गत विषय सूची उपलब्ध अछि",
        "copyrightpage": "{{ns:project}}:सर्वाधिकार",
        "currentevents": "आइ-काल्हिक घटनासभ",
        "currentevents-url": "Project:आइ-काल्हिक घटनासभ",
        "disclaimers": "अनाधिकार घोषणा",
        "disclaimerpage": "Project:अनाधिकार घोषणा",
-       "edithelp": "सà¤\82पादन सहयोग",
+       "edithelp": "समà¥\8dपादन सहयोग",
        "helppage-top-gethelp": "मदति",
        "mainpage": "सम्मुख पन्ना",
        "mainpage-description": "सम्मुख पृष्ठ",
        "privacy": "गोपनीयताक नियम",
        "privacypage": "Project:गोपनीयता नियम",
        "badaccess": "आज्ञा गल्ती",
-       "badaccess-group0": "अहाँकेँ आग्रह कएल क्रियाकेँ करबाक अनुमति नै अछि।",
-       "badaccess-groups": "à¤\9cà¤\87 à¤\95à¥\8dरियाà¤\95 à¤\85हाà¤\81 à¤\86à¤\97à¥\8dरह à¤\95à¥\87नà¥\87 à¤\9bà¥\80 à¤¸à¥\87 à¤®à¤¾à¤¤à¥\8dर à¤\95िà¤\9bà¥\81 à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dता à¤²à¥\87ल à¤¸à¥\81रà¤\95à¥\8dषित à¤\85à¤\9bि {{PLURAL:$2|सà¤\82वरà¥\8dà¤\97|सà¤\82वरà¥\8dà¤\97 à¤¸à¤­à¤®à¥\87 à¤\8fà¤\95à¤\9fा}}: $1",
-       "versionrequired": "मिडियाविà¤\95à¥\80à¤\95ऽ संस्करण $1 चाही",
-       "versionrequiredtext": "à¤\90 à¤ªà¤¨à¥\8dनाà¤\95 à¤ªà¥\8dरयà¥\8bà¤\97 à¤²à¥\87ल à¤®à¤¿à¤¡à¤¿à¤¯à¤¾à¤µà¤¿à¤\95à¥\80à¤\95ऽ à¤¸à¤\82सà¥\8dà¤\95रण $1 à¤\9aाहà¥\80।\nदà¥\87à¤\96à¥\82 [[Special:Version|पà¥\83षà¥\8dठ à¤­à¤°à¥\8dसन]]",
+       "badaccess-group0": "अहाँक आग्रह कएल क्रियाक करबाक अनुमति नै अछि।",
+       "badaccess-groups": "à¤\85हाà¤\81 à¤\9cà¥\87 à¤\95à¥\8dरिया à¤\86à¤\9cमà¥\87नà¥\87 à¤\9bà¥\80 à¤\93 à¤®à¤¾à¤¤à¥\8dर {{PLURAL:$2|$1 à¤¸à¤®à¥\82ह|$1 à¤¸à¤®à¥\82हसभ}}à¤\95 à¤¸à¤¦à¤¸à¥\8dय à¤¹à¥\80 à¤\95रि à¤¸à¤\95à¤\8fत à¤\85à¤\9bि।",
+       "versionrequired": "मिडियाविà¤\95िà¤\95 संस्करण $1 चाही",
+       "versionrequiredtext": "à¤\88 à¤ªà¥\83षà¥\8dठ à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\88à¤\95 à¤²à¥\87ल à¤®à¤¿à¤¡à¤¿à¤¯à¤¾à¤µà¤¿à¤\95िà¤\95 $1 à¤\85वतरण à¤\9cरà¥\81रà¥\80 à¤\85à¤\9bि।\nदà¥\87à¤\96à¥\80 [[Special:Version|à¤\85वतरण à¤ªà¥\83षà¥\8dठ]]।",
        "ok": "ठीक अछि",
        "pagetitle-view-mainpage": "{{अन्तर्जाल}}",
        "backlinksubtitle": "← $1",
        "retrievedfrom": "प्राप्ति स्थल \"$1\"",
-       "youhavenewmessages": "अहाँ लग अछि $1 ($2).",
+       "youhavenewmessages": "{{PLURAL:$3|अहाँक लेल}} $1 ($2) अछि।",
        "youhavenewmessagesfromusers": "{{PLURAL:$4|अहाँके लेल}} $1 सँ {{PLURAL:$3|अन्य प्रयोक्ता|$3 प्रयोक्तासभ}} ($2)।",
        "youhavenewmessagesmanyusers": "अहाँके $1 सँ बहुत प्रयोक्ता सभ ($2)।",
        "newmessageslinkplural": "{{PLURAL:$1|एगो नयाँ पत्र|999=नयाँ पत्र}}",
        "newmessagesdifflinkplural": "अन्तिम {{PLURAL:$1|परिवर्त्तन|999=परिवर्त्तन सभ}}",
        "youhavenewmessagesmulti": "$1 पर अहाँ लेल नव पत्र अछि",
        "editsection": "सम्पादन करी",
-       "editold": "समà¥\8dपादित à¤\95रà¥\82",
-       "viewsourceold": "à¤\9cड़ि à¤¦à¥\87à¤\96à¥\82",
-       "editlink": "समà¥\8dपादन à¤\95रà¥\82",
-       "viewsourcelink": "à¤\9cडà¥\80 देखी",
+       "editold": "समà¥\8dपादित à¤\95रà¥\80",
+       "viewsourceold": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\80",
+       "editlink": "समà¥\8dपादन à¤\95रà¥\80",
+       "viewsourcelink": "सà¥\8dरà¥\8bत देखी",
        "editsectionhint": "सम्पादन शाखा: $1",
        "toc": "विषय सूचीसभ",
-       "showtoc": "दà¥\87à¤\96ाà¤\8a",
-       "hidetoc": "नà¥\81à¤\95ाà¤\8a",
-       "collapsible-collapse": "भà¤\96ड़ाà¤\89",
-       "collapsible-expand": "बढ़ाà¤\89",
-       "confirmable-confirm": "कि {{GENDER:$1|अहाँ}} छी?",
+       "showtoc": "दà¥\87à¤\96ाबà¥\80",
+       "hidetoc": "नà¥\81à¤\95ाबà¥\80",
+       "collapsible-collapse": "भà¤\96डाबà¥\80",
+       "collapsible-expand": "विसà¥\8dतार à¤\95रà¥\80",
+       "confirmable-confirm": "à¤\95ि {{GENDER:$1|à¤\85हाà¤\81}} à¤¨à¤¿à¤¶à¥\8dà¤\9aित à¤\9bà¥\80?",
        "confirmable-yes": "हँ",
        "confirmable-no": "नै",
-       "thisisdeleted": "$1 à¤¦à¥\87à¤\96à¥\82 à¤µà¤¾ à¤«à¥\87र à¤¸à¤\81 à¤\86नà¥\81?",
-       "viewdeleted": "$1 à¤\95à¥\87 à¤¦à¥\87à¤\96ाà¤\8a?",
+       "thisisdeleted": "$1 à¤¦à¥\87à¤\96à¥\80 à¤µà¤¾ à¤«à¥\87रसà¤\81 à¤\86नà¥\80?",
+       "viewdeleted": "$1 à¤\95à¥\87 à¤¦à¥\87à¤\96ाबà¥\80?",
        "restorelink": "{{PLURAL:$1|एकटा मेटाएल सम्पादन|$1 मेटाएल सम्पादन सभ}}",
        "feedlinks": "सूचक:",
        "feed-invalid": "अमान्य सूचक प्रकार मासुल",
        "feed-atom": "अणु",
        "feed-rss": "आर.एस.एस.",
        "red-link-title": "$1 (पृष्ठ उपलब्ध नै अछि)",
-       "sort-descending": "à¤\98à¤\9fà¥\88त à¤\95à¥\8dरममà¥\87 à¤\9bाà¤\81à¤\9fà¥\82",
-       "sort-ascending": "बढ़à¥\88त à¤\95à¥\8dरममà¥\87 à¤\9bाà¤\81à¤\9fà¥\82",
+       "sort-descending": "à¤\98à¤\9fà¥\88त à¤\95à¥\8dरममà¥\87 à¤\9bाà¤\81à¤\9fà¥\80",
+       "sort-ascending": "बढà¥\88त à¤\95à¥\8dरममà¥\87 à¤\9bाà¤\81à¤\9fà¥\80",
        "nstab-main": "पन्ना",
        "nstab-user": "प्रयोक्ता पृष्ठ",
        "nstab-media": "मिडिया पृष्ठ",
        "nstab-mediawiki": "पत्र",
        "nstab-template": "आकृति",
        "nstab-help": "सहायता पृष्ठ",
-       "nstab-category": "सà¤\82वरà¥\8dà¤\97",
+       "nstab-category": "शà¥\8dरà¥\87णà¥\80",
        "mainpage-nstab": "सम्मुख पन्ना",
        "nosuchaction": "एहेन कोनो क्रिया नै अछि",
        "nosuchactiontext": "ऐ सार्वत्रिक विभव संकेत द्वारा निर्दिष्ट क्रिया अमान्य अछि।\nअहाँ सार्वत्रिक विभव संकेतक गलत टंकण केने हएब, वा कोनो गलत लिंकक पाछाँ गेल हएब।\nई {{अन्तर्जाल}} प्रयोक्ता द्वारा प्रयुक्त तंत्रांशमे स्थित कोनो दोषक संकेत सेहो कऽ सकैए।",
        "laggedslavemode": "'''चेतौनी:''' पन्नापर सम्भव जे अद्यतन परिवर्तन नै हुअए।",
        "readonly": "दत्तनिधि प्रतिबन्धित",
        "enterlockreason": "प्रतिबन्ध लेल कारण बताउ, संगमे एकटा अंदाज सेहो बताउ जे कखन ई प्रतिबन्ध हटाएल जाएत।",
-       "readonlytext": "à¤\85à¤\96न à¤¦à¤¤à¥\8dताà¤\82शनिधि à¤¨à¤µ à¤ªà¥\8dरविषà¥\8dà¤\9fि à¤\86 à¤\86न à¤¸à¤\82शà¥\8bधन à¤²à¥\87ल à¤ªà¥\8dरतिबनà¥\8dधित à¤\85à¤\9bि, à¤¸à¤®à¥\8dभवतà¤\83 à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dत à¤¦à¤¤à¥\8dताà¤\82शनिधि à¤¦à¥\87à¤\96भाल à¤²à¥\87ल, à¤¤à¤\95र à¤¬à¤¾à¤¦ à¤\88 à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dय à¤­à¤½ à¤\9cाà¤\8fत।\n\nसà¤\82चालक जे एकरा प्रतिबन्धित कएने छथि ई कारण दै छथि:$1",
+       "readonlytext": "à¤\85à¤\96न à¤¦à¤¤à¥\8dताà¤\82शनिधि à¤¨à¤µ à¤ªà¥\8dरविषà¥\8dà¤\9fि à¤\86 à¤\86न à¤¸à¤\82शà¥\8bधन à¤²à¥\87ल à¤ªà¥\8dरतिबनà¥\8dधित à¤\85à¤\9bि, à¤¸à¤®à¥\8dभवतà¤\83 à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dत à¤¦à¤¤à¥\8dताà¤\82शनिधि à¤¦à¥\87à¤\96भाल à¤²à¥\87ल, à¤¤à¤\95र à¤¬à¤¾à¤¦ à¤\88 à¤¸à¤¾à¤®à¤¾à¤¨à¥\8dय à¤­à¤½ à¤\9cाà¤\8fत।\n\nसà¤\9eà¥\8dचालक जे एकरा प्रतिबन्धित कएने छथि ई कारण दै छथि:$1",
        "missing-article": "दत्तनिधि पृष्ठक वांछित पाठ्य नै ताकि सकल, माने \"$1\" $2\nएकर कारण कोनो पुरान फाइल चेन्हासी वा ऐतिहासिक लिंकक पाछाँ जाएब अछि, जे मेटा देल गेल छै।\nजौं ई तकर कारण नै अछि,  तखन अहाँकेँ तंत्रांशमे कोनो दोष भेटल अछि।\nएकर खबरि पहुँचाउ [[Special:ListUsers/sysop|administrator]], केँ, अपन सार्वत्रिक विभव संकेत सूचित करैत।",
        "missingarticle-rev": "(संशोधन#: $1)",
        "missingarticle-diff": "(फाइल-अन्तर प्रणाली: $1, $2)",
        "readonly_lag": "दत्तांशनिधि स्वचालित रूपेँ प्रतिबन्धित कएल गेल अछि जा परजीवी दतांशनिधि वितरक मूलक समक्ष नै आबि जाए।",
+       "nonwrite-api-promise-error": "'Promise-Non-Write-API-Action'क एचटिटिपी शीर्षकद्वारा भेजल गएल पर एपिआईमे लेखन मोड्युल अछि।",
        "internalerror": "आन्तरिक भ्रम",
        "internalerror_info": "आन्तरिक भ्रम: $1",
        "internalerror-fatal-exception": "प्रकारक गम्भीर अपवाद \"$1\"",
        "directorynotreadableerror": "निर्देशिका \"$1\" पठनीय नै अछि।",
        "filenotfound": "फाइल \"$1\" नै ताकि सकल।",
        "unexpected": "आसक विपरीत परिणाम: \"$1\"=\"$2\"",
-       "formerror": "फà¥\89रà¥\8dम à¤¨à¥\88 à¤ªà¤ ा सकल",
+       "formerror": "तà¥\8dरà¥\81à¤\9fि: à¤«à¤°à¥\8dम à¤\85नà¥\81रà¥\8bध à¤¨à¥\88 à¤\95à¤\8fल à¤\9cा सकल",
        "badarticleerror": "ई क्रिया ऐ पन्नापर नै कएल जा सकैए।",
        "cannotdelete": "पन्ना व संचिका \"$1\" मेटाएल नै जा सकल।",
        "cannotdelete-title": "पन्ना \"$1\" नै मेटा सकल",
        "perfcached": "ई दत्तांश उपस्मृतिक आधारपर अछि आ भऽ सकैए जे अद्यतन नै हुअए। अधिकतम {{PLURAL:$1|एकटा परिणाम|$1 परिणाम सभ}} क्याचेमे उपलब्ध अछि ।",
        "perfcachedts": "ई दत्तांश उपस्मृतिमे अछि, आ एकर अन्तिम परिवर्धन भेल अछि $1 केँ। A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.",
        "querypage-no-updates": "ऐ पन्नाक नवीनीकरण अखन बन्न अछि।\nएतुक्का दत्तांश अखन नवीकरण नै कएल जाएत।",
-       "viewsource": "à¤\9cड़ि à¤¦à¥\87à¤\96à¥\82",
-       "viewsource-title": "\"$1\" à¤²à¥\87ल à¤\9cड़ि à¤¦à¥\87à¤\96à¥\82",
-       "actionthrottled": "à¤\95à¥\8dरियाà¤\95à¥\87à¤\81 à¤®à¥\8bà¤\95ल à¤\97à¥\87ल",
-       "actionthrottledtext": "à¤\85नपà¥\87à¤\95à¥\8dषित à¤¸à¤\82दà¥\87श à¤°à¥\8bà¤\95ा à¤²à¥\87ल, à¤\85हाà¤\81à¤\95à¥\87à¤\81 à¤\90 à¤\95à¥\8dरियाà¤\95à¥\87à¤\81 à¤\95मà¥\8dमà¥\87 à¤\95ालमà¥\87 à¤¸à¥\80मासà¤\81 à¤¬à¥\87शà¥\80 à¤¬à¥\87र à¤\95रबासà¤\81 à¤°à¥\8bà¤\95ल à¤\97à¥\87ल à¤\85à¤\9bि, à¤\85हाà¤\81 à¤\93à¤\87 à¤¸à¥\80माà¤\95à¥\87à¤\81 à¤ªà¤¾à¤° à¤\95ऽ à¤\97à¥\87ल à¤\9bà¥\80।\nà¤\95à¥\83पया à¤\95िà¤\9bà¥\81 à¤\95ाल à¤¬à¤¾à¤¦ à¤«à¥\87रसà¤\81 à¤ªà¥\8dरयास à¤\95रà¥\82।",
+       "viewsource": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\80",
+       "viewsource-title": "\"$1\" à¤²à¥\87ल à¤¸à¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\80",
+       "actionthrottled": "à¤\95ारà¥\8dय à¤¸à¤®à¤¾à¤ªà¥\8dत à¤\95रि à¤¦à¥\87ल à¤\97à¤\8fल",
+       "actionthrottledtext": "à¤\85नपà¥\87à¤\95à¥\8dषित à¤¸à¤¨à¥\8dदà¥\87श à¤°à¥\8bà¤\95 à¤²à¥\87ल, à¤\85हाà¤\81à¤\95 à¤\88 à¤\95à¥\8dरियाà¤\95 à¤\95मà¥\8dमà¥\87 à¤\95ालमà¥\87 à¤¸à¥\80मासà¤\81 à¤¬à¥\87सà¥\80बà¥\87र à¤\95रबासà¤\81 à¤°à¥\8bà¤\95ल à¤\97à¥\87ल à¤\85à¤\9bि, à¤\85हाà¤\81 à¤\93 à¤¸à¥\80माà¤\95 à¤ªà¤¾à¤° à¤\95ऽ à¤\97à¥\87ल à¤\9bà¥\80।\nà¤\95à¥\83पया à¤\95िà¤\9b à¤\95ाल à¤¬à¤¾à¤¦ à¤«à¥\87रसà¤\81 à¤ªà¥\8dरयास à¤\95रà¥\80।",
        "protectedpagetext": "ई पन्ना सम्पादन रोकबा लेल संरक्षित अछि।",
-       "viewsourcetext": "à¤\85हाà¤\81 à¤\90 à¤ªà¤¨à¥\8dनाà¤\95 à¤\9cड़िà¤\95à¥\87à¤\81 देख आ अनुकृत कऽ सकै छी:",
-       "viewyourtext": "अहाँ '''अहाँक सम्पादन''' केँ देख आ एतए उतारि सकै छी:",
+       "viewsourcetext": "à¤\85हाà¤\81 à¤\87 à¤ªà¥\83षà¥\8dठà¤\95 à¤\9cडिà¤\95 देख आ अनुकृत कऽ सकै छी:",
+       "viewyourtext": "अहाँ ई पृष्ठमे '''अपन सम्पादन'''क देख आ एतए उतारि सकै छी:",
        "protectedinterface": "ई पन्ना तंत्रांश लेल मध्यस्थ पाठक व्यवस्था करैत अछि, आ अपशब्द रोकबाक ब्योंत करैत अछि।",
        "editinginterface": "'''चेतौनी''' अहाँ एकटा एहेन पन्नाक सम्पादन कऽ रहल छी जे तंत्रांशक मध्यस्थ पन्नाकेँ पाठ देबा लेल प्रयोग भऽ रहल अछि।\nऐ पन्नामे परिवर्तन दोसर प्रयोक्ता लेल प्रयोक्ता मध्यस्थक रूपमे परिवर्तन करत।\nअनुवाद लेल [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net] जाउ, मीडियाविकी स्थानीयकरण परियोजना पर।",
        "translateinterface": "सभ विकिसब के लेल अनुवाद जोडइ या बदलई के लेल मीडियाविकि क्षेत्रीयकरण परियोजना [//translatewiki.net/ translatewiki.net] कें प्रयोग करु।",
-       "cascadeprotected": "à¤\90 à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¤®à¥\8dपादन à¤¸à¤®à¥\8dभव à¤¨à¥\88 à¤\85à¤\9bि, à¤\95ारण à¤\88 à¤\90 à¤®à¥\87 à¤¸à¤®à¥\8dमिलित à¤\85à¤\9bि, {{PLURAL:$1|पनà¥\8dना, à¤\9cà¥\87 à¤\85à¤\9bि|पनà¥\8dना, à¤¸à¥\87 à¤¸à¤­ à¤\85à¤\9bि}} à¤¸à¥\81रà¤\95à¥\8dषित à¤\85à¤\9bि \"तराà¤\89पड़ी\" विकल्प खोललाक बाद:\n$2",
+       "cascadeprotected": "à¤\88 à¤ªà¤¨à¥\8dनाà¤\95 à¤¸à¤®à¥\8dपादन à¤¸à¤®à¥\8dभव à¤¨à¥\88 à¤\85à¤\9bि, à¤\95ारण à¤\85हिमà¥\87 à¤¸à¤®à¥\8dमिलित à¤\85à¤\9bि, {{PLURAL:$1|पà¥\83षà¥\8dठ|पà¥\83षà¥\8dठसभ}} à¤¸à¥\81रà¤\95à¥\8dषित à¤\85à¤\9bि \"तराà¤\89पडी\" विकल्प खोललाक बाद:\n$2",
        "namespaceprotected": "अहाँकेँ '''$1''' नाम-पेटारमे सम्पादनक अनुमति नै अछि।",
        "customcssprotected": "अहांकें ऐ सी.एस.एस.पन्नाकें सम्पादित करबाक अधिकार नै अछि, कारण ऐमे दोसर प्रयोक्ताक व्यक्तिगत विकल्प छै।",
        "customjsprotected": "अहांकें ऐ जावास्क्रिप्ट पन्नाकें सम्पादित करबाक अधिकार नै अछि, कारण ऐमे दोसर प्रयोक्ताक व्यक्तिगत विकल्प छै।",
        "mypreferencesprotected": "अहाके अपन प्राथमिकता बदलैक अनुमति नै अछि।",
        "ns-specialprotected": "विशेष पन्ना सभकेँ सम्पादित नै कएल जा सकैए।",
        "titleprotected": "ऐ शीर्षकक निर्माण प्रतिबन्धित अछि [[User:$1|$1]] द्वारा।\nकारण एतऽ देल अछि <em>$2</em>।",
-       "filereadonlyerror": "\"$1\" फाइलके बदलैलेल अक्षम कियाक भण्डार \"$2\" इ समय 'मात्र पाठन के लेल' (रीड ओनली) अछि।\n\nजे प्रबंधक इ प्रबंध लगोनै अछि हुनका निम्न विवरण प्रदान कएल गेल अछि: \"$3\"।",
+       "filereadonlyerror": "\"$1\" फाइलके बदलैलेल अक्षम कियाक भण्डार \"$2\" इ समय 'मात्र पाठनक लेल' अछि।\n\nजे प्रबन्धक ई प्रबन्ध लगोनै अछि ओ निम्न विवरण प्रदान कएने अछि: \"$3\"।",
        "invalidtitle-knownnamespace": "\"$2\" नामस्थान आर \"$3\" नाम बला गलत शीर्षक",
        "invalidtitle-unknownnamespace": "अज्ञात नामस्थान संख्या $1 आर नाम \"$2\" वाला गलत शीर्षक",
        "exception-nologin": "सम्प्रवेशित नै",
        "virus-scanfailed": "बिम्ब विफल (विध्यादेश $1)",
        "virus-unknownscanner": "अज्ञात विषविधि निरोधक",
        "logouttext": "'''अहाँ निष्क्रमण कऽ गेल छी।'''\n\nअहाँ {{अन्तर्जाल}} प्रयोग अनाम भऽ कऽ सकै छी, वा अहाँ <span class='plainlinks'>[$1 log in again]</span> वएह आकि कोनो आन प्रयोक्ताक रूपमे सेहू प्रयोक कऽ सकै छी।\nई मोन राखू जे किछु पन्ना एना देखा पड़ि सकैए जेना अहाँ अखनो सम्प्रवेशित होइ, जावत अहाँ अपन गवेषकक उपस्मृति मेटा नै दै छी।",
+       "cannotlogoutnow-title": "अखन प्रस्थान नै भऽ रहल अछि",
+       "cannotlogoutnow-text": "$1 क उपयोग समय प्रस्थान नै कएल जा सकएत अछि।",
        "welcomeuser": "अहाके स्वागत अछि, $1!",
-       "welcomecreation-msg": "à¤\85हाà¤\95à¥\87 à¤\96ाता à¤¬à¤¨à¤¾à¤µà¥\8bल à¤\97à¥\87ल à¤\85à¤\9bि à¥¤\nà¤\85पन [[Special:Preferences|{{SITENAME}} à¤ªà¥\8dराथमिà¤\95तासभ]] à¤¬à¤¦à¤²à¥\88ल नै बिसरब।",
+       "welcomecreation-msg": "à¤\85हाà¤\81à¤\95 à¤\96ाता à¤¬à¤¨à¤¾à¤\8fल à¤\97à¥\87ल à¤\85à¤\9bि।\nà¤\85पन [[Special:Preferences|{{SITENAME}} à¤ªà¤¸à¤¨à¥\8dद]] à¤¬à¤¦à¤²à¥\88 à¤²à¥\87ल नै बिसरब।",
        "yourname": "प्रयोक्ता:",
        "userlogin-yourname": "प्रयोक्ता:",
-       "userlogin-yourname-ph": "à¤\85पन à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dतानाम à¤²à¤¿à¤\96à¥\81",
-       "createacct-another-username-ph": "à¤\8fà¤\95à¤\9fा à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dतानाम à¤²à¤¿à¤\96à¥\82:",
+       "userlogin-yourname-ph": "à¤\85पन à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dतानाम à¤²à¤¿à¤\96à¥\80",
+       "createacct-another-username-ph": "पà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dतानाम à¤ªà¥\8dरदान à¤\95रà¥\80",
        "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": "खाहे सत्यापन दतांश भ्रम छल वा अहाँ अपन बाह्य खाताकेँ अद्यतन करबामे असमर्थ छी।",
+       "userlogin-yourpassword": "कूटशब्द",
+       "userlogin-yourpassword-ph": "अपन कूटशब्द लिखी",
+       "createacct-yourpassword-ph": "कूटशब्द दर्ज करी",
+       "yourpasswordagain": "कूटशब्द फेरसँ टाइप करी:",
+       "createacct-yourpasswordagain": "कूटशब्दक जाँच करी",
+       "createacct-yourpasswordagain-ph": "कूटशब्द पुनः लिखी",
+       "remembermypassword": "ई ब्राउजर पर हमर सम्प्रवेश याद राखी (अधिकतम $1 {{PLURAL:$1|दिन|दिनधरि}}क लेल)",
+       "userlogin-remembermypassword": "हमरा सम्प्रवेशित राखी",
+       "userlogin-signwithsecure": "सुरक्षित कनेक्शनक प्रयोग करी",
+       "cannotloginnow-title": "अखन प्रवेश नै भऽ रहल अछि",
+       "cannotloginnow-text": "$1 क उपयोग समय प्रवेश नै कएल जा सकएत अछि।",
+       "yourdomainname": "अहाँक डोमेन (प्रभावक्षेत्र):",
+       "password-change-forbidden": "अहाँ ई विकिमे कूटशब्द नै बदल सकैत छी।",
+       "externaldberror": "या त प्रमाणिकरण डेटाबेसमे त्रुटि भएल अछि या फेर अहाँक अपन बाह्य खाता अपडेट करैक अनुमति नै अछि।",
        "login": "सम्प्रवेश",
-       "nav-login-createaccount": "सम्प्रवेश /खेसरा बनाऊ",
-       "userlogin": "समà¥\8dपà¥\8dरवà¥\87श/ à¤\96à¥\87सरा à¤¬à¤¨à¤¾à¤\8a",
+       "nav-login-createaccount": "सम्प्रवेश / खाता खोली",
+       "userlogin": "समà¥\8dपà¥\8dरवà¥\87श/ à¤\96ाता à¤¬à¤¨à¤¾à¤¬à¥\80",
        "userloginnocreate": "सम्प्रवेश",
        "logout": "निष्क्रमण",
        "userlogout": "फेर आयब",
        "notloggedin": "सम्प्रवेशित नै छी",
        "userlogin-noaccount": "खाता नै अछि?",
-       "userlogin-joinproject": "{{SITENAME}} से जोडु",
+       "userlogin-joinproject": "{{SITENAME}}सँ जुडी",
        "nologin": "खाता नै अछि? $1।",
-       "nologinlink": "नव à¤\96ाता à¤\96à¥\8bलà¥\82",
-       "createaccount": "à¤\96ाता à¤\96à¥\8bलà¥\82",
+       "nologinlink": "नव à¤\96ाता à¤\96à¥\8bलà¥\80",
+       "createaccount": "à¤\96ाता à¤\96à¥\8bलà¥\80",
        "gotaccount": "पहिनहियेसँ खाता अछि? $1",
        "gotaccountlink": "सम्प्रवेश",
-       "userlogin-resetlink": "à¤\85पन à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤µà¤¿à¤µà¤°à¤£ à¤¬à¤¿à¤¸à¤°à¤¿ à¤\97à¥\87लहà¥\81à¤\81?",
-       "userlogin-resetpassword-link": "अपन कूटशब्द बिसर गेलौ ?",
+       "userlogin-resetlink": "à¤\85पन à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤µà¤¿à¤µà¤°à¤£ à¤¬à¤¿à¤¸à¤°à¤¿ à¤\97à¥\87लà¥\8c?",
+       "userlogin-resetpassword-link": "अपन कूटशब्द बिसरि गेलौ?",
        "userlogin-helplink2": "सम्प्रवेशित करवाकलेल मदत",
-       "userlogin-loggedin": "अहा {{GENDER:$1|$1}} के रूपमे पहिले स सम्प्रवेशित छि।\nकोनो दोसर सदस्यके रुपमे सम्प्रवेशित करवाक लेल देल गेल फारमके प्रयोग करु।",
-       "userlogin-createanother": "दà¥\8bसर à¤\96ाता à¤¬à¤¨à¤¾à¤\89",
-       "createacct-emailrequired": "à¤\88-पतà¥\8dर à¤¸à¤\82à¤\95à¥\87त",
-       "createacct-emailoptional": "à¤\88-पतà¥\8dर à¤¸à¤\82à¤\95à¥\87त (वैकल्पिक)",
-       "createacct-email-ph": "à¤\85पन à¤\88-पतà¥\8dर à¤¸à¤\82à¤\95à¥\87त à¤¸à¤¤à¥\8dयापित à¤\95रà¥\82",
-       "createacct-another-email-ph": "ई-पत्र संकेत सत्यापित करू",
-       "createaccountmail": "à¤\88-पतà¥\8dर à¤¦à¥\8dवारा",
+       "userlogin-loggedin": "अहाँ {{GENDER:$1|$1}}क रूपमे पहिनेसँ सम्प्रवेशित छी।\nकोनो दोसर सदस्यक रुपमे सम्प्रवेशित करवाक लेल देल गेल फारमके प्रयोग करी।",
+       "userlogin-createanother": "दà¥\8bसर à¤\96ाता à¤¬à¤¨à¤¾à¤¬à¥\80",
+       "createacct-emailrequired": "à¤\88-मà¥\87ल à¤ªà¤¤à¤¾",
+       "createacct-emailoptional": "à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ (वैकल्पिक)",
+       "createacct-email-ph": "à¤\85पन à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ à¤²à¤¿à¤\96à¥\80",
+       "createacct-another-email-ph": "ईमेल पता प्रदान करी",
+       "createaccountmail": "à¤\8fà¤\95 à¤\85सà¥\8dथायà¥\80 à¤¯à¤¾à¤¦à¥\83à¤\9aà¥\8dà¤\9bिà¤\95 à¤\95à¥\82à¤\9fशबà¥\8dद à¤\9aà¥\81नà¥\80 à¤\86 à¤\93 à¤¨à¤¿à¤°à¥\8dदिषà¥\8dà¤\9f à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ à¤ªà¤° à¤­à¥\87à¤\9cà¥\80",
        "createacct-realname": "असली नाम (वैकल्पिक)",
        "createaccountreason": "कारण:",
        "createacct-reason": "कारण:",
        "createacct-reason-ph": "अहा इगो आर दोसर खाता कियाक बनउने जा रहल छि",
        "createacct-submit": "अपन खाता बनाउ",
-       "createacct-another-submit": "दोसर खाता बनाउ",
-       "createacct-benefit-heading": "{{SITENAME}} अहि जोका लोकनिसभ द्वारा बनावल गेल अछि।",
-       "createacct-benefit-body1": "$1 {{PLURAL:$1|सम्पादन|सम्पादन सभ}}",
-       "createacct-benefit-body2": "{{PLURAL:$1|पन्ना}}",
-       "createacct-benefit-body3": "{{PLURAL:$1|योगदानकर्ता}}",
-       "badretype": "कूटशब्द जे अहाँ भरलहुँ से मेल नै खाइए।",
-       "userexists": "सम्प्रवेशित प्रयोक्तानाम पहिनहियेसँ प्रयोगमे अछि।\nकृपा कऽ कोनो दोसर नाम चुनू।",
-       "loginerror": "सम्प्रवेश भ्रम",
-       "createacct-error": "खाता निर्माण त्रुटि",
-       "createaccounterror": "खाता नै बना सकल: $1",
-       "nocookiesnew": "प्रयोक्ता खाता खुजि गेल, मुदा अहाँ सम्प्रवेशित नै छी।\n{{अन्तर्जाल}} सम्प्रवेशित प्रयोक्ताक लेल ज्ञापकक प्रयोग करैत अछि।\nअहाँ ज्ञापककेँ अशक्त केने छी।\nकृपा कऽ ओकरा सक्रिप करू, तखन अपन प्रयोक्तानाम आ कूटशब्दक संग सम्प्रवेश करू।",
-       "nocookieslogin": "{{अन्तर्जाल}} प्रयोक्ताकेँ सम्प्रवेशित करबा लेल ज्ञापकक प्रयोग करैत अछि।\nअहाँ ज्ञापककेँ अशक्त केने छी।\nकृपा कऽ ओकरा सक्रिय करू आ फेरसँ प्रयास करू।",
-       "nocookiesfornew": "प्रयोक्ता खाजा नै खुजल, कारण हम ओकर जड़ि पूर्ण रूपेँ नै ताकि सकलौं।\nई दृढ़ करू जे ज्ञापक सक्रिय अछि, ऐ पन्नाकेँ फेरसँ भारित करू आ फेरसँ प्रयास करू।",
+       "createacct-another-submit": "खाता बनाबी",
+       "createacct-benefit-heading": "{{SITENAME}} अहाँ जोका लोगसभद्वारा बनाएल गएल अछि।",
+       "createacct-benefit-body1": "$1 {{PLURAL:$1|सम्पादन|सम्पादनसभ}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|पन्ना|पन्नासभ}}",
+       "createacct-benefit-body3": "सन्निकट {{PLURAL:$1|योगदानकर्ता|योगदानकर्तासभ}}",
+       "badretype": "कूटशब्द जे अहाँ देलौ से मेल नै खाइए।",
+       "usernameinprogress": "ई प्रयोक्ताक खाता निर्माण अखन चालू अछि।\nकृपया प्रतीक्षा करी।",
+       "userexists": "सम्प्रवेशित प्रयोक्तानाम पहिनहियेसँ प्रयोगमे अछि।\nकृपा कऽ कोनो दोसर नाम चुनी।",
+       "loginerror": "सम्प्रवेश त्रुटी",
+       "createacct-error": "खाता निर्माण त्रुटी",
+       "createaccounterror": "खाता नै बनि सकल: $1",
+       "nocookiesnew": "प्रयोक्ता खाता खुजि गेल, मुदा अहाँ सम्प्रवेशित नै छी।\n{{SITENAME}} सम्प्रवेशित प्रयोक्ताक लेल ज्ञापकक प्रयोग करैत अछि।\nअहाँ ज्ञापकक अशक्त केनए छी।\nकृपा कऽ ओकरा सक्रिय करी, तखन अपन प्रयोक्तानाम आ कूटशब्दक संग सम्प्रवेश करी।",
+       "nocookieslogin": "{{SITENAME}} प्रयोक्ताक सम्प्रवेशित करबा लेल ज्ञापकक प्रयोग करैत अछि।\nअहाँ ज्ञापकक अशक्त केने छी।\nकृपा कऽ ओकरा सक्रिय करी आ फेरसँ प्रयास करी।",
+       "nocookiesfornew": "प्रयोक्ता खाजा नै खुजल, कारण हम ओकर जडि पूर्ण रूपेँ नै ताकि सकलौ।\nई दृढ करी जे ज्ञापक सक्रिय अछि, ई पन्नाक फेरसँ भारित करी आ फेरसँ प्रयास करी।",
        "noname": "अहाँ वैध प्रयोक्तानाम नै देने छी।",
-       "loginsuccesstitle": "समà¥\8dपà¥\8dरवà¥\87श à¤¸à¤«ल",
+       "loginsuccesstitle": "समà¥\8dपà¥\8dरवà¥\87श à¤­à¤\8fल",
        "loginsuccess": "'''अहाँ सम्प्रवेश केलहुँ {{SITENAME}} \"$1\".'''क रूपमे।",
-       "nosuchuser": "\"$1\" à¤¨à¤¾à¤®à¤¸à¤\81 à¤\95à¥\8bनà¥\8b à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dता à¤¨à¥\88 à¤\85à¤\9bि।\nपà¥\8dरयà¥\8bà¤\95à¥\8dतानाम à¤¬à¥\8dरहà¥\8dमà¤\95à¥\8dषर-लà¤\98à¥\8dवà¤\95à¥\8dषर à¤­à¥\87द à¤¯à¥\81à¤\95à¥\8dत à¤\85à¤\9bि।\nà¤\85पन à¤¹à¥\8dरिà¤\9cà¥\88 à¤\9cाà¤\81à¤\9aà¥\82, à¤µà¤¾ [[Special:UserLogin/signup|नव à¤\96ाता à¤¬à¤¨à¤¾à¤\89]] ।",
-       "nosuchusershort": "\"$1\" à¤¨à¤¾à¤®à¥\8dना à¤\95à¥\8bनà¥\8b à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dता à¤¨à¥\88 à¤\85à¤\9bि।\nà¤\85पन à¤¹à¥\8dरिà¤\9cà¤\8f à¤¸à¥\81धारà¥\82।",
-       "nouserspecified": "अहाँकेँ एकटा प्रयोक्तानाम देबऽ पड़त।",
+       "nosuchuser": "\"$1\" à¤¨à¤¾à¤®à¤¸à¤\81 à¤\95à¥\8bनà¥\8b à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dता à¤¨à¥\88 à¤\85à¤\9bि।\nपà¥\8dरयà¥\8bà¤\95à¥\8dतानाम à¤¬à¥\8dरहà¥\8dमà¤\95à¥\8dषर-लà¤\98à¥\8dवà¤\95à¥\8dषर à¤­à¥\87द à¤¯à¥\81à¤\95à¥\8dत à¤\85à¤\9bि।\nà¤\85पन à¤¹à¥\8dरिà¤\9cà¥\88 à¤\9cाà¤\81à¤\9aà¥\80, à¤µà¤¾ [[Special:UserLogin/signup|नव à¤\96ाता à¤¬à¤¨à¤¾à¤¬à¥\80]] ।",
+       "nosuchusershort": "\"$1\" à¤¨à¤¾à¤®à¥\8dना à¤\95à¥\8bनà¥\8b à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dता à¤¨à¥\88 à¤\85à¤\9bि।\nà¤\85पन à¤¹à¤¿à¤\9cà¤\8f à¤¸à¥\81धारà¥\80।",
+       "nouserspecified": "अहाँक एकटा प्रयोक्तानाम देबऽ पडत।",
        "login-userblocked": "ई प्रयोक्ता प्रतिबन्धित अछि। सम्प्रवेशक अधिकार नै अछि।",
        "wrongpassword": "गलत कूटशब्द देल गेल।\nफेरसँ प्रयास करू।",
        "wrongpasswordempty": "रिक्त कूटशब्द देल गेल।\nफेरसँ प्रयास करू।",
        "passwordtooshort": "कूटशब्द कमसँ कम {{PLURAL:$1|1 वर्ण|$1 वर्णक}} हुअए।",
        "passwordtoolong": "कुटशब्द kuttsabda {{PLURAL:$1|1 वर्ण|$1 वर्णों}} से बेसी नम्हर भ्या सकएत अछि।",
+       "passwordtoopopular": "आम पासवर्ड अहाँ नै चुनि सकएत अछि। कृपया अनोखा पासवर्ड चुनी।",
        "password-name-match": "अहाँक कूटशब्द अहाँक प्रयोक्तानामसँ भिन्न हेबाक चाही।",
        "password-login-forbidden": "ऐ प्रयोक्तानाम आ कूटशब्दक प्रयोग प्रतिबन्धित अछि।",
        "mailmypassword": "नूतन कूटशब्द ई-पत्रसँ पठाउ",
        "emaildisabled": "ई अन्तर्जाल ई-पत्र नै पठाएत।",
        "accountcreated": "खाता खुजि गेल",
        "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|वार्ता]]) के लेल खाता खोलल गेल अछि।",
-       "createaccount-title": "{{अन्तर्जाल}} लेल खाता निर्माण",
+       "createaccount-title": "{{SITENAME}}क लेल खाता बनाबी",
        "createaccount-text": "कियो अहाँक ई-पत्र संकेत लेल एकटा खाता {{अन्तर्जाल}} पर खोललन्हि ($4) नाम भेल \"$2\", कूटशब्द भेल \"$3\"।\nअहाँ सम्प्रवेश करू आ अपन कूटशब्द बदलू।\n\nअहाँ ऐ संदेशकेँ बिसरि सकै छी, जँ ई खाता भ्रमवश बनल हुअए।",
        "login-throttled": "अहाँ ढ़ेर रास सम्प्रवेश प्रयास केलहुँ।\nफेर प्रयास करबासँ पहिने कने काल थम्हू।",
-       "login-abort-generic": "à¤\85हाà¤\81à¤\95 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤¸à¤«à¤² à¤¨à¥\88 à¤­à¥\87ल- à¤\96तम",
+       "login-abort-generic": "à¤\85हाà¤\81à¤\95 à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤¸à¤«à¤² à¤¨à¥\88 à¤­à¥\87ल- à¤°à¥\8bà¤\95ल à¤\97à¤\8fल",
        "login-migrated-generic": "अहाँके खाता माइग्रेट कएल गेल अछि, आर अहाँके प्रयोक्ता नाम आब ई विकिमे नै अछि।",
        "loginlanguagelabel": "भाषा : $1",
        "suspicious-userlogout": "अहाँक निष्क्रमणक अनुरोध नै मानल गेल कारण ई लागल जे ई पुरान गवेषकक लागि वा दोसराइत उपस्मृति द्वारा पठाओल गेल छल।",
        "newpassword": "नव कूटशब्द",
        "retypenew": "नव कूटशब्द फेरसँ टंकित करू",
        "resetpass_submit": "कूटशब्द बनाउ आ सम्प्रवेश करू",
-       "changepassword-success": "à¤\85हाà¤\81à¤\95 à¤\95à¥\82à¤\9fशबà¥\8dद सफलतासँ बदलि देल गेल!",
+       "changepassword-success": "à¤\85हाà¤\81à¤\95 à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड सफलतासँ बदलि देल गेल!",
        "changepassword-throttled": "अहाँ ढ़ेर रास सम्प्रवेश प्रयास केलहुँ।\nफेर प्रयास $1 करबासँ पहिने कने काल थम्हू।",
+       "botpasswords": "बोट पासवर्ड",
+       "botpasswords-disabled": "बोट पासवर्ड अखन निष्क्रिय अछि।",
+       "botpasswords-no-central-id": "बोट पासवर्डक उपयोग करएक लेल अहाँक मुख्य खातासँ प्रवेश करै पडत।",
+       "botpasswords-existing": "वर्तमान बोट पासवर्ड",
+       "botpasswords-createnew": "बोटक लेल नव पासवर्ड बनाबी",
+       "botpasswords-editexisting": "बोटक वर्तमान पासवर्डके बदली",
+       "botpasswords-label-appid": "बोट नाम:",
+       "botpasswords-label-create": "बनाबी",
+       "botpasswords-label-update": "अद्यतन",
+       "botpasswords-label-cancel": "रद्द करी",
+       "botpasswords-label-delete": "मेटाबी",
+       "botpasswords-label-resetpassword": "पासवर्ड पुनः तय करी",
+       "botpasswords-label-grants": "अनुदान आवेदन:",
        "resetpass_forbidden": "कूटशब्द नै बदलल जा सकैए।",
        "resetpass-no-info": "अहाँकेँ ऐ पन्नाकेँ सोझे प्रयोग करबालेल सम्प्रवेशित हुअए पड़त।",
-       "resetpass-submit-loggedin": "à¤\95à¥\82à¤\9fशबà¥\8dद à¤¬à¤¦à¤²à¥\82",
-       "resetpass-submit-cancel": "à¤\96तम à¤\95रà¥\82",
+       "resetpass-submit-loggedin": "à¤\95à¥\82à¤\9fशबà¥\8dद à¤¬à¤¦à¤²à¥\80",
+       "resetpass-submit-cancel": "रदà¥\8dद à¤\95रà¥\80",
        "resetpass-wrong-oldpass": "अमान्य अस्थायी वा अखुनका कूटशब्द।\nअहाँ पहिनहिये सफलतासँ कूटशब्द बदलि लेने छी वा एकटा नव अस्थायी कूटशब्द लेल आग्रह केने छी।",
        "resetpass-recycled": "रीसेट करएके लेल नयाँ कूटशब्दमे कृपया अपन वर्तमान कूटशब्द नै द के नयाँ कूटशब्द देल जाउ।",
        "resetpass-temp-emailed": "अहाँ अखन एकटा अस्थायी ई-पत्र कोड सँ सम्प्रवेशित केनए छी। सम्प्रवेश पूर्ण करए के लेल अहाँ के एतए नयाँ कूटशब्द राखए पडत:",
        "changeemail-oldemail": "अखुनका ई-पत्र संकेत:",
        "changeemail-newemail": "नव ई-पत्र संकेत:",
        "changeemail-none": "(कोनो नै)",
-       "changeemail-password": "à¤\85हाà¤\95à¥\87 {{SITENAME}} कूटशब्द:",
-       "changeemail-submit": "à¤\88-पतà¥\8dर à¤¸à¤\82à¤\95à¥\87त à¤¬à¤¦à¤²à¥\82",
-       "changeemail-throttled": "à¤\85हाà¤\81 à¤¢à¤¼à¥\87र à¤°à¤¾à¤¸ à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤ªà¥\8dरयास à¤\95à¥\87लहà¥\81à¤\81।\nफà¥\87र à¤ªà¥\8dरयास à¤\95रबासà¤\81 à¤ªà¤¹à¤¿à¤¨à¥\87 à¤\95नà¥\87 काल थम्हू।",
+       "changeemail-password": "à¤\85हाà¤\81à¤\95 {{SITENAME}} कूटशब्द:",
+       "changeemail-submit": "à¤\88-मà¥\87ल à¤¬à¤¦à¤²à¥\80",
+       "changeemail-throttled": "à¤\85हाà¤\81 à¤¢à¥\87र à¤°à¤¾à¤¸ à¤¸à¤®à¥\8dपà¥\8dरवà¥\87श à¤ªà¥\8dरयास à¤\95à¥\87लहà¥\81à¤\81।\nफà¥\87र à¤ªà¥\8dरयास à¤\95रबासà¤\81 à¤ªà¤¹à¤¿à¤¨à¥\87 à¤\95नà¥\87 $1 काल थम्हू।",
        "resettokens": "टोकन रीसेट करी",
        "resettokens-text": "जे स्तोक अहाँके खाता सँ सम्बद्ध किछु विशिष्ट व्यक्तिगत जानकारी प्रदान करएत अछि, अहाँ वोकरा एतए सँ रिसेट कऽ सकएत छी।\n\nयदि अहाँ एकरा गलती सँ केकरो देखा देनए छी वा अहाँ के खाता ह्याक भ गेल अछि तहन अहाँके एकरा रिसेट कऽ देना चाही।",
        "resettokens-no-tokens": "रीसेट करवाक लेल कोनो टोकन नै अछि।",
        "token_suffix_mismatch": "'''अहाँक सम्पादन अस्वीकार कऽ देल गेल अछि कारण अहाँक ग्राहक प्रेष्यमान अंक विधानक विराम चेन्ह सभकेँ नष्ट कऽ देलन्हि।'''\nई सम्पादन पन्नाक पाठकेँ दूषित होएबासँ बचेबा लेल अमान्य कऽ देल गेल।\nई कखनो काल होइए जखन अहाँ जाल आधारित अनाम दोसरा लेल चल सेवा प्रयुक्त करै छी।",
        "edit_form_incomplete": "'''सम्पादन आवेदनक किछु भाग वितरक धरि नै पहुँचल; एक बेर फेर देखू जे अहाँक सम्पादन दुरुस्त अछि आ फेरसँ प्रयास करू।'''",
        "editing": "सम्पादन होइए $1",
-       "creating": "$1 à¤¬à¤¨à¤¾à¤\89",
+       "creating": "$1 à¤¬à¤¨à¤¾à¤¬à¥\80",
        "editingsection": "सम्पादन कऽ रहल छी $1 (खण्ड)",
        "editingcomment": "सम्पादन कऽ रहल छी $1 (नव खण्ड)",
        "editconflict": "सम्पादन अन्तर: $1",
        "storedversion": "पेटारमे राखल संशोधन",
        "nonunicodebrowser": "'''चेतौनी: अहाँक गवेषक सार्वत्रिकाक्षरकूट सहयोगी नै अछि।'''\nएकटा अस्थायी-परोक्ष तंत्रांश अहाँकेँ सुरक्षित रूपेँ पन्नाक सम्पादनमे मदति करत: गएर-अस्की अक्षर सभ षोडशमान पद्धतिमे सम्पादन बक्सामे आएत।",
        "editingold": "'''चेतौनी: अहाँ ऐ पन्नाक एकटा पुरान संशोधनक सम्पादन कऽ रहल छी।'''\nजँ अहाँ एकरा संरक्षित करै छी, कोनो संशोधन जे ऐ संशोधनक बाद भेल छै से खतम भऽ जाएत।",
-       "yourdiff": "फराà¤\95",
+       "yourdiff": "à¤\85नà¥\8dतर",
        "copyrightwarning": "कृपा कय बुझू जे सभटा योगदान {{SITENAME}} ई बुझि कय देल जा रहल अछि जे ई निम्नांकितक अंतर्गत अछि $2 (देखू $1 जनकारीक हेतु). जौँ अहाँ चाहैत छी जी अहाँक रचना बिना रोकटोकक संपादित नहि हो किंवा बाँटल नहि जाय, तँ एकर योगदान एतय नहि करू। <br />\nएतय अहाँ ईहो सप्पत खाइत छी जी ई अहाँक अपन रचना छी आकि अहाँ एकरा कोनो सार्वजनिक डोमेन किंवा ओह्ने कोनो मँगनीक संदर्भ-स्थलसँ कॉपी कएने छी।\n< दृढ़> सर्वाधिकार सुरक्षित कार्य एतय नहि दी।!</दृढ़>",
        "copyrightwarning2": "कृपा कऽ बुझू जे सभटा योगदान {{अन्तर्जाल}} योगदानकर्ता द्वारा सम्पादित, बदलल वा हटाएल जा सकैत अछि।. जौँ अहाँ चाहैत छी जी अहाँक रचना बिना रोकटोकक संपादित नहि हो किंवा बाँटल नहि जाय, तँ एकर योगदान एतय नहि करू। <br />\nएतय अहाँ ईहो सप्पत खाइत छी जी ई अहाँक अपन रचना छी आकि अहाँ एकरा कोनो सार्वजनिक डोमेन किंवा ओहने कोनो मँगनीक संदर्भ-स्थलसँ कॉपी कएने छी(देखू $1 वर्णन लेल)।\n''' सर्वाधिकार सुरक्षित कार्य एतय नहि दी।!'''",
        "longpageerror": "'''भ्रम: पाठ जे अहाँ देने छी से $1 किलोबाइट नमगर अछि,  जे अधिकतम आकार $2 किलोबाइट सँ बेशी नमगर अछि।'''\nई संरक्षित नै कएल जा सकत।",
        "edittools": "<!-- एतए देल गेल पाठ सम्पादन आर अपलोड फारम के निचा देखाओल जाएत। -->",
        "edittools-upload": "-",
        "nocreatetext": "{{अन्तर्जाल}} नव पन्ना निर्माणक क्षमताकेँ सीमित कऽ देने अछि।\nअहाँ आपस जा सकै छी आ कोनो पन्नाकेँ सम्पादित कऽ सकै छी, वा [[Special:UserLogin|log in or create an account]]",
-       "nocreate-loggedin": "अहाँकेँ नव पन्ना बनेबाक अधिकार नै अछि।",
-       "sectioneditnotsupported-title": "à¤\96à¤\82ड à¤¸à¤®à¥\8dपादन à¤¸à¤®à¤°à¥\8dथन à¤¨à¥\88",
-       "sectioneditnotsupported-text": "à¤\96à¤\82ड à¤¸à¤®à¥\8dपादनà¤\95 à¤\90 à¤ªà¤¨à¥\8dनापर  à¤¸à¤®à¤°à¥\8dथन à¤¨à¥\88",
+       "nocreate-loggedin": "अहाँक नव पन्ना बनेबाक अधिकार नै अछि।",
+       "sectioneditnotsupported-title": "à¤\85नà¥\81भाà¤\97 à¤¸à¤®à¥\8dपादन à¤¸à¤®à¤°à¥\8dथित à¤¨à¥\88 à¤\85à¤\9bि",
+       "sectioneditnotsupported-text": "à¤\88 à¤ªà¥\83षà¥\8dठ à¤ªà¤° à¤\85नà¥\81भाà¤\97 à¤¸à¤®à¥\8dपादन à¤¸à¤®à¤°à¥\8dथित à¤¨à¥\88 à¤\85à¤\9bि",
        "permissionserrors": "आज्ञा गल्ती",
        "permissionserrorstext": "अहाँके ऐ लेल अनुमति नै अछि, ऐ ले {{PLURAL:$1|कारण|कारण सभ}}:",
        "permissionserrorstext-withaction": "अहाँके अनुमति नै अछि $2 लेल, ऐ लेल {{PLURAL:$1|कारण|कारण सभ}}:",
        "columns": "स्तम्भ सभ",
        "searchresultshead": "ताकू",
        "stub-threshold": "सीमा <a href=\"#\" class=\"stub\">काटल लागि</a> सँचियाएल (अष्टक):",
+       "stub-threshold-sample-link": "उदाहरण",
        "stub-threshold-disabled": "अशक्त कएल",
        "recentchangesdays": "आइ-काल्हिक परिवर्तनमे कतेक दिन देखाएल गेल:",
        "recentchangesdays-max": "बेसीसँ बेसी $1 {{PLURAL:$1|दिन|दिन}}",
        "prefs-help-recentchangescount": "ऐ मे सम्मिलित अछि आइ-काल्हिक परिवर्तन, पन्नाक इतिहास आ वृत्तलेख",
        "prefs-help-watchlist-token2": "इ अहाँके कंक्षाकसूचीके वेब फिडके गोपनीय चाभी छी ।\nइ जे कोइ लंग अछि उ अपन कंक्षाकसूची पैढ सकैत अछि, ऐ लेल इ क्यों गोटा स नै बाटब ।\n[[Special:ResetTokens|एकरा रीसेट करवाक लेल यै ठाम क्लिक करु]]।",
        "savedprefs": "अहाँक पसिन्न सुरक्षित कएल गेल",
+       "savedrights": "प्रयोक्ता {{GENDER:$1|$1}}क सदस्य अधिकार सङ्ग्रह कएल गेल।",
        "timezonelegend": "समय क्षेत्र",
        "localtime": "स्थानीय समए:",
        "timezoneuseserverdefault": "पूर्वनिर्धारित वितरक प्रयुक्त करू ($1)",
        "prefs-reset-intro": "अहाँ ऐ पन्नाक प्रयोग अपन विकल्पकेँ पूर्वनिविष्ट रूपेँ जाल पुनर्निधारित करबा लेल कऽ सकै छी।\nई बदलल नै जा सकैए।",
        "prefs-emailconfirm-label": "ई-पत्र पुष्टि:",
        "youremail": "ई-पत्र:",
-       "username": "प्रयोक्तानाम:",
-       "prefs-memberingroups": "{{PLURAL:$1|संवर्ग|संवर्ग सभ}}:एकर सदस्य",
+       "username": "{{GENDER:$1|प्रयोगकर्तानाम}}:",
+       "prefs-memberingroups": "निम्नलिखित {{PLURAL:$1|समूह|समूहसभ}}क {{GENDER:$2|सदस्य}}:",
        "prefs-memberingroups-type": "$1",
        "prefs-registration": "पंजीकरणक समए:",
        "prefs-registration-date-time": "$1",
        "badsig": "अमान्य प्रारम्भिक पहिचान।\nएच.टी.एम.एल.चेन्ह जाँचू।",
        "badsiglength": "अहाँक हस्ताक्षर बड्ड पैघ अछि।\nई $1 सँ बेसी नै हेबाक चाही {{PLURAL:$1|वर्ण|वर्ण}} पैघ।",
        "yourgender": "पुरुख आकि स्त्री",
-       "gender-unknown": "à¤\85à¤\9cà¥\8dà¤\9eात",
+       "gender-unknown": "à¤\85हाà¤\81à¤\95 à¤µà¤°à¥\8dणन à¤\95रà¥\88त à¤¸à¤®à¤¯, à¤\9cतà¥\87à¤\95धरि à¤¸à¤®à¥\8dभव à¤¹à¥\8bà¤\8fत à¤¸à¤«à¥\8dà¤\9fवà¥\87यर à¤²à¤¿à¤\99à¥\8dà¤\97 à¤¤à¤\9fसà¥\8dथ à¤¶à¤¬à¥\8dदसभà¤\95 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रत",
        "gender-male": "पुरुख",
        "gender-female": "स्त्री",
        "prefs-help-gender": "वैकल्पिक: तंत्रांश द्वारा लिंग निरपेक्ष सम्बोधन लेल प्रयुक्त।\nई सूचना सार्वजनिक हएत।",
        "userrights": "प्रयोक्ता अधिकारक प्रबन्धन",
        "userrights-lookup-user": "प्रयोक्ता संवर्ग सभक प्रबन्ध करू",
        "userrights-user-editname": "एकटा प्रयोक्तानाम लिखू:",
-       "editusergroup": "प्रयोक्ता संवर्ग सभक सम्पादन करू",
-       "editinguser": "पà¥\8dरयà¥\8bà¤\95à¥\8dताà¤\95 à¤ªà¥\8dरयà¥\8bà¤\95à¥\8dता à¤\85धिà¤\95ार à¤¬à¤¦à¤²à¤¬ '''[[User:$1|$1]]''' $2",
+       "editusergroup": "{{GENDER:$1|सदस्य}} समूहसभक सम्पादन करी",
+       "editinguser": "सदसà¥\8dय '''[[User:$1|$1]]''' $2 à¤\95 à¤\85धिà¤\95ार à¤¬à¤¦à¤²à¤¿\n{{GENDER:$1|सदसà¥\8dय}}à¤\95 à¤¸à¤¦à¤¸à¥\8dय à¤\85धिà¤\95ार à¤¬à¤¦à¤²à¤² à¤\9cा à¤°à¤¹à¤² à¤\85à¤\9bि <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "प्रयोक्ता संवर्ग सभक सम्पादन करू",
-       "saveusergroups": "प्रयोक्ता संवर्ग सभकेँ सुरक्षित करू",
+       "saveusergroups": "{{GENDER:$1|सदस्य}} समूह सङ्ग्रह करी",
        "userrights-groupsmember": "क सदस्य:",
        "userrights-groupsmember-auto": "क जानल सदस्य:",
        "userrights-groups-help": "अहाँ ऐ प्रयोक्ताक वर्गकेँ बदलि सकै छी:\n* एकटा निशान लगाएल बक्सा माने प्रयोक्ता ओइ वर्गमे अछि।\n* एकटा बिन निशान लगाएल माने प्रयोक्ता ओइ वर्गमे नै अछि।\n* ई * देखबैए जे अहाँ वर्गकेँ एक बेर देलाक बाद हटा नै सकै छी, आ एकर उलट सेहो ठीक अछि।",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "प्रयोक्ता अधिकार बदलावक समयमे अंतर्विरोध! कृपया अपन बदलाव जाँच करु आ पुनः सुनिश्चित करु।",
        "userrights-removed-self": "अहाँ सफलतापूर्वक अपन अधिकार हटा देने छी। अतः अहाँ आब ई पृष्ठ नै देख सकैत छी।",
-       "group": "वरà¥\8dà¤\97:",
-       "group-user": "प्रयोक्ता सभ",
+       "group": "समà¥\82ह:",
+       "group-user": "प्रयोक्तासभ",
        "group-autoconfirmed": "स्वतःअनुमोदित प्रयोक्ता सभ",
        "group-bot": "स्वचालक",
-       "group-sysop": "माà¤\87नà¤\9cन",
+       "group-sysop": "पà¥\8dरबनà¥\8dधà¤\95",
        "group-bureaucrat": "अधिकारी",
-       "group-suppress": "नà¤\9cरिपर à¤¨à¥\88 à¤\86à¤\8fल",
+       "group-suppress": "नà¥\81à¤\95ाबà¤\8f à¤µà¤¾à¤²à¤¾",
        "group-all": "(सभ)",
        "group-user-member": "{{लिंग:$1|प्रयोक्ता}}",
        "group-autoconfirmed-member": "{{लिंग:$1|स्वतःअनुमोदित प्रयोक्ता}}",
        "group-bot-member": "{{लिंग:$1|स्वचालक}}",
        "group-sysop-member": "{{लिंग:$1|माइनजन}}",
        "group-bureaucrat-member": "{{लिंग:$1|अधिकारी}}",
-       "group-suppress-member": "{{लिंग:$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}}:नà¤\9cरिपर à¤¨à¥\88 à¤\86à¤\8fल",
+       "grouppage-suppress": "{{ns:project}}:नà¥\81à¤\95ाबà¥\80",
        "right-read": "पन्ना सभ पढ़ू",
        "right-edit": "पन्ना सभ सम्पादन करू",
        "right-createpage": "पन्ना सभ बनाउ (जे वार्ता पन्ना नै हुअए)",
        "right-createtalk": "वार्ता पन्ना सभ बनाउ",
        "right-createaccount": "नव प्रयोक्ता खाता सभ बनाउ",
+       "right-autocreateaccount": "बाहरी खातासँ स्वतः प्रवेश",
        "right-minoredit": "सम्पादन सभकेँ मामूली चिन्हित करू",
        "right-move": "पन्ना सभ घसकाउ",
        "right-move-subpages": "पन्ना सभकेँ उपपन्ना सभक संग घसकाउ",
        "right-managechangetags": "डेटाबेस से [[Special:Tags|नुकाबू]] बनाबु आर हटाबु",
        "right-applychangetags": "प्रयोग में लाबू [[Special:Tags|tags]] कक्रो बदलाव के साथ।",
        "right-changetags": "जमा करु आर हटाबु स्वतंत्र [[Special:Tags|टैग]] व्यक्तिगत अवतरण आर लॉग प्रविक्ति पे",
+       "grant-generic": "\"$1\" अधिकार सङ्ग्रह",
+       "grant-group-page-interaction": "पृष्ठसभसँ जोडी",
+       "grant-group-file-interaction": "मिडियासँ जोडी",
        "newuserlogpage": "प्रयोक्ता रचना वृत्तलेख",
        "newuserlogpagetext": "ई प्रयोक्ता निर्माणक वृत्तलेख अछि।",
        "rightslog": "प्रयोक्ता अधिकार वृत्तलेख",
        "recentchanges-label-bot": "ई सम्पादन यांत्रिक छल।",
        "recentchanges-label-unpatrolled": "ऐ सम्पादनक पुनरीक्षण अखन धरि नै कएल गेल अछि।",
        "recentchanges-label-plusminus": "पन्नाके आकार इ बाइट संख्यासे बदलल गेल",
-       "recentchanges-legend-heading": "<strong>à¤\95à¥\81à¤\82जी:</strong>",
+       "recentchanges-legend-heading": "<strong>à¤\95à¥\81à¤\9eà¥\8dजी:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|नयाँ पन्नसभके सूची]] सहो देखु)",
        "rcnotefrom": "नीचाँमे '''$2''' सँ भेल परिवर्तन अछि ('''$1''' धरि देखाएल)।",
        "rclistfrom": "$3 $2 सँ शुरू भेल नव परिवर्तन देखू",
        "upload-copy-upload-invalid-domain": "कपि अपलोड इ डोमेन स उपलब्ध नै अछि।",
        "upload-dialog-title": "फाइल अपलोड करी",
        "upload-dialog-button-cancel": "रद्द करी",
+       "upload-dialog-button-done": "पूर्ण भएल",
+       "upload-dialog-button-save": "सङ्ग्रह करी",
+       "upload-dialog-button-upload": "उपारोपण",
+       "upload-form-label-infoform-title": "विवरण",
+       "upload-form-label-infoform-name": "नाम",
+       "upload-form-label-infoform-description": "विवरण",
+       "upload-form-label-usage-title": "उपयोग",
+       "upload-form-label-usage-filename": "फाइलक नाम",
+       "foreign-structured-upload-form-label-own-work": "ई हमर काज छी",
+       "foreign-structured-upload-form-label-infoform-categories": "श्रेणीसभ",
+       "foreign-structured-upload-form-label-infoform-date": "दिनाङ्क",
        "backend-fail-stream": "\"$1\" केँ नै स्ट्रिम क सकल।",
        "backend-fail-backup": "\"$1\" केँ नै ब्याकअप क सकल।",
        "backend-fail-notexists": "फाइल $1 नै अछि।",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|सुधार|सुधार सभ}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|सुधार|सुधार सभ}} $2 सँ",
        "javascripttest": "जावास्क्रिप्ट परिक्षण",
-       "javascripttest-pagetext-noframework": "इ पृष्ठ जावास्क्रिप्ट परीक्षण चलावए के लेल अछि।",
-       "javascripttest-pagetext-unknownframework": "अज्ञात परीक्षण ढाँचा \"$1\"",
        "javascripttest-pagetext-unknownaction": "अज्ञात क्रिया \"$1\" ।",
-       "javascripttest-pagetext-frameworks": "कृपया निम्न परीक्षण ढाँचा सभ में सँ एक चुनु: $1",
-       "javascripttest-pagetext-skins": "परीक्षण करए के लेल त्वचा चुनु:",
        "javascripttest-qunit-intro": "mediawiki.org पर [$1 परीक्षण के प्रलेखन] देखु।",
        "tooltip-pt-userpage": "{{GENDER:|अहाँक प्रयोगकर्ता}} पृष्ठ",
        "tooltip-pt-anonuserpage": "सम्पाद्न कएल जा रहल स्थानक  अनिकेतक प्रयोक्ता पन्ना",
        "version-libraries-library": "लाइब्रेरी",
        "version-libraries-version": "संस्करण",
        "redirect": "अनुप्रेषित करु फ़ाइल, प्रयोगकर्ता, वा संशोधन पहीचान के आधार में",
-       "redirect-legend": "फ़ाइल अथवा पन्ना के पुनर्प्रेषण",
        "redirect-summary": "ई विशेष पन्ना फ़ाइलनाम प्रदान करै पे फ़ाइल नाम के, पन्न आइ॰दी अथवा अवतरण आइ॰दी दुनु पे पन्ना के,आर साथी सदस्य आइ॰दी दुनु पे सदस्य पन्ना के पुनर्प्रेषित करएत अछि । उदाहरण: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], या [[{{#Special:Redirect}}/user/101]]।",
        "redirect-submit": "जाऊ",
        "redirect-lookup": "ताकू:",
index b14772c..7468ee4 100644 (file)
        "sort-descending": "Fandaharana miiba",
        "sort-ascending": "Fandaharana miabo",
        "nstab-main": "Lahatsoratra",
-       "nstab-user": "Pejy ny mpikambana",
+       "nstab-user": "Pejim-pikambana",
        "nstab-media": "Pejy sary sy/na feo",
        "nstab-special": "Pejy Manokana",
        "nstab-project": "Tetikasa",
        "missingcommentheader": "'''Fampahatsiahivana :''' Tsy nampiditra lohateny amin'ity resaka ity ianao.\nRaha tsindrianao indray eo amin'ny « {{MediaWiki:Savearticle}} » ho voatahiry tsy misy lohateny ny fanovananao.",
        "summary-preview": "Topi-maso n'ilay ambangovangony :",
        "subject-preview": "Topi maso ny lazaina :",
+       "previewerrortext": "Nisy hadisoana nitranga tamin'ny fanandramana namoaka topi-mason'ny fanovanao",
        "blockedtitle": "Mpikambana voasakana",
        "blockedtext": "'''Voasakana ny solonanaranao na ny adiresy IP anao.'''\n\nNataon'i $1 ny fisakanana.\nNy antony : ''$2''.\n\n* Fanombohan'ilay fisakanana : $8\n* Farany : $6\n* Kaonty voasakana : $7.\n\nAfaka antsoinao i $1 na [[{{MediaWiki:Grouppage-sysop}}|ny mpandrindra]] mba hiresaka mombamomba n'izany.\nAfaka andefasanao imailaka ra nampiditra ny adiresy imailakanao ianao ao anatin'ny [[Special:Preferences|mombamombanao]].\n'''$3''' ny adiresy IP-nao ary ny ''identifiant de blocage''-nao dia #$5.\nAsio ao anaty ny fangatahanao io adiresy io.",
        "autoblockedtext": "Voasakana ny adiresy IP anareo satria nampiasain'ny olon-kafa io adiresy ampiasainao io. Ary voasakan'i $1 ilay olona nampiasa ny adiresinao.<br />\nIty ny antony navoakany\n\n:''$2''\n\n* nanomboka tamin'ny $8 ilay fisakanana\n* Amin'ny $6 ilay fisakanana no mijanona\n* $7 no anaran'ilay kaonty voasakana\n\nAfaka antsoinao i $1 na miantso ny [[{{MediaWiki:Grouppage-sysop}}|mpandrindra]] mba hiresaka momba ny fanakananao.\n\nJereo koa fa tsy afaka mampiasa ny asa ''emailuser'' ianao ra tsy nanometraka ny adiresy imailakao anatin'ny [[Special:Preferences|safidinao]]. Jereo koa ra tsy nesorinao ny asa ''emailuser''.\n\n$3 izao ny adiresinao, ary ny isa ny fisakananai dia $5.\nSoraty ireo fanoroana ireo anatin'ny fangatahana ataonao.",
        "previewnote": "'''Fantaro fa topi-maso fotsiny ity.'''\nMbola tsy voatahiry ny fanovanao !",
        "continue-editing": "Hanohy ny fanovàna",
        "previewconflict": "\nIty topi-maso ity no mifanaraka amin'ny lahatsoratra ao amin'ny faritra eo ambony,\nary toy izao no ho fisehon'ny pejy raha misafidy ny hitahiry azy ianao.",
-       "session_fail_preview": "'''Tsy afaka tahirizina ny fanovanao noho ny haverezan'ny fampahalalàna mikasikan'ny fidiranao. Andramo fanindroany azafady.\nRaha mbola tsy mandeha foana dia [[Special:UserLogout|mivoaha]] amin'ny kaontinao ary miverena miditra.'''",
+       "session_fail_preview": "Miala tsiny indrindra fa tsy afaka nandraikitra ny fiovanao izahay noho ny fahaverezana fampahalalana mikasika ny fidiranao teto.\n\nMety nivoaka ianao. <strong>Jereo raha mbola tafiditra ianao, ary avereno indray</strong>\nRaha tsy mbola mandeha izany, dia [[special:Userlogout|mivoaha]] amin'ny kaontinao ary midira indray, ary jereo raha manaiky cookies avy amin'ity tranonkala ity ny mpitety tranonkalanao.",
        "session_fail_preview_html": "'''Tsy afaka tehirizinay ny fanovanao noho ny haverezan'ny fampahalalàna momba ny session-nao.\n\n'''Satria nalefan'i {{SITENAME}} HTML tsotra, nasitrika ny topi-paso mba tsy hisy fanafihana atao amin'ny Javascript.\n\n'''Raha ara-dalàna ny fanovanao, avereno.'''\nRaha mbola tsy mandeha foana ilay izy, [[Special:UserLogout|mivoaha]] ary midira",
        "token_suffix_mismatch": "'''Tsy nekena ny fanovanao satria tsy voakaodin'ny rindrankajinao tsara ny soratra tao anatin'ny identifiant de modification.'''\nNilaina io tsy fanekena io mba tsy hikatso ilay pejy.\nMisy io olana io rehefa mamppiasa serveur mandataire tsy manana anarana sy manan-olana eo amin'ny tranonkala ianao.",
        "edit_form_incomplete": "'''Misy tsy tonga tany amin'ny lohamilina ny singan'ity pejy fenoina ity. Azonao ampiana ny mpandika hafa amin'ny famoronana ny fanazavana ity pejy ity.",
        "mergehistory-empty": "tsy misy version azo hatambarana",
        "mergehistory-done": "{{PLURAL:$3|}}Versiona $3 an'i $1 no natsonika tamin'ny [[:$2]]",
        "mergehistory-fail": "Tsy afaka manatambatra ny tantara(n'asa). Avereno checheo ny pejy sy ny daty.",
+       "mergehistory-fail-bad-timestamp": "Tsy ekena ny daty sy ora.",
+       "mergehistory-fail-invalid-source": "Tsy ekena ny pejy loharano.",
+       "mergehistory-fail-invalid-dest": "Tsy ekena ny pejy tanjona.",
+       "mergehistory-fail-permission": "Zo tsy ampy amin'ny fampiraisana tantaram-pejy.",
+       "mergehistory-fail-self-merge": "Mitovy ny pejy loharano sy tanjona.",
        "mergehistory-no-source": "Tsy misy ny pejy avy amin'ny $1.",
        "mergehistory-no-destination": "Tsy misy ilay pejy tanjona $1.",
        "mergehistory-invalid-source": "Tokony manana lohateny azo ampiasaina ny pejy fiavina",
        "columns": "Tsanganana/Tioba :",
        "searchresultshead": "Fikarohana",
        "stub-threshold": "Fetra ambony ho an'i <a href=\"#\" class=\"stub\">rohim-bangovango</a> (oktety):",
+       "stub-threshold-sample-link": "santiôna",
        "stub-threshold-disabled": "Tsy alefa",
        "recentchangesdays": "Isan'ny andro ho aseho amin'ny fiovana farany:",
        "recentchangesdays-max": "($1 andro{{PLURAL:$1||}} fara-faha betsany)",
        "prefs-help-recentchangescount": "Misy ny fiovana farany, ny tantaram-pejy ary ny laogy",
        "prefs-help-watchlist-token2": "Ity ny lakilen'ny topaka Web ny lisitra arahanao. Afaka mamangy ny lisitra arahanao izay mahalala io lakileo io, ka aza zarazaraina ilay izy. Raha ilainao izany dia afaka [[Special:ResetTokens|manavao izy io ianao]]",
        "savedprefs": "Voatahiry ny mombamomba anao.",
+       "savedrights": "Voatahiry soa aman-tsara ny zom-pikambana ho an'i {{GENDER:$1|$1}}.",
        "timezonelegend": "Faritr'ora :",
        "localtime": "Ora an-toerana",
        "timezoneuseserverdefault": "Sanda tsipalotry ny wiki ($1)",
        "userrights": "Fandrindràna ny fahefahan'ny mpikambana",
        "userrights-lookup-user": "Handrindra vondrom-pikambana",
        "userrights-user-editname": "Manomeza solonanarana:",
-       "editusergroup": "Hanova satan'ny mpikambana",
-       "editinguser": "Fanovana ny zon'ny mpikambana '''[[User:$1|$1]]''' $2",
+       "editusergroup": "Hanova satan'ny {{GENDER:$1|}}mpikambana",
+       "editinguser": "Fanovana ny zon'ny mpikambana <strong>{{GENDER:$1|}}[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Hanova vondrom-pikambana",
-       "saveusergroups": "Tehirizo ny vondrom-pikambana",
+       "saveusergroups": "{{GENDER:$1|}}Tehirizo ny vondrom-pikambana",
        "userrights-groupsmember": "Mpikambana amin'ny vondrona:",
        "userrights-groupsmember-auto": "Mpikambana tsy dia voalazan'i :",
        "userrights-groups-help": "Azonao atao ny manova ny vondrona isian'ity mpikambana ity.\n* Ny boaty voa-\"check\" dia midika fa ao amin'io vondrona io ilay mpikambana.\n* Ny boaty tsy voa-\"check\" dia midika fa tsy ao amin'io vondrona io ilay mpikambana.\n* Ny * dia fa tsy azonao esorina amin'ilay vondrona nampianao/nesorinao ilay mpikambana.",
        "userrights-changeable-col": "Ny gropy azonao ovaina",
        "userrights-unchangeable-col": "Ny gropy tsy azonao ovaina",
        "userrights-conflict": "Fifandonana fanovana zom-pikambana! Avereno vakiana ary marino ny fanovanao.",
-       "userrights-removed-self": "Afakao soa aman-tsara ny zonao. Noho izany, tsy afaka mijery amin'ilay pejy intsony ianao.",
+       "userrights-removed-self": "Nanala ny zonao ianao. Noho izany dia tsy afaka mitsidika ity pejy ity intsony ianao.",
        "group": "Gropy :",
        "group-user": "Mpikambana",
        "group-autoconfirmed": "Mpikambana voamarina",
        "group-bot": "Mpikambana rôbô",
        "group-sysop": "Mpandrindra",
        "group-bureaucrat": "Borôkraty",
-       "group-suppress": "Mpitondra",
+       "group-suppress": "Mpametra",
        "group-all": "(izy rehetra)",
        "group-user-member": "{{GENDER:$1|mpikambana}}",
        "group-autoconfirmed-member": "{{GENDER:$1|Mpikambana voamarina ho azy}}",
        "group-bot-member": "{{GENDER:$1|Mpikambana rôbô}}",
        "group-sysop-member": "{{GENDER:$1|Mpandrindra}}",
        "group-bureaucrat-member": "{{GENDER:$1|Borôkraty}}",
-       "group-suppress-member": "{{GENDER:$1|Mpitondra}}",
+       "group-suppress-member": "{{GENDER:$1|mpamafa}}",
        "grouppage-user": "{{ns:project}}:Mpikambana",
        "grouppage-autoconfirmed": "{{ns:project}}:Mpikambana Voamafy",
        "grouppage-bot": "{{ns:project}}:Mpikambana rôbô",
        "grouppage-sysop": "{{ns:project}}:Mpandrindra",
        "grouppage-bureaucrat": "{{ns:project}}:Borôkraty",
-       "grouppage-suppress": "{{ns:project}}:Oversight",
+       "grouppage-suppress": "{{ns:project}}:Mpamafa",
        "right-read": "Mamaky ny pejy",
        "right-edit": "Manova ny pejy",
        "right-createpage": "Manamboatra pejy (tsy pejin-dresaka)",
        "right-createtalk": "Mamorona pejin-dresaka",
        "right-createaccount": "Manamboatra kaonty",
+       "right-autocreateaccount": "Hiditra ho azy miaraka amina kaontim-pikambana ivelany",
        "right-minoredit": "Marihana ho fanovana madinika",
        "right-move": "Manakisaka pejy",
        "right-move-subpages": "Manakisaka pejy miarak'amin'ny zana-pejiny",
        "right-sendemail": "Mandefa imailaka any amin'ny mpikambana hafa",
        "right-passwordreset": "Hijery ny imailaka famerenana ny tenimiafina",
        "right-managechangetags": "Mamorona ary mamafa [[Special:Tags|balizy]] ao amin'ny banky angona",
+       "grant-generic": "\"$1\" vondron-jo",
+       "grant-group-page-interaction": "Mifanakalo amin'ny pejy",
+       "grant-group-file-interaction": "Mifanakalo amin'ny hainoamanjery",
+       "grant-group-watchlist-interaction": "Mifanakalo amin'ny lisitry ny pejy arahanao",
+       "grant-group-email": "Mandefa mailaka",
+       "grant-group-high-volume": "Manao zavatra haingana",
+       "grant-group-administration": "Hanao asam-pandrindrana",
+       "grant-group-other": "Manao hetsika maro samihafa",
+       "grant-blockusers": "Manakana sy manala sakan'ny mpikambana",
+       "grant-createaccount": "Hamorona kaonty",
+       "grant-createeditmovepage": "Mamorona, manova, ary manisaka pejy",
+       "grant-delete": "Mamafa pejy, versiona ary iditry ny laogy",
+       "grant-editinterface": "Manova ny CSS/Javascript an'ny mpikambana ary anaran-tsehatra MediaWiki",
+       "grant-editmycssjs": "Manova CSS/Javascript anao",
+       "grant-editmyoptions": "Hanova ny safidim-pikambanao",
+       "grant-editmywatchlist": "Manova ny lisitry ny pejy arahana",
+       "grant-editpage": "Manova ny pejy efa misy",
+       "grant-editprotected": "Manova ny pejy voaaro",
+       "grant-highvolume": "Manova pejy ambongadiny",
+       "grant-oversight": "Manafina mpikambana ary mamafa versiona",
+       "grant-patrol": "Manamarika ireo fiovam-pejy ho voatsidika",
+       "grant-protect": "Miaro ary manala ny fiavoram-pejy",
+       "grant-rollback": "Mamafa fiovana amin'ny pejy",
+       "grant-sendemail": "Mandefa mailaka amin'ny mpikambana hafa",
+       "grant-uploadeditmovefile": "Manondrana, manova ary manisaka rakitra",
+       "grant-uploadfile": "Mampiditra rakitra vaovao",
+       "grant-basic": "Zo fototra",
+       "grant-viewdeleted": "Mitsidika ireo rakitra ary pejy voafafa",
+       "grant-viewmywatchlist": "Hijery ny lisitry ny pejy arahanao",
        "newuserlogpage": "Laogim-panokafana kaontim-pikambana",
        "newuserlogpagetext": "Ity pejy ity dia maneho ny tantaran'asan'ny fampidirana mpikambana vaovao.",
        "rightslog": "Laogim-piovan'ny zom-pikambana",
        "action-createpage": "hanao pejy",
        "action-createtalk": "hanao pejin-dresaka",
        "action-createaccount": "amboary io kaontim-pikambana io",
+       "action-autocreateaccount": "foronina ho azy io kaontim-pikambana ivelany io",
        "action-history": "hijery ny tantaran'ity pejy ity",
        "action-minoredit": "Mariho ho kely ity fanovana ity",
        "action-move": "hamindra io pejy io",
        "recentchanges-label-plusminus": "IO ny isan'ny oktety niova tamin'ilay pejy",
        "recentchanges-legend-heading": "<strong>Maribolana:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (jereo koa ny [[Special:NewPage|lisitry ny pejy vaovao]])",
+       "recentchanges-submit": "Aseho",
        "rcnotefrom": "Eo ambany dia ahitana ireo fiovana{{PLURAL:$5}} hatry ny <strong>$3, $4</strong> (naseho hatramin'ny <strong>$1</strong>).",
        "rclistfrom": "Asehoy izay vao niova manomboka ny $3 $2",
        "rcshowhideminor": "$1 ny fanovàna kely",
        "rcshowhidemine": "$1 ny fanovàko",
        "rcshowhidemine-show": "Haneho",
        "rcshowhidemine-hide": "Hanafina",
+       "rcshowhidecategorization": "$1 ny fisokajiam-pejy",
+       "rcshowhidecategorization-show": "Aseho",
+       "rcshowhidecategorization-hide": "Afenina",
        "rclinks": "Asehoy ny $1 niova farany tato anatin'ny $2 andro<br />$3",
        "diff": "Fampitahana",
        "hist": "tant.",
        "recentchangeslinked-summary": "Mampiseho ny fanovàna vao haingana ity pejy manokana ity. Voasoratra amin'ny '''sora-matavy''' ny lohaten'ny [[Special:Watchlist|pejy arahinao-maso]].",
        "recentchangeslinked-page": "anaram-pejy :",
        "recentchangeslinked-to": "Ampisehoy ny fanovàn'ny pejy misy rohy makany amin'ny pejy fa tsy atao mivadika",
+       "recentchanges-page-added-to-category": "Nampiana tamin'ny sokajy [[:$1]]",
+       "recentchanges-page-removed-from-category": "Nesorina tamin'ny sokajy i [[:$1]]",
+       "autochange-username": "Fiovàna vita ho azy MediaWiki",
        "upload": "Handefa rakitra",
        "uploadbtn": "Alefaso ny rakitra",
        "reuploaddesc": "Miverena any amin'ny fisy fandefasan-drakitra.",
        "upload-form-label-infoform-description": "Famisavisana",
        "upload-form-label-usage-title": "Fampiasana",
        "upload-form-label-usage-filename": "Anaran-drakitra",
+       "foreign-structured-upload-form-label-own-work": "Asako ity",
+       "foreign-structured-upload-form-label-infoform-categories": "Sokajy",
+       "foreign-structured-upload-form-label-infoform-date": "Daty",
        "backend-fail-stream": "Tsy afaka mamaky ilay rakitra $1.",
        "backend-fail-backup": "Tsy afaka mitahiry ilay rakitra $1.",
        "backend-fail-notexists": "Tsy misy ilay rakitra $1.",
        "mostrevisions": "Lahatsoratra niova im-betsaka indrindra",
        "prefixindex": "Pejy manomboka amin'ny...",
        "prefixindex-namespace": "Ny pejy rehetra mitondra ny tovona (anaran-tsehatra $1)",
+       "prefixindex-submit": "Aseho",
+       "prefixindex-strip": "Hanala ny tovona anaty lisitra",
        "shortpages": "Pejy fohy",
        "longpages": "Pejy lavabe",
        "deadendpages": "Pejy tsy mirohy",
        "protectedpages-performer": "Fiarovana ny mpikambana",
        "protectedpages-params": "Parametatry ny fiavorana",
        "protectedpages-reason": "Antony",
+       "protectedpages-submit": "Haneho pejy",
        "protectedpages-unknown-timestamp": "Tsy fantatra",
        "protectedpages-unknown-performer": "Mpikambana tsy fantatra",
        "protectedtitles": "Lohateny voaaro",
        "protectedtitlesempty": "Tsy misy lohateny voaaro miaraka amin'ireo mpihazaka ireo.",
+       "protectedtitles-submit": "Lohateny aseho",
        "listusers": "Lisitry ny mpikambana",
        "listusers-editsonly": "Ny mpikambana manam-pandraisan'anjara ihany no aseho",
        "listusers-creationsort": "Afantina amin'ny daty fanokafana",
        "usereditcount": "fanovana $1 {{PLURAL:}}",
        "usercreated": "Noforonina ny {{GENDER:$3}} $1 tamin'ny $2",
        "newpages": "Pejy vaovao",
+       "newpages-submit": "Aseho",
        "newpages-username": "Solonanarana:",
        "ancientpages": "Ireo pejy tranainy indrindra",
        "move": "Hamindra azy toerana",
        "querypage-disabled": "Tsy ampiasaina ity pejy manokana ity mba hitsitsy ny solosaina",
        "apihelp": "Fanoroana API",
        "apihelp-no-such-module": "Tsy hita ny joro \"$1\".",
+       "apisandbox": "Kianjam-pasika API",
+       "apisandbox-jsonly": "Ilaina amin'ny fampiasana kianjam-pasika API ny JavaScript.",
+       "apisandbox-api-disabled": "Tsy alefa amin'ity tranonkala ity ny API.",
+       "apisandbox-fullscreen": "Hanitatra solaitra",
+       "apisandbox-unfullscreen": "Haneho pejy",
+       "apisandbox-submit": "Hanao hataka",
+       "apisandbox-reset": "Diovina",
+       "apisandbox-retry": "Andramana indray",
+       "apisandbox-helpurls": "Rohim-panoroana",
+       "apisandbox-examples": "Ohatra",
+       "apisandbox-dynamic-parameters": "Parametatra miampy",
+       "apisandbox-dynamic-parameters-add-label": "Hanampy parametatra:",
+       "apisandbox-dynamic-parameters-add-placeholder": "Anaram-parametatra",
+       "apisandbox-dynamic-error-exists": "Efa misy parametatra mitondra ny anarana \"$1\".",
+       "apisandbox-deprecated-parameters": "Parametatra tola",
+       "apisandbox-fetch-token": "Fenoina ho azy ny token",
+       "apisandbox-submit-invalid-fields-title": "Misy saha tsy azo raisina",
+       "apisandbox-results": "Valiny",
+       "apisandbox-sending-request": "Mandefa hataka API...",
+       "apisandbox-loading-results": "Mandray valiny API...",
+       "apisandbox-results-error": "Nisy hadisoana tamin'ny fakàna ny valin-kataka API: $1.",
+       "apisandbox-request-url-label": "Hataka URL:",
+       "apisandbox-request-time": "Fotoana nangatahana{{PLURAL:$1|$1 ms}}",
+       "apisandbox-results-fixtoken": "Ahitsio ny token ary alefaso indray",
+       "apisandbox-results-fixtoken-fail": "Tsy afaka naka ny token \"$1\".",
+       "apisandbox-alert-page": "Tsy ekena ny votoatin'ny saha ato amin'ity pejy ity.",
        "booksources": "boky tsiahy",
        "booksources-search-legend": "hikaroka anatin'ny boky todika",
        "booksources-search": "Fikarohana",
        "specialloguserlabel": "Mpikambana nanao :",
        "speciallogtitlelabel": "Tanjona (lohateny na mpikambana) :",
        "log": "Tatitr’asa",
+       "logeventslist-submit": "Aseho",
        "all-logs-page": "Laogy rehetra",
        "alllogstext": "Seho nakambana ho an'ny laogy rehetra azo jerena eto amin'ny {{SITENAME}}.\nAzonao ferana ny fahitana ny tao amin'ny fisafidianana karazana laogy iray, anaram-pikambana iray na pejy iray (samihafa ny sorabaventy sy soramadinika).",
        "logempty": "Tsy nahitana.",
        "log-title-wildcard": "Hitady amin'ny lohateny manomboka amin'io soratra io",
        "showhideselectedlogentries": "Haneho/Hanafina ny iditry ny laogy nofidiana",
+       "checkbox-select": "Hifidy: $1",
+       "checkbox-all": "Rehetra",
+       "checkbox-none": "Tsy misy",
+       "checkbox-invert": "Avadika",
        "allpages": "Pejy rehetra",
        "nextpage": "Pejy manaraka ($1)",
        "prevpage": "Pejy taloha ($1)",
        "allpages-bad-ns": "{{SITENAME}} dia tsy manana anaran-tsehatra mitondra anarana « $1 ».",
        "allpages-hide-redirects": "Haneho ny fihodinana",
        "cachedspecial-viewing-cached-ttl": "Mijery pejy anaty takona ianao, izay namboarina $1 taona lasa.",
+       "cachedspecial-viewing-cached-ts": "Mijery versiôna voatakon'ity pejy ity ianao, izay mety efa tsy mitaratra ny zava-misy ankehitriny intsony.",
        "cachedspecial-refresh-now": "Hijery ny farany indrindra",
        "categories": "Sokajy",
+       "categories-submit": "Aseho",
        "categoriespagetext": "{{PLURAL:$1}}Ampiasain'ny rakitra na pejy ireo sokajy manaraka ireo.\nTsy hiseho eto ny [[Special:UnusedCategories|sokajy tsy miasa]].\nVangio koa ny [[Special:WantedCategories|sokajy ilaina]].",
        "categoriesfrom": "Haneho ny sokajy manomboka amin'ny :",
        "special-categories-sort-count": "afantina amin'ny isan-javatra",
        "activeusers-hidebots": "Asitriho ny robo",
        "activeusers-hidesysops": "Asitriho ny mpandrindra",
        "activeusers-noresult": "Tsy nahitana mpikambana.",
+       "activeusers-submit": "Hanseho ny mpikambana mavitrika",
        "listgrouprights": "Fahefan'ny vondrom-pikambana",
        "listgrouprights-summary": "Ity pejy ity dia ahitana ny lisitry ny vondrom-pikambana voafaritra ato amin'ity wiki ity ary ny zo ananany. Mety misy [[{{MediaWiki:Listgrouprights-helppage}}|fampahalalana fanampiny]] mikasika ny zo manokana.",
        "listgrouprights-key": "* <span class=\"listgrouprights-granted\">Zo nomena</span>\n* <span class=\"listgrouprights-revoked\">Zo nofoanana</span>",
        "listgrouprights-namespaceprotection-header": "Fifehezana amin'ny valan'anarana",
        "listgrouprights-namespaceprotection-namespace": "Valan'anarana",
        "listgrouprights-namespaceprotection-restrictedto": "Zo ahafahan'ny mpikambana manova",
+       "listgrants": "Fahazoan-dalana",
+       "listgrants-grant": "Omena alalana",
+       "listgrants-rights": "Zo",
        "trackingcategories": "Sokajy fanarahana",
        "trackingcategories-msg": "Sokajy fanarahana",
        "trackingcategories-name": "Anaran-kafatra",
        "wlheader-showupdated": "Aseho '''sorabaventy''' ny pejy niova taorian'ny famangianao azy farany.",
        "wlnote": "Eo ambany dia ahitana ny {{PLURAL:$1|fiovana farany indrindra|ny fiovana ''$1'' farany}} natao tanatin'ny adin'ny {{PLURAL:$2|iray|'''$2'''}}, nanomboka ny $3, $4.",
        "wlshowlast": "Haneho ny $1 ora farany, ny $2 andro farany na",
+       "watchlist-hide": "Afenina",
+       "watchlist-submit": "Aseho",
+       "wlshowtime": "Vanim-potoana aseho:",
+       "wlshowhideminor": "fiovana madinika",
+       "wlshowhidebots": "rôbô",
+       "wlshowhideliu": "mpikambana nisoratra anarana",
+       "wlshowhideanons": "mpikambana tsy nisoratra anarana",
+       "wlshowhidepatr": "fiovana voavaky",
+       "wlshowhidemine": "fiovako",
+       "wlshowhidecategorization": "fanasokajiam-pejy",
        "watchlist-options": "Safidy ny lisitry ny pejy arahana",
        "watching": "Fanarahana...",
        "unwatching": "Fanalana ny fanarahana...",
        "watcherrortext": "Nisy hadisoana nitranga teo ampanovana ny safidy ny lisitry ny pejy arahanao ho an'i « $1 ».",
        "enotif_reset": "Marihana ho efa voavaky ny pejy rehetra",
        "enotif_impersonal_salutation": "Mpikamban'i {{SITENAME}}",
+       "enotif_subject_deleted": "Nofaran'i $2{{GENDER:$2|}} ny pejy $1 an'i {{SITENAME}}",
+       "enotif_subject_created": "Noforonin'i $2 ny pejy $1 tao amin'i {{SITENAME}}",
+       "enotif_subject_moved": "Nahetsik'i $2 ny pejy $1 tao amin'i {{SITENAME}}",
+       "enotif_subject_restored": "Naverin'i $2 ny pejy $1 tao amin'i {{SITENAME}}",
+       "enotif_subject_changed": "Novain'i $2 ny pejy $1 tao amin'i {{SITENAME}}",
+       "enotif_body_intro_deleted": "Nofafàn'i $2 ny pejy $1 an'i {{SITENAME}} tamin'ny $PAGEEDITDATE, jereo $3",
+       "enotif_body_intro_created": "Noforonin'i $2 ny pejy $1 an'i {{SITENAME}} tamin'ny $PAGEEDITDATE, jereo $3 ho an'ny versiona ankehitriny.",
+       "enotif_body_intro_moved": "Nahetsik'i $2 ny pejy $1 an'i {{SITENAME}} tamin'ny $PAGEEDITDATE, jereo $3 ho an'ny versiona ankehitriny.",
+       "enotif_body_intro_restored": "Naverin'i $2 ny pejy $1 an'i {{SITENAME}} tamin'ny $PAGEEDITDATE, jereo $3 ho an'ny versiona ankehitriny.",
+       "enotif_body_intro_changed": "Novain'i $2 ny pejy $1 an'i {{SITENAME}} tamin'ny $PAGEEDITDATE, jereo $3 ho an'ny versiona ankehitriny.",
        "enotif_lastvisited": "Jereo eto $1 ny niova rehetra hatramin'ny fitsidihanao farany.",
        "enotif_lastdiff": "Jereo $1 mba ahitana ireo fanovana ireo.",
        "enotif_anon_editor": "mpikambana tsy nisoratra anarana $1",
        "delete-confirm": "Hamafa ny « $1 »",
        "delete-legend": "Fafao",
        "historywarning": "'''Tandremo :''' Ny pejy hofafanao io dia manana tantaram-pejy misy famerenana $1{{PLURAL:}}",
+       "historyaction-submit": "Aseho",
        "confirmdeletetext": "Handeha hamafa tanteraka ny pejy na sary miaraka amin'ny tantarany rehetra\nao anatin'ny toby ianao. Azafady mba hamafiso fa irinao tokoa izany,\nfantatrao ny vokany ary mahalala ianao fa tsy mifanipaka amin'ny\n[[{{MediaWiki:Policy-url}}|fepetra]] izao ataonao izany.",
        "actioncomplete": "Vita ny asa",
        "actionfailed": "Tsy nandeha ny tao",
        "rollback-success": "Fanesorana ny fiovana nataon'i $1 ;\nfiverenana amin'ny fiovana farany nataon'i $2.",
        "sessionfailure-title": "Tsi-fetezaka mikasika ny kaonty idirana",
        "sessionfailure": "Ohatry ny misy olana ny fidirana amin'ny kaontinao ; \nnofoanana ilay tao mba tsy hisy fanodinana fotaom-pidirana (session).\nTsindrio \"Mialoha\" ary vaozy ilay pejy niavianao ary andramo fanindroany.",
+       "changecontentmodel-legend": "Môdelim-botoatim-pejy",
        "changecontentmodel-title-label": "Lohatenim-pejy",
        "changecontentmodel-model-label": "Môdelim-botoatiny",
        "changecontentmodel-reason-label": "Antony :",
+       "changecontentmodel-submit": "Ovaina",
        "changecontentmodel-success-title": "Niova ny môdelim-botoatiny",
        "logentry-contentmodel-change-revertlink": "mamerina",
        "logentry-contentmodel-change-revert": "mamerina",
        "whatlinkshere-hidelinks": "$1 ny rohy",
        "whatlinkshere-hideimages": "$1 ny rakitra mirohy",
        "whatlinkshere-filters": "sivana",
+       "whatlinkshere-submit": "Andao",
        "autoblockid": "Fanakanana mandeha ho azy #$1",
        "block": "Hanakana ilay mpikambana",
        "unblock": "Hanala ny sakan'ilay mpikambana",
        "movenotallowedfile": "Tsy mahazo ovainao anarana ny rakitra.",
        "cant-move-user-page": "Tsy azo ovainao anarana ny renipejim-pikambana (any ivelan'ny zana-pejiny).",
        "cant-move-to-user-page": "Tsy azo ovainao ny manova anarana pejy makany amina pejim-pikambana (afatsy zana-pejy iray).",
-       "newtitle": "Lohateny vaovao",
+       "newtitle": "Lohateny vaovao:",
        "move-watch": "araho-maso ity pejy ity",
        "movepagebtn": "Afindrao",
        "pagemovedsub": "Voafindra ny pejy",
        "export-download": "Hitahiry azy anaty rakitra",
        "export-templates": "Ataovy ao ny endrika",
        "export-pagelinks": "Ataovy ao any pejy mmirohy amin'y halalina :",
+       "export-manual": "Ampiana amin'ny alalan'ny tanana ilay pejy:",
        "allmessages": "Hafatry ny rindrankajy",
        "allmessagesname": "Anarana",
        "allmessagesdefault": "Dikan-teny tany am-boalohany",
        "thumbnail-temp-create": "Tsy afaka namorona ilay thumbnail miserana",
        "thumbnail-dest-create": "Tsy nahatahiry ilay thumbnail tany amin'ny tanjona",
        "thumbnail_invalid_params": "Parametatry ny saritapaka tsy mety",
+       "thumbnail_toobigimagearea": "Rakitra manana habe mihoatra ny $1",
        "thumbnail_dest_directory": "Tsy mety amboarina ilay petra-drakitra tanjona",
        "thumbnail_image-type": "Karazan-drakitra tsy zaka",
        "thumbnail_image-missing": "Rakitra ohatran'ny tsy ao : $1",
        "import-interwiki-history": "Handika ny santiônan'ny tantaran'ity pejy ity",
        "import-interwiki-templates": "Ataovy ao ny endrika rehetra",
        "import-interwiki-submit": "Hampiditra",
+       "import-mapping-namespace": "Ampidirina amin'ny anaran-tsehatra:",
+       "import-mapping-subpage": "Ampidirina ho zana-pejin'ny pejy manaraka:",
        "import-upload-filename": "Anaran-drakitra :",
        "import-comment": "Resaka :",
        "importstart": "Am-pampidirana ny pejy…",
        "importlogpage": "laogin'ny fampidirana",
        "importlogpagetext": "Fampidirana ara-pandraharahana ny pejy miaraka amin'ny tantaram-panvany avy any amin'ny wiki hafa.",
        "javascripttest": "Fanandramana JavaScript",
+       "javascripttest-pagetext-unknownaction": "Asa tsy fantatra \"$1\".",
        "javascripttest-pagetext-skins": "Mifidia skin hanaovana ny fanandramana:",
        "javascripttest-qunit-intro": "Jereo ny [$1 fanoroana mikasika ny andrana] eo amin'i mediawiki.org.",
        "tooltip-pt-userpage": "Ny pejim-pikambanao",
        "duplicate-defaultsort": "'''Tandremo''' : manitsaka ny sort key taloha \"$1\" ilay sort key ankehitriny \"$2\".",
        "version": "Versiona",
        "version-extensions": "Fanitarana nampidirina",
+       "version-skins": "Fitafy efa napetraka",
        "version-specialpages": "Pejy manokana",
        "version-variables": "Miova",
+       "version-antispam": "Fisorohana maila-pako",
        "version-other": "Samihafa",
        "version-hook-subscribedby": "Nalefan'i",
        "version-version": "($1)",
        "version-license": "Lisansa Mediawiki",
+       "version-ext-license": "Fahazoan-dalana",
+       "version-ext-colheader-name": "Fanitarana",
+       "version-skin-colheader-name": "Fiseho",
+       "version-ext-colheader-version": "Versiona",
+       "version-ext-colheader-license": "Fahazoan-dalana",
+       "version-ext-colheader-description": "Famaritana",
+       "version-ext-colheader-credits": "Mpamorona",
+       "version-license-title": "Fahazoan-dalana ho an'i $1",
+       "version-credits-title": "Fisaorana ho an'i $1",
        "version-poweredby-others": "hafa",
        "version-software": "Rindrankahy voapetraka",
        "version-software-product": "Vokatra",
        "version-software-version": "Versiona",
+       "version-entrypoints": "URL ny toeram-pidirana",
+       "version-entrypoints-header-entrypoint": "Toeram-pidirana",
+       "version-entrypoints-header-url": "URL",
+       "version-libraries": "Librery napetraka",
+       "version-libraries-library": "Librery",
+       "version-libraries-version": "Versiona",
+       "version-libraries-license": "Fahazoan-dalana",
+       "version-libraries-description": "Visavisa",
+       "version-libraries-authors": "Mpamorona",
+       "redirect-submit": "Alefa",
+       "redirect-lookup": "Karohana:",
+       "redirect-value": "Sanda:",
+       "redirect-user": "ID mpikambana",
+       "redirect-page": "ID ny pejy",
+       "redirect-revision": "Versiom-pejy",
+       "redirect-file": "Anaran-drakitra",
+       "redirect-logid": "ID laogy",
+       "redirect-not-exists": "Sanda tsy hita",
        "fileduplicatesearch": "Hitady rakitra mitovy endrika",
        "fileduplicatesearch-legend": "Hitady mitovy endrika",
        "fileduplicatesearch-filename": "Anaran-drakitra :",
        "fileduplicatesearch-result-1": "Tsy misy rakitra mitovy amin'ny « $1 ».",
        "fileduplicatesearch-result-n": "Misy rakitra {{PLURAL:}}$2 mitovy amin'i « $1 ».",
        "specialpages": "Pejy manokana",
-       "specialpages-note": "* Pejy manokana tsotra\n* <strong class=\"mw-specialpagerestricted\">Pejy manokana voafetra.</strong>",
+       "specialpages-note-top": "Maribolana",
+       "specialpages-note": "* Pejy manokana tsotra\n* <span class=\"mw-specialpagerestricted\">Pejy manokana voafetra ara-pijey.</span>",
        "specialpages-group-maintenance": "laogy hikojakojana",
        "specialpages-group-other": "Pejy manokana hafa",
        "specialpages-group-login": "Hiditra / hisoratra anarana",
        "specialpages-group-wiki": "Data sy fitaovana",
        "specialpages-group-redirects": "Pejy manokana voaodina",
        "specialpages-group-spam": "Fitaovana fanalana spam",
+       "specialpages-group-developer": "Fitaovam-panitatra",
        "blankpage": "Pejy fotsy",
        "intentionallyblankpage": "Avela fananiana ho fotsy ity pejy ity.",
        "external_image_whitelist": "#Avelao tahaka izao ity andalana ity.<pre>\n#Lazao ny singana REGEX (ny singa voalaza eo anelanelan'ny //) eo ambany.\n#Miady amin'ny URL ny sary ivelany izy ireo.\n#Hiseho sahala sary izay miady, raha tsy izany dia rohy mankany amin'ilay sary ihany no haseho.\n#Ho resaka ny andalana manomboka amin'ny #.\n#Tsy miraharaha ny zanatsoratra sy ny renisoratra ity lisitra ity.\n\n#Ataovy eo ambonin'ity andalana ity ny singana REGEX. Avelao tahaka izao ity andalana farany ity.</pre>",
        "tags-tag": "Anaran'ny balizy",
        "tags-display-header": "Seho anatin'ny lisitry ny fanovana",
        "tags-description-header": "Famisavisana tanteraka an'ilay balizy",
+       "tags-source-header": "Loharano",
+       "tags-active-header": "Mandeha?",
        "tags-hitcount-header": "Fanovana voabalizy",
+       "tags-actions-header": "Tao",
+       "tags-active-yes": "Eny",
+       "tags-active-no": "Tsia",
+       "tags-source-extension": "Voafaritr'itatra",
+       "tags-source-manual": "Ampiharin'ny mpikambana sy rôbô tanana",
+       "tags-source-none": "Tsy ampiasaina intsony",
        "tags-edit": "hanova",
+       "tags-delete": "fafao",
+       "tags-activate": "alefa",
+       "tags-deactivate": "aza alefa",
        "tags-hitcount": "{{PLURAL:$1|fanovana|fanovana}} $1",
+       "tags-manage-no-permission": "Tsy manana zo mikirakira ny balizy ianao.",
+       "tags-manage-blocked": "Tsy afaka manova balizy ianao rehefa voasakana.",
+       "tags-create-heading": "Hamorona balizy vaovao",
+       "tags-create-tag-name": "Anaram-balizy:",
+       "tags-create-reason": "Antony :",
+       "tags-create-submit": "Foronona",
+       "tags-create-no-name": "Tsy maintsy manisy anaram-balizy ianao.",
+       "tags-delete-title": "Hamafa balizy",
+       "tags-delete-explanation-initial": "Mby hamafa ny balizy \"$1\" amin'ny banky angona ianao.",
+       "tags-delete-reason": "Antony:",
+       "tags-delete-submit": "Hamafa ity balizy ity mandrakizay",
+       "tags-delete-not-allowed": "Tsy afaka fafana ny balizy voafatr'itatra raha tsy mamela hanao izany ilay itatra.",
+       "tags-delete-not-found": "Tsy misy ny balizy \"$1\".",
+       "tags-activate-title": "Alefa ilay balizy",
+       "tags-activate-question": "Mby handefa balizy \"$1\" ianao.",
+       "tags-activate-reason": "Antony:",
+       "tags-activate-not-allowed": "Tsy mety atao ny mandefa balizy \"$1\".",
+       "tags-activate-not-found": "Tsy misy ny balizy \"$1\".",
+       "tags-activate-submit": "Alefa",
+       "tags-deactivate-title": "Aza alefa ny balizy",
+       "tags-deactivate-question": "Mby tsy hampandefa ny balizy \"$1\" ianao.",
+       "tags-deactivate-reason": "Antony:",
+       "tags-deactivate-not-allowed": "Tsy afaka atao ny manajanona ny balizy \"$1\".",
+       "tags-deactivate-submit": "Aza alefa",
+       "tags-edit-title": "Hanova balizy",
+       "tags-edit-manage-link": "Hikirakira balizy",
+       "tags-edit-new-tags": "Balizy vaovao:",
+       "tags-edit-add": "Ampiana ireo balizy ireo:",
+       "tags-edit-remove": "Hanala ireo balizy ireo:",
+       "tags-edit-remove-all-tags": "(hanala ny balizy rehetra)",
+       "tags-edit-chosen-placeholder": "Hifidy balizy sasany",
+       "tags-edit-chosen-no-results": "Tsy nisy balizy niady",
+       "tags-edit-reason": "Antony:",
+       "tags-edit-success": "Efa mihatra ny fiovana.",
+       "tags-edit-failure": "Tsy tafahatra ireto fiovana ireto:\n$1",
+       "tags-edit-nooldid-title": "Versiona tanjona tsy ekena",
        "comparepages": "Hampitaha pejy",
        "compare-page1": "Pejy 1",
        "compare-page2": "Pejy 2",
        "compare-rev1": "Versiona 1",
        "compare-rev2": "Versiona 2",
        "compare-submit": "Ampitahao",
+       "compare-invalid-title": "Tsy ekena ny lohateny nosoratanao.",
+       "compare-title-not-exists": "Tsy misy ny lohateny nosoratanao.",
+       "compare-revision-not-exists": "Tsy misy ny versiona nosoratanao.",
        "dberr-problems": "Azafady Tompoko ! Manana olana ara-teknika ny sehatra.",
        "dberr-again": "Miandrasa minitra vitsivitsy ary alefaso fanindroany",
-       "dberr-info": "(Tsy afaka mifandray amin'ny lohamilin'ny database : $1)",
+       "dberr-info": "(Tsy afaka mifandray amin'ny banky angona: $1)",
+       "dberr-info-hidden": "(Tsy afaka mifandray amin'ny banky angona)",
        "dberr-usegoogle": "Afaka manandrana mikaroka eo amin'ny Google ianao mandritra izay.",
+       "dberr-outofdate": "Fantaro fa mety efa lany andro ny index-n'ny votoatinay",
        "dberr-cachederror": "Izy io dia dika nasitriky ny pejy nangatahana ary mety efa tola.",
        "htmlform-invalid-input": "Nisy olana nitranga tamin'ny sanda sasany",
        "htmlform-select-badoption": "Tsy azo ekena ny sanda nambaranao.",
        "htmlform-float-invalid": "Tsy isa ny sanda nambaranao.",
        "htmlform-int-toolow": "Ny sanda nambaranao dia kely nohon'ny fetra iva indrindra $1",
        "htmlform-int-toohigh": "Ny sanda nambaranao dia ngeza nohon'ny fetra avo indrindra $1",
+       "htmlform-required": "Ilaina ny sandany.",
        "htmlform-submit": "Alefa",
        "htmlform-reset": "Hanala ny fanovana",
        "htmlform-selectorother-other": "Hafa",
+       "htmlform-no": "Tsia",
+       "htmlform-yes": "Eny",
+       "htmlform-chosen-placeholder": "Makà safidy",
+       "htmlform-cloner-create": "Hanampy be kokoa",
+       "htmlform-cloner-delete": "Esorina",
+       "htmlform-cloner-required": "Sanda iray farafahakeliny no ilaina",
+       "htmlform-title-badnamespace": "Tsy ao amin'i anaran-tsehatra \"{{ns:$2}}\" i [[:$1]].",
+       "htmlform-title-not-creatable": "Lohatenim-pejy tsy azo foronina \"$1\"",
+       "htmlform-title-not-exists": "Tsy misy $1.",
+       "htmlform-user-not-exists": "Tsy misy ny <strong>$1</strong>.",
+       "htmlform-user-not-valid": "Tsy anaram-pikambana azo raisina <strong>$1</strong>.",
+       "sqlite-has-fts": "$1 misy fikarohan-dahatsoratra tanteraka",
+       "sqlite-no-fts": "$1 tsy misy fikarohan-dahatsoratra tanteraka",
        "logentry-delete-delete": "nofafan'i $1 ny pejy $3",
+       "logentry-delete-restore": "Namerina ny pejy $3 i $1{{GENDER:$2|}}",
+       "logentry-delete-event": "Nanova ny fahitana {{PLURAL:$5|laogy iray|laogy $5}} tamin'i $3 i $1: $4",
+       "logentry-delete-revision": "Nanova ny fahitana {{GENDER:$2|}}{{PLURAL:$5|versiona $5}} tamin'ny pejy $3 i $1: $4",
+       "logentry-delete-event-legacy": "{{GENDER:$2|}}Nanova ny fahitana ny zava-mitranga amin'ny laogy momba an'i $3 i $1",
+       "logentry-delete-revision-legacy": "Nanova ny fahitana ny versiona amin'ny pejy $3 i $1",
        "logentry-suppress-delete": "{{GENDER:$2|nofafan'i}} $1 ny pejy $3",
+       "logentry-suppress-event": "Nanova{{GENDER:$2|}} antsokosoko ny fahitana amin'ny {{PLURAL:$5|zava-mitranga amin'ny laogy $5}} amin'i $3 i $1: $4",
+       "logentry-suppress-revision": "Nanova{{GENDER:$2|}} antsokosoko ny fahitana amin'ny {{PLURAL:$5|versiona $5}} amin'i $3 i $1: $4",
+       "logentry-suppress-event-legacy": "Nanova antsokosoko ny fahitana ny zava-mitranga amin'ny laogy momba an'i $3 i $1",
        "revdelete-content-hid": "votoatiny nafenina",
        "revdelete-summary-hid": "ambangovangom-panovana nafenina",
        "revdelete-uname-hid": "anaram-pikambana nafenina",
        "feedback-subject": "Lohahevitra:",
        "feedback-submit": "Alefa",
        "feedback-thanks": "Misaotra! lanefa tany amin'ilay pejy ''[$2 $1]'' ilay fanehoan-kevitrao.",
+       "feedback-useragent": "User agent:",
        "searchsuggest-search": "Karohy",
        "searchsuggest-containing": "misy...",
        "api-error-badaccess-groups": "Tsy afaka mampiditra rakitra eto amin'ity wiki ity ianao.",
index e498c30..f55d378 100644 (file)
        "articlepage": "Lihek isi laman",
        "talk": "Rundiang",
        "views": "Caliak",
-       "toolbox": "Kotak pakakeh",
+       "toolbox": "Pakakeh",
        "userpage": "Lihek laman pangguno",
        "projectpage": "Caliak laman proyek",
        "imagepage": "Caliak laman berkas",
        "nstab-template": "Templat",
        "nstab-help": "Bantuan",
        "nstab-category": "Kategori",
+       "mainpage-nstab": "Palanta",
        "nosuchaction": "Indak ado tindakan tasabuik",
        "nosuchactiontext": "Tindakan nan diminta dek URL tasabuik indak valid. Sanak mungkin salah mangetikkan URL, atau mangikuik pautan nan salah. Iko mungkin manunjuakan adonyo suatu bug pado parangkaik lunak nan dipagunoan dek {{SITENAME}}.",
        "nosuchspecialpage": "Indak ado laman istimewa tasabuik",
        "login-abort-generic": "Proses masuak Sanak indak barasil - Dibatalan",
        "loginlanguagelabel": "Baso: $1",
        "suspicious-userlogout": "Pamintaan Sanak untuak kalua log ditulak karano tampaknyo dikirim oleh paramban nan rusak atau proksi panyinggah.",
+       "pt-login": "Masuak log",
+       "pt-createaccount": "Buek akun",
        "pt-userlogout": "Kalua log",
        "php-mail-error-unknown": "Kasalahan nan indak jaleh dalam fungsi mail() PHP",
        "user-mail-no-addy": "Mancubo mangirim surel tanpa alamaik surel.",
        "minoreditletter": "k",
        "newpageletter": "B",
        "boteditletter": "b",
+       "rc-change-size-new": "$1 {{PLURAL:$1|byte|bita}} satalah parubahan",
        "rc-enhanced-expand": "Tampilkan rincian (paralu JavaScript)",
        "rc-enhanced-hide": "Suruakkan rincian",
        "recentchangeslinked": "Parubahan takaik",
        "tooltip-pt-mycontris": "Daftar jariah Sanak",
        "tooltip-pt-login": "Sanak disaranan untuak masuak log; walaupun indak wajib",
        "tooltip-pt-logout": "Kalua log",
+       "tooltip-pt-createaccount": "Sanak dianjuaan mambuek akun dan masuak log; walaupun hal iko indak aruih",
        "tooltip-ca-talk": "Parudiangan tantang isi laman",
-       "tooltip-ca-edit": "Angku dapek manyuntiang laman ko. Silakan gunoan tombol pratonton sabalun manyimpan",
+       "tooltip-ca-edit": "Suntiang laman ko",
        "tooltip-ca-addsection": "Mulai bagian baru",
        "tooltip-ca-viewsource": "Laman ko dilinduangi.\nSanak hanyo buliah mancaliak sumbernyo sajo",
        "tooltip-ca-history": "Revisi sabalunnyo dari laman ko",
index f3e4132..1d68d63 100644 (file)
@@ -16,7 +16,8 @@
                        "לערי ריינהארט",
                        "아라",
                        "Milicevic01",
-                       "Macofe"
+                       "Macofe",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Потцртување на врски:",
        "userlogin-remembermypassword": "Запомни ме",
        "userlogin-signwithsecure": "Користи безбеден опслужувач",
        "cannotloginnow-title": "Во моментов не можам да ве најавм",
+       "cannotloginnow-text": "Не можам да ве најавам кога се користи $1.",
        "yourdomainname": "Вашиот домен:",
        "password-change-forbidden": "Не можете да ја менувате лозинката на ова вики.",
        "externaldberror": "Настана грешка при надворешното најавување на базата или пак немате дозвола да ја подновите вашата надворешна сметка.",
        "nocookiesfornew": "Корисничката сметка не е создадена бидејќи не можеше да се потврди нејзиниот извор.\nЗа оваа цел ќе ви требаат колачиња. Проверете дали се овозможени, превчитајте ја страницава и обидете се повторно.",
        "nocookiesforlogin": "{{int:nocookieslogin}}",
        "noname": "Внесовте погрешно корисничко име.",
-       "loginsuccesstitle": "Ð\9dаÑ\98аваÑ\82а Ðµ Ñ\83Ñ\81пеÑ\88на",
+       "loginsuccesstitle": "Ð\9dаÑ\98авени Ñ\81Ñ\82е",
        "loginsuccess": "Сега сте најавени на {{SITENAME}} како „$1“.",
        "nosuchuser": "Нема корисник со името „$1“.\nКорисничките имиња разликуваат мали и големи букви.\nПроверете да не сте направиле грешка во пишувањето, или [[Special:UserLogin/signup|создајте нова корисничка сметка]].",
        "nosuchusershort": "Нема корисник со името „$1“.\nПроверете дали правилно сте напишале.",
        "createaccount-title": "Создавање на сметка за {{SITENAME}}",
        "createaccount-text": "Некој направил сметка со вашата е-поштенска адреса на {{SITENAME}} ($4) со име „$2“ и  лозинка „$3“.\nБи требало сега да се пријавите и да ја промените вашата лозинка.\n\nМожете да ја занемарите оваа порака ако сметката била направена по грешка.",
        "login-throttled": "Имате премногу обиди за најава за кратко време.\nПочекајте $1 пред да се обидете повторно.",
-       "login-abort-generic": "Најавата е неуспешна - Прекинато",
+       "login-abort-generic": "Најавата е неуспешна — Откажано",
        "login-migrated-generic": "Вашата сметка е пренесена и корисничкото име веќе не постои на ова вики.",
        "loginlanguagelabel": "Јазик: $1",
        "suspicious-userlogout": "Вашето барање за одјава е одбиено бидејќи се чини дека е испратено од расипан прелистувач или кеширачки застапник (proxy).",
        "newpassword": "Нова лозинка:",
        "retypenew": "Повторете ја новата лозинка:",
        "resetpass_submit": "Поставете лозинка и најавете се",
-       "changepassword-success": "Ð\92аÑ\88аÑ\82а Ð»Ð¾Ð·Ð¸Ð½ÐºÐ° Ðµ Ñ\83Ñ\81пеÑ\88но Ñ\81менеÑ\82а!",
+       "changepassword-success": "Вашата лозинка е сменета!",
        "changepassword-throttled": "Имате премногу обиди за најава за кратко време.\nПочекајте $1 пред да се обидете повторно.",
+       "botpasswords": "Ботовски лозинки",
        "botpasswords-label-appid": "Име на ботот:",
        "botpasswords-label-create": "Создај",
        "botpasswords-label-update": "Поднови",
        "recentchangeslinked-page": "Име на страницата:",
        "recentchangeslinked-to": "Прикажи ги промените на страниците поврзани со дадената страница",
        "recentchanges-page-added-to-category": "[[:$1]] ставена во категорија",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] и уште {{PLURAL:$2|една страница ставена|$2 страници ставеи}} во категорија",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] и уште [[Special:WhatLinksHere/$1|{{PLURAL:$2|една страница ставена|$2 страници ставеи}}]] во категорија",
        "recentchanges-page-removed-from-category": "[[:$1]] отстранета од категорија",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] и уште {{PLURAL:$2|една страница отстранета|$2 страници отстранети}} од категорија",
        "autochange-username": "Автоматски промени на МедијаВики",
index e313abe..0f9afb9 100644 (file)
        "recentchangeslinked-page": "താളിന്റെ പേര്:",
        "recentchangeslinked-to": "തന്നിരിക്കുന്ന താളിലെ മാറ്റങ്ങൾക്കു പകരം ബന്ധപ്പെട്ട താളുകളിലെ മാറ്റങ്ങൾ കാണിക്കുക",
        "recentchanges-page-added-to-category": "[[:$1]] വർഗ്ഗത്തിലേക്ക് ചേർത്തിരിക്കുന്നു",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] താളും ഒപ്പം {{PLURAL:$2|മറ്റൊരു താളും|$2 താളുകളും}} വർഗ്ഗത്തിലേക്ക് ചേർത്തിരിക്കുന്നു",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] താളും ഒപ്പം [[Special:WhatLinksHere/$1|{{PLURAL:$2|മറ്റൊരു താളും|$2 താളുകളും}}]] വർഗ്ഗത്തിലേക്ക് ചേർത്തിരിക്കുന്നു",
        "recentchanges-page-removed-from-category": "[[:$1]] വർഗ്ഗത്തിൽ നിന്ന് നീക്കംചെയ്തു",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] താളും ഒപ്പം {{PLURAL:$2|മറ്റൊരു താളും|$2 താളുകളും}} വർഗ്ഗത്തിൽ നിന്ന് നീക്കംചെയ്തിരിക്കുന്നു",
        "autochange-username": "മീഡിയവിക്കി സ്വയംപ്രവർത്തിത മാറ്റം",
index 1f7e833..2ba3513 100644 (file)
        "recentchangeslinked-page": "पृष्ठ नाव:",
        "recentchangeslinked-to": "याऐवजी दिलेल्या पानाला जोडलेल्या पानांवरील बदल दाखवा",
        "recentchanges-page-added-to-category": "[[:$1]] वर्गास जोडले",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] व {{PLURAL:$2|एक पान वर्गास जोडले|$2 पाने वर्गास जोडलीत}}",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] व [[Special:WhatLinksHere/$1|{{PLURAL:$2|एक पान वर्गास जोडले|$2 पाने वर्गास जोडलीत}}]]",
        "recentchanges-page-removed-from-category": "[[:$1]] ला वर्गातून हटविले",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] व {{PLURAL:$2|एक पान वर्गातून हटविले|$2 पाने वर्गातून हटविलीत}}",
        "autochange-username": "मिडियाविकि आपोआप बदल",
index aa44e04..d29a55d 100644 (file)
@@ -20,7 +20,8 @@
                        "아라",
                        "Pizza1016",
                        "Macofe",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Garis bawah pautan:",
        "recentchangeslinked-page": "Nama laman:",
        "recentchangeslinked-to": "Paparkan perubahan pada laman yang mengandungi pautan ke laman yang diberikan",
        "recentchanges-page-added-to-category": "[[:$1]] ditambahkan kepada kategori",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] dan {{PLURAL:$2|satu|$2}} lagi halaman ditambahkan kepada kategori",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] dan [[Special:WhatLinksHere/$1|{{PLURAL:$2|satu|$2}}]] lagi halaman ditambahkan kepada kategori",
        "recentchanges-page-removed-from-category": "[[:$1]] digugurkan dari kategori",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] dan {{PLURAL:$2|satu|$2}} lagi halaman digugurkan dari kategori",
        "autochange-username": "Perubahan automatik MediaWiki",
index cd21621..3e8e28f 100644 (file)
@@ -22,7 +22,8 @@
                        "아라",
                        "9.sinistra",
                        "Ninjastrikers",
-                       "Penguinlay"
+                       "Penguinlay",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "လင့်ကို မျဉ်းသားသည့် ပုံစံ -",
        "returnto": "$1 သို့ ပြန်သွားရန်။",
        "tagline": "{{SITENAME}} မှ",
        "help": "အ​ကူ​အ​ညီ​",
-       "search": "ရှာ​ဖွေ​ရန်​",
-       "searchbutton": "ရှာ​ဖွေ​ရန်​",
+       "search": "ရှာဖွေရန်",
+       "searchbutton": "ရှာဖွေရန်",
        "go": "သွား​ပါ​",
        "searcharticle": "သွား​ပါ​",
        "history": "စာမျက်နှာ ရာဇဝင်",
        "protectedpage": "ကာကွယ်ထားသည့် စာမျက်နှာ",
        "jumpto": "ဤနေရာသို့သွားရန် -",
        "jumptonavigation": "အ​ညွှန်း​",
-       "jumptosearch": "ရှာ​ဖွေ​ရန်​",
+       "jumptosearch": "ရှာဖွေရန်",
        "view-pool-error": "ဆာဗာသည် ယခုအချိန်တွင် မမျှသောဝန်ကို ထမ်းနေရသည်။\nအသုံးပြုသူ အမြောက်အများက ဤစာမျက်နှာကို ကြည့်ရှုရန် ကြိုးပမ်းနေကြသည်။\nဤစာမျက်နှာကို နောက်တစ်ကြိမ် ပြန်မကြည့်မီ ခဏတာမျှ စောင့်ပါ။\n\n$1",
        "generic-pool-error": "ဝမ်းနည်းပါသည်၊ ဆာဗာများသည် ယခုအချိန်တွင် မမျှသောဝန်ကို ထမ်းနေရသည်။\nအသုံးပြုသူ အမြောက်အများက ဤစာမျက်နှာကို ကြည့်ရှုရန် ကြိုးပမ်းနေကြသည်။\nဤစာမျက်နှာကို နောက်တစ်ကြိမ် ပြန်မကြည့်မီ ခဏတာမျှ စောင့်ပါ။",
        "pool-errorunknown": "အမည်မသိအမှား",
        "createacct-error": "အကောင့်ဖန်တီးမှု အမှား",
        "createaccounterror": "ဤအကောင့်ကို မဖန်တီးနိုင်ပါ - $1",
        "noname": "တရားဝင် အသုံးပြုသူအမည်ကို မသတ်မှတ်ရသေးပါ။",
-       "loginsuccesstitle": "Login ဝင်​ခြင်း အောင်မြင်သည်။",
+       "loginsuccesstitle": "လော့ဂ်အင်ဝင်ပြီးပြီ",
        "loginsuccess": "'''သင်သည် {{SITENAME}} သို့ \"$1\" အဖြစ် Login ဝင်ပြီးဖြစ်သည်။'''",
        "nosuchusershort": "\"$1\" အမည်ဖြင့် အသုံးပြုသူမရှိပါ။\nစာလုံးပေါင်း ပြန်စစ်ပေးပါရန်။",
        "nouserspecified": "အသုံးပြုသူအမည်ကို ဖော်ပြရမည်ဖြစ်သည်။",
        "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|ဆွေးနွေး]]) အတွက် အကောင့်ကို ဖန်တီးပြီး ဖြစ်သည်။",
        "createaccount-title": "{{SITENAME}} အတွက် အကောင့်ပြုလုပ်ခြင်း",
        "login-throttled": "သင်သည် login ဝင်ရန် အကြိမ်မြောက်မြားစွာ အားထုတ်ခဲ့ပြီးဖြစ်သည်။\nကျေးဇူးပြု၍ ထပ်မဝင်ခင် $1 စောင့်ပေးပါ။",
-       "login-abort-generic": "Login ဝင်ခြင်း မအောင်မြင်ပါ - ထွက်သွားပြီ",
+       "login-abort-generic": "လော့ဂ်အင်ဝင်ခြင်း မအောင်မြင်ပါ - ဖျက်သိမ်းပြီး",
        "loginlanguagelabel": "ဘာသာ: $1",
        "pt-login": "အကောင့်ဝင်ရန်",
        "pt-login-button": "အကောင့်ဝင်ရန်",
        "newpassword": "စကားဝှက် အသစ် -",
        "retypenew": "စကားဝှက် အသစ်ကို ထပ်ရိုက်ပါ -",
        "resetpass_submit": "စကားဝှက်ကို သတ်မှတ်ပြီးနောက် Log in ဝင်ရန်",
-       "changepassword-success": "á\80\9eá\80\84á\80·á\80ºá\80\85á\80\80á\80¬á\80¸á\80\9dá\80¾á\80\80á\80ºá\80\80á\80­á\80¯ á\80¡á\80±á\80¬á\80\84á\80ºá\80\99á\80¼á\80\84á\80ºá\80\85á\80½á\80¬ á\80\95á\80¼á\80±á\80¬á\80\84á\80ºá\80¸á\80\9cá\80²á\80\95á\80¼á\80®á\80¸á\80\95á\80«á\80\95á\80¼á\80®á\81\8b",
+       "changepassword-success": "á\80\9eá\80\84á\80·á\80ºá\80\85á\80\80á\80¬á\80¸á\80\9dá\80¾á\80\80á\80ºá\80\80á\80­á\80¯ á\80\95á\80¼á\80±á\80¬á\80\84á\80ºá\80¸á\80\9cá\80²á\80\95á\80¼á\80®á\80¸á\80\95á\80«á\80\95á\80¼á\80®!",
        "botpasswords-label-appid": "ဘော့အမည်-",
        "botpasswords-label-create": "ဖန်တီး",
        "botpasswords-label-cancel": "မလုပ်တော့ပါ",
        "revdelete-nooldid-title": "တရားမဝင်သော မူအမည်",
        "revdelete-no-file": "ဖော်ပြထားသောဖိုင် မရှိပါ။",
        "revdelete-show-file-submit": "မှန်",
+       "revdelete-selected-file": "[[:$2]] ၏ ရွေးချယ်ထားသော {{PLURAL:$1|ဖိုင်ဗားရှင်း|ဖိုင်ဗားရှင်းများ}}:",
+       "revdelete-text-text": "ဖျက်လိုက်သည့် မူများသည် စာမျက်နှာရာဇဝင်တွင် ရှိနေဦးမည်ဖြစ်သော်လည်း ထိုပါဝင်အကြောင်းအရာသည် အများပြည်သူမှ မြင်ရတော့မည် မဟုတ်ပေ။",
+       "revdelete-text-file": "ဖျက်လိုက်သော ဖိုင်ဗားရှင်းများသည် ဖိုင်ရာဇဝင်ထဲတွင် ရှိနေဦးမည်ဖြစ်သော်လည်း ယင်းတို့ကို အများပြည်သူ ကြည့်ရှုနိုင်မည် မဟုတ်ပေ။",
+       "logdelete-text": "ဖျက်လိုက်သော မှတ်တမ်းသည် မှတ်တမ်းများထဲတွင် ပေါ်နေဦးမည်ဖြစ်သော်လည်း ပါဝင်အကြောင်းအရာကို အများပြည်သူများ မြင်ရတော့မည် မဟုတ်ပေ။",
+       "revdelete-text-others": "အပိုကန့်သတ်ချက်များကို မထည့်ထားပါက အခြားသော အက်ဒမင်များအနေဖြင့် ဝှက်ထားသော အကြောင်းအရာကို ကြည့်နိုင်ပြီး ဖျက်ထားခြင်းကို ပယ်ဖျက်နိုင်သည်။",
+       "revdelete-confirm": "ဤသို့ ဖျက်ပစ်ရန် သင် အမှန်တကယ် ရည်ရွယ်လျက် နောက်ဆက်တွဲ အကျိုးဆက်များကို သိရှိနားလည်ပြီး [[{{MediaWiki:Policy-url}}|မူဝါဒ]]အတိုင်း လုပ်ဆောင်နေခြင်းဖြစ်ကြောင်းကို ကျေးဇူးပြု၍ အတည်ပြုပေးပါ။",
        "revdelete-legend": "မြင်နိုင်စွမ်းရှိမှုတို့အား ကန့်သတ်ခြင်းကို သတ်မှတ်ရန်",
        "revdelete-hide-text": "တည်းဖြတ်မူမှ စာသား",
        "revdelete-hide-image": "ဖိုင်ပါ အေကြာင်းအရာများကို ဝှက်ရန်",
        "revdelete-unsuppress": "ပြန်လည်ထိန်းသိမ်းထားသော မူများမှ ကန့်သတ်ချက်များကို ဖယ်ရှားရန်",
        "revdelete-log": "အ​ကြောင်း​ပြ​ချက်:",
        "revdelete-submit": "ရွေးချယ်ထားသော {{PLURAL:$1|မူ|မူများ}}ကို သက်ရောက်စေရန်",
-       "revdelete-success": "'''မူမြင်နိုင်စွမ်းရှိမှုကို အောင်မြင်စွာ update လုပ်ပြီးပါပြီ။'''",
+       "revdelete-success": "မူမြင်နိုင်စွမ်းရှိမှုကို update လုပ်ပြီးပါပြီ။",
        "revdel-restore": "မည်မျှ ရှုမြင်နိုင်သည်ကို ပြောင်းရန်",
        "pagehist": "စာမျက်နှာ မှတ်တမ်း",
        "deletedhist": "ဖျက်ပစ်လိုက်သော မှတ်တမ်း",
        "mergehistory-reason": "​ကြောင်း​ပြ​ချက် -",
        "mergelog": "ပေါင်းလိုက်သော မှတ်တမ်း",
        "revertmerge": "ပြန်ခွဲထုတ်ရန်",
+       "mergelogpagetext": "အောက်ပါတို့သည် စာမျက်နှာ ရာဇဝင်ကို အခြားတစ်ခုသို့  မကြာမီက ပေါင်းလိုက်သော စာရင်းဖြစ်သည်။",
        "history-title": "\"$1\"၏ တည်းဖြတ်မှု ရာဇဝင်",
        "difference-title": "\"$1\" ၏ တည်းဖြတ်မှု မူကွဲများ",
        "difference-title-multipage": "စာမျက်နှာ \"$1\" နှင့် \"$2\" အကြား ကွဲပြားမှု",
        "prefs-editing": "တည်းဖြတ်ခြင်း",
        "rows": "အလျားလိုက်တန်း -",
        "columns": "ဒေါင်လိုက်တန်း -",
-       "searchresultshead": "ရှာ​ဖွေ​ရန်​",
+       "searchresultshead": "ရှာဖွေရန်",
        "stub-threshold-disabled": "ပိတ်ထားသည်",
        "recentchangesdays": "လတ်တလောအပြောင်းအလဲများကို ပြရန်နေ့များ -",
        "recentchangesdays-max": "အများဆုံး $1 {{PLURAL:$1|ရက်|ရက်}}",
        "timezoneregion-indian": "အိန္ဒိယသမုဒ္ဒရာ",
        "timezoneregion-pacific": "ပစိဖိတ်သမုဒ္ဒရာ",
        "allowemail": "အခြားအသုံးပြုသူများထံမှ အီးမေးများကို လက်ခံရန်",
-       "prefs-searchoptions": "ရှာ​ဖွေ​ရန်​",
+       "prefs-searchoptions": "ရှာဖွေရန်",
        "prefs-namespaces": "အမည်ညွှန်း",
        "default": "ပုံမှန်အားဖြင့်",
        "prefs-files": "ဖိုင်",
        "right-sendemail": "အခြားအသုံးပြုသူများကို အီးမေးပို့ရန်",
        "grant-editmywatchlist": "သင့် စောင့်ကြည့်စာရင်းကို တည်းဖြတ်ရန်",
        "newuserlogpage": "အသုံးပြုသူအသစ်ရောက်လာခြင်း မှတ်တမ်း",
-       "newuserlogpagetext": "á\80¤á\80\9eá\80\8aá\80ºá\80\99á\80¾á\80¬ á\80¡á\80\9eá\80¯á\80¶á\80¸á\80\95á\80¼á\80¯á\80\9eá\80°á\80¡á\80\9eá\80\85á\80º á\80\96á\80\90်တီးမှု မှတ်တမ်း ဖြစ်သည်။",
+       "newuserlogpagetext": "á\80¤á\80\9eá\80\8aá\80ºá\80\99á\80¾á\80¬ á\80¡á\80\9eá\80¯á\80¶á\80¸á\80\95á\80¼á\80¯á\80\9eá\80°á\80¡á\80\9eá\80\85á\80º á\80\96á\80\94်တီးမှု မှတ်တမ်း ဖြစ်သည်။",
        "rightslog": "အသုံးပြုသူ၏ အခွင့်အရေးများ မှတ်တမ်း",
        "rightslogtext": "ဤသည်မှာ အသုံးပြုသူအခွင့်အရေးများ၏ ပြောင်းလဲမှုများမှတ်တမ်းဖြစ်သည်။",
        "action-read": "ဤစာမျက်နှာကို ဖတ်ရန်",
        "rcshowhideanons": "အမည်မသိ အသုံးပြုသူ $1ရန်",
        "rcshowhideanons-show": "ပြသရန်",
        "rcshowhideanons-hide": "ဝှက်",
-       "rcshowhidepatr": "á\80\85á\80±á\80¬á\80\84á\80·á\80ºá\80¼á\80\80ပ်တည်းဖြတ်မှု $1ရန်",
+       "rcshowhidepatr": "á\80\85á\80±á\80¬á\80\84á\80·á\80ºá\80\80á\80¼ပ်တည်းဖြတ်မှု $1ရန်",
        "rcshowhidepatr-show": "ပြသရန်",
        "rcshowhidepatr-hide": "ဝှက်ရန်",
        "rcshowhidemine": "ကျွန်ုပ်တည်းဖြတ်ထားသည်များ $1",
        "recentchangeslinked-page": "စာမျက်နှာ အမည် -",
        "recentchangeslinked-to": "ပေးထားသော စာမျက်နှာများအစား လင့်များနှင့် ဆက်စပ်နေသာ စာမျက်နှာများ၏ အပြောင်းအလဲများကို ပြရန်",
        "recentchanges-page-added-to-category": "ကဏ္ဍထဲသို့ [[:$1]] ကို ပေါင်းထည့်ခဲ့သည်",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] နှင့် {{PLURAL:$2|စာမျက်နှာ တစ်ခု|စာမျက်နှာ $2 ခု}}ကို ကဏ္ဍထဲသို့ ပေါင်းထည့်ခဲ့သည်",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] နှင့် [[Special:WhatLinksHere/$1|{{PLURAL:$2|စာမျက်နှာ တစ်ခု|စာမျက်နှာ $2 ခု}}]]ကို ကဏ္ဍထဲသို့ ပေါင်းထည့်ခဲ့သည်",
        "recentchanges-page-removed-from-category": "ကဏ္ဍထဲမှ [[:$1]] ကို ဖယ်ရှားခဲ့သည်",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] နှင့် {{PLURAL:$2|စာမျက်နှာ တစ်ခု|စာမျက်နှာ $2 ခု}}ကို ကဏ္ဍထဲမှ ဖယ်ရှားခဲ့သည်",
        "upload": "ဖိုင်​တင်​ရန်​",
        "upload-preferred": "အလေးပေးထားသော ဖိုင် {{PLURAL:$2|အမျိုးအစား|အမျိုးအစားများ}}: $1။",
        "upload-prohibited": "တားမြစ်ထားသော ဖိုင် {{PLURAL:$2|အမျိုးအစား|အမျိုးအစားများ}}: $1။",
        "uploadlogpage": "Upload တင်သည့် မှတ်တမ်း",
+       "uploadlogpagetext": "အောက်ပါတို့သည် မကြာမီက upload လုပ်ထားသော ဖိုင်စာရင်း ဖြစ်သည်။\nပိုမို၍ ခြုံငုံသုံးသပ်ကြည့်ရှုနိုင်ရန် [[Special:NewFiles|ဖိုင်အသစ်များ ပြခန်း]]ကို ကြည့်ပါ။",
        "filename": "ဖိုင်အမည်",
        "filedesc": "အ​ကျဉ်း​ချုပ်​",
        "fileuploadsummary": "အ​ကျဉ်း​ချုပ်​ -",
        "statistics-edits-average": "စာတစ်မျက်နှာလျှင် ပျမ်းမျှတည်းဖြတ်မှုနှုန်း",
        "statistics-users": "မှတ်ပုံတင်ထားသော [[Special:ListUsers|အသုံးပြုသူများ]]",
        "statistics-users-active": "လက်ရှိလုပ်ကိုင်နေသော အသုံးပြုသူများ",
+       "statistics-users-active-desc": "နောက်ဆုံး {{PLURAL:$1|ရက်|$1 ရက်}}အတွင်း ဆောင်ရွက်ချက်ရှိသည့် အသုံးပြုသူများ",
        "doubleredirects": "နှစ်ဆင့်ပြန် ပြန်ညွှန်းများ",
        "double-redirect-fixed-move": "[[$1]] ကို ရွှေ့ပြောင်းပြီးဖြစ်သည်။ ၎င်းအား အလိုအလျောက် ပြင်ဆင်ပြီး [[$2]] သို့ ပြန်ညွှန်းထားသည်။",
        "brokenredirects": "ကျိုးပျက်နေသော ပြန်ညွှန်းများ",
        "log": "မှတ်​တမ်း​များ​",
        "logeventslist-submit": "ပြသရန်",
        "all-logs-page": "အများနှင့်ဆိုင်သောမှတ်တမ်းအားလုံး",
+       "alllogstext": "{{SITENAME}}၏ ရရှိနိုင်သော မှတ်တမ်းများအားလုံး ပေါင်းစည်းပြသခြင်း ဖြစ်သည်။\nမှတ်တမ်းအမျိုးအစား၊ အသုံးပြုသူအမည် (စာလုံးအကြီးအသေး)၊ သို့မဟုတ် သက်ဆိုင်ရာ စာမျက်နှာ (စာလုံးအကြီးအသေး) ကို ရွေးချယ်ခြင်းဖြင့် ကြည့်ရှုမှုကို အကျဉ်းချုံးနိုင်ပါသည်။",
+       "logempty": "မှတ်တမ်းထဲတွင် ကိုက်ညီသော အရာများ မရှိပါ။",
        "allpages": "စာမျက်နှာအားလုံး",
        "nextpage": "နောက်ထပ်စာမျက်နှာ ($1)",
        "prevpage": "ယခင် စာမျက်နှာ ($1)",
        "linksearch": "ပြင်ပလင့်ခ်များ ရှာဖွေ",
        "linksearch-pat": "ရှာသည့်ပုံစံ -",
        "linksearch-ns": "အမည်ညွှန်း -",
-       "linksearch-ok": "ရှာ​ဖွေ​ရန်​",
+       "linksearch-ok": "ရှာဖွေရန်",
        "linksearch-line": "$1 သည် $2 မှ လင့်ချိတ်ထားသည်",
        "listusersfrom": "ဤမှစသော အသုံးပြုသူများကို ပြရန် -",
        "listusers-submit": "ပြ",
        "listusers-noresult": "အသုံးပြုသူ မတွေ့ပါ။",
        "listusers-blocked": "(ပိတ်ပင်ထားသည်)",
        "activeusers": "တက်ကြွလှုပ်ရှားသည့် အသုံးပြုသူစာရင်း",
+       "activeusers-intro": "ဤသည်မှာ နောက်ဆုံး $1 {{PLURAL:$1|ရက်|ရက်}}အတွင်း တက်ကြွလှုပ်ရှားသည့် အသုံးပြုသူများ စာရင်း ဖြစ်သည်။",
        "activeusers-from": "ဤမှစသော အသုံးပြုသူများကို ပြရန် -",
        "activeusers-hidebots": "ဘော့များကို ဝှက်ရန်",
        "activeusers-hidesysops": "အက်ဒမင်များကို ဝှက်ရန်",
        "notanarticle": "မာတိကာစာမျက်နှာတစ်ခု မဟုတ်",
        "watchlist-details": "{{PLURAL:$1|စာမျက်နှာ $1 ခု|စာမျက်နှာ $1 ခု}} သည် သင့်စောင့်ကြည့်စာရင်းတွင် ရှိပြီး ဆွေးနွေးချက်စာမျက်နှာများကို ထည့်တွက် မထားပါ။",
        "wlheader-showupdated": "သင် နောက်ဆုံးကြည့်ရှုခဲ့ပြီးနောက် ပြောင်းလဲမှုရှိခဲ့သော စာမျက်နှာများကို <strong>စာလုံးမဲ</strong> ဖြင့် ပြသထားသည်",
+       "wlnote": "အောက်ပါတို့သည် $3၊ $4 အထိ နောက်ဆုံး {{PLURAL:$2|နာရီ|<strong>$2</strong> နာရီ}}အတွင်း {{PLURAL:$1|နောက်ဆုံးပြောင်းလဲချက် တစ်ခု|နောက်ဆုံးပြောင်းလဲချက်များ <strong>$1</strong> ခု}} ဖြစ်သည်။",
        "wlshowlast": "နောက်ဆုံး $1 နာရီ $2 ရက်  ကိုပြရန်",
        "watchlist-hide": "ဝှက်",
        "watchlist-submit": "ပြသရန်",
+       "wlshowtime": "ပြသပေးရမည့် အချိန်ကာလ:",
        "wlshowhideminor": "အရေးမကြီးသော ပြင်ဆင်မှုများ",
        "wlshowhideliu": "မှတ်ပုံတင်ထားသော အသုံးပြုသူများ",
        "wlshowhideanons": "အမည်မသိ အသုံးပြုသူများ",
+       "wlshowhidemine": "ကျွန်ုပ်၏ တည်းဖြတ်မှုများ",
        "wlshowhidecategorization": "စာမျက်နှာ ကဏ္ဍထည့်သွင်းခြင်း",
        "watchlist-options": "စောင့်ကြည့်စာရင်းအတွက် ရွေးချယ်စရာများ",
        "watching": "စောင့်ကြည့်လျက်ရှိ...",
        "excontentauthor": "ပါဝင်အကြောင်းအရာမှာ - \"$1\"၊ ဖြစ်ပြီး တစ်ဦးတည်းသော အကူအညီပေးအပ်သူမှာ \"[[Special:Contributions/$2|$2]]\" ([[User talk:$2|ဆွေးနွေး]])  ဖြစ်သည်",
        "delete-confirm": "\"$1\"ကို ဖျက်ပါ",
        "delete-legend": "ဖျက်",
+       "historywarning": "<strong>သတိပေးချက်။</strong> သင်ဖျက်ပစ်တော့မည့် စာမျက်နှာတွင် {{PLURAL:$1|တည်းဖြတ်မူ|တည်းဖြတ်မူများ}} $1 ခု ရှိနေသည်-",
        "historyaction-submit": "ပြသရန်",
        "confirmdeletetext": "သင်သည် စာမျက်နှာတစ်ခုကို ယင်း၏ မှတ်တမ်းများနှင့်တကွ ဖျက်ပစ်တော့မည် ဖြစ်သည်။\nဤသို့ ဖျက်ပစ်ရန် သင် အမှန်တကယ် ရည်ရွယ်လျက်  နောက်ဆက်တွဲ အကျိုးဆက်များကို သိရှိနားလည်ပြီး [[{{MediaWiki:Policy-url}}|မူဝါဒ]] အတိုင်းလုပ်ဆောင်နေခြင်းဖြစ်ကြောင်းကို အတည်ပြုပေးပါ။",
        "actioncomplete": "လုပ်ဆောင်ချက် ပြီးပြီ",
        "actionfailed": "ဆောင်ရွက်မှုမအောင်မြင်ပါ",
        "deletedtext": "\"$1\" ကို ဖျက်ပစ်လိုက်ပြီးဖြစ်သည်။\nလတ်တလောဖျက်ထားသည်များ၏ မှတ်တမ်းကို $2 တွင် ကြည့်ပါ။",
        "dellogpage": "ဖျက်ထားသည်များ မှတ်တမ်း",
+       "dellogpagetext": "အောက်ပါတို့သည် မကြာမီက ဖျက်ထားမှုများ စာရင်း ဖြစ်သည်။",
        "deletionlog": "ဖျက်ပစ်သည့်မှတ်တမ်း",
        "deletecomment": "အ​ကြောင်း​ပြ​ချက် -",
        "deleteotherreason": "အခြားသော/နောက်ထပ် အကြောင်းပြချက် -",
        "rollbacklink": "နောက်ပြန် ပြန်သွားရန်",
        "rollbacklinkcount": "{{PLURAL:$1|တည်းဖြတ်မှု|တည်းဖြတ်မှုများ}} $1 ကို နောက်ပြန်ပြင်ရန်",
        "protectlogpage": "ကာကွယ်မှုများ၏ မှတ်တမ်း",
+       "protectlogtext": "အောက်ပါတို့သည် စာမျက်နှာ ကာကွယ်မှုများအတွက် အပြောင်းအလဲ စာရင်း ဖြစ်သည်။\nလက်ရှိ စာမျက်နှာ ကာကွယ်မှုများ စာရင်းအတွက် [[Special:ProtectedPages|ကာကွယ်ထားသော စာမျက်နှာများ စာရင်း]]ကို ကြည့်ပါ။",
        "protectedarticle": "\"[[$1]]\" ကို ကာကွယ်ထားသည်",
        "modifiedarticleprotection": "\"[[$1]]\" ၏ ကာကွယ်မှု အဆင့်ကို ပြောင်းရန်",
        "protect-title": "\"$1\" ၏ ကာကွယ်မှုအဆင့်ကို ပြောင်းလဲရန်",
        "prot_1movedto2": "[[$1]]  မှ​ [[$2]] သို့​",
+       "protect-legend": "ကာကွယ်မှု အတည်ပြုရန်",
        "protectcomment": "အ​ကြောင်း​ပြ​ချက်:",
        "protectexpiry": "သက်တမ်းကုန်လွန်မည် -",
        "protect_expiry_invalid": "သက်တမ်းကုန်လွန်မည့် အချိန်သည် တရားမဝင်ပါ။",
        "protect_expiry_old": "သက်တမ်းသည် အတိတ်ကာလတွင် ကုန်လွန်ခဲ့ပြီး ဖြစ်သည်။",
+       "protect-unchain-permissions": "နောက်ထပ် ကာကွယ်မှု ရွေးချယ်စရာများ ဖော်ပြရန်",
        "protect-text": "'''$1''' စာမျက်နှာအတွက် ကာကွယ်မှုအဆင့်ကို ဤနေရာတွင် ကြည့်ရှုပြောင်းလဲနိုင်သည်။",
        "protect-locked-access": "သင့်အကောင့်သည် စာမျက်နှာ၏ ကာကွယ်မှုအဆင့်ကို ပြောင်းလဲနိုင်ရန် ခွင့်ပြုချက် မရှိပါ။\nဤသည်မှာ '''$1''' စာမျက်နှာအတွက် လက်ရှိ settings သတ်မှတ်ချက်များ ဖြစ်သည်။",
        "protect-cascadeon": "ပြန်စီစဉ်ခြင်း cascading ကို ကာကွယ်ထားသော အောက်ပါ{{PLURAL:$1|စာမျက်နှာ|စာမျက်နှာများ}} ပါဝင်နေသောကြောင့် ဤစာမျက်နှာကို လက်ရှိတွင် ကာကွယ်ထားသည်။\nဤစာမျက်နှာ၏ ကာကွယ်မှုအဆင့်ကို ပြောင်းလဲသော်လည်း ပြန်စီစဉ်ခြင်းကို အကျိုးသက်ရောက်လိမ့်မည် မဟုတ်။",
        "protect-level-sysop": "စီမံခန့်ခွဲသူများသာ",
        "protect-summary-cascade": "အစီအစဉ်ကျအောင် စီနေသည်",
        "protect-expiring": "$1 (UTC) တွင် သက်တမ်းကုန်မည်",
+       "protect-expiry-indefinite": "အနန္တ",
        "protect-cascade": "ဤစာမျက်နှာအတွင်း ပါဝင်သော စာမျက်နှာများကို ထိန်းသိမ်းကာကွယ်ပါ (အများခွင့်ပြုချက်ဖြင့်သာ ပြင်ဆင်သင့်သည်)",
        "protect-cantedit": "ကာကွယ်ထားသောစာမျက်နှာဖြစ်သည့်အတွက် ပြင်ဆင်၍ မရနိုင်ပါ။ အဘယ့်ကြောင့်ဆိုသော် သင့်မှာ တည်းဖြတ်ပိုင်ခွင့် မရှိ၍ ဖြစ်ပါသည်။",
        "protect-otherreason": "အခြားသော/နောက်ထပ် အကြောင်းပြချက် -",
        "undeletecomment": "အ​ကြောင်း​ပြ​ချက် -",
        "undeletedrevisions": "{{PLURAL:$1|မူတစ်ခု|မူ $1 ခု}} ကိုပြန်လည် ထိန်းသိမ်းပြီး",
        "undelete-search-box": "ဖျက်ပစ်သည့် စာမျက်နှာများမှ ရှာရန်",
-       "undelete-search-submit": "ရှာ​ဖွေ​ရန်​",
+       "undelete-search-submit": "ရှာဖွေရန်",
        "undelete-show-file-submit": "မှန်",
        "namespace": "အမည်ညွှန်း -",
        "invert": "ရွေးချယ်ထားခြင်းကို ပြောင်းပြန်လှန်ရန်",
        "sp-contributions-search": "ပံ့ပိုးမှုများကို ရှာရန်",
        "sp-contributions-username": "အိုင်ပီလိပ်စာ သို့ အသုံးပြုသူအမည် :",
        "sp-contributions-toponly": "နောက်ဆုံးတည်းဖြတ်မူများသာပြရန်",
-       "sp-contributions-submit": "ရှာ​ဖွေ​ရန်​",
+       "sp-contributions-submit": "ရှာဖွေရန်",
        "whatlinkshere": "ဘယ်ကလင့်ခ်ထားလဲ",
        "whatlinkshere-title": "\"$1\" ကို လင့်ထားသော စာမျက်နှာများ",
        "whatlinkshere-page": "စာမျက်နှာ -",
        "whatlinkshere-prev": "{{PLURAL:$1|နောက်သို့|နောက်သို့ $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|ရှေ့သို့|ရှေ့သို့ $1}}",
        "whatlinkshere-links": "← လင့်များ",
-       "whatlinkshere-hideredirs": "redirect ပြန်ညွှန်း $1 ခု",
+       "whatlinkshere-hideredirs": "ပြန်ညွှန်းများ $1ရန်",
        "whatlinkshere-hidetrans": "ထည့်သွင်းကူးယူချက် $1 ခု",
        "whatlinkshere-hidelinks": "လင့် $1 ခု",
        "whatlinkshere-hideimages": "ဖိုင်အချိတ်အဆက်များ $1 ခု",
        "blocklist": "ပိတ်ပင်ထားသော အသုံးပြုသူများ",
        "ipblocklist": "ပိတ်ပင်ထားသော အသုံးပြုသူများ",
        "ipblocklist-legend": "ပိတ်ပင်ထားသော အသုံးပြုသူတစ်ဦးကို ရှာရန်",
-       "ipblocklist-submit": "ရှာ​ဖွေ​ရန်​",
+       "ipblocklist-submit": "ရှာဖွေရန်",
        "ipblocklist-otherblocks": "အခြား ပိတ်ပင်ထားမှု{{PLURAL:$1|ခု|ခု}}",
        "infiniteblock": "အကန့်အသတ်မရှိ",
        "expiringblock": "$1 ရက် $2 အချိန်တွင် သက်တမ်းကုန်မည်",
        "contribslink": "ပံ့ပိုး",
        "blocklogpage": "ပိတ်ပင်တားဆီးမှု မှတ်တမ်း",
        "blocklogentry": "[[$1]] ကို $2 ကြာအောင် ပိတ်ပင် တားဆီးလိုက်သည် $3",
+       "blocklogtext": "ဤသည်မှာ အသုံးပြုသူအား ပိတ်ပင်ခြင်းနှင့် ပိတ်ပင်မှုဖယ်ရှားခြင်း ဆောင်ရွက်မှု မှတ်တမ်း ဖြစ်သည်။\nအလိုအလျောက် ပိတ်ပင်ထားသည့် အိုင်ပီလိပ်စာများအား မထည့်သွင်းထားပါ။\nလက်ရှိ တားမြစ်မှုများနှင့် ပိတ်ပင်မှုများ စာရင်းအတွက် [[Special:BlockList|ပိတ်ပင်စာရင်း]]ကို ကြည့်ပါ။",
        "unblocklogentry": "$1 ကို ပိတ်ထားရာမှ ပြန်ဖွင့်ရန်",
        "block-log-flags-anononly": "အမည်မသိ အသုံးပြုသူများသာ",
        "block-log-flags-nocreate": "အကောင့်ဖန်တီးခြင်းကို ပိတ်ထားသည်",
        "ipb_already_blocked": "\"$1\" ကို အစကတည်းက ပိတ်ထားသည်",
        "move-page": "$1 ကို ရွှေ့ရန်",
        "move-page-legend": "စာ​မျက်​နှာ​ကို ရွှေ့ပြောင်းရန်",
-       "movepagetext": "အောက်ပါပုံစံကို အသုံးပြုခြင်းသည် စာမျက်နှာကို အမည်ပြောင်းလဲပေးမည် ဖြစ်ပြီး အမည်သစ်သို့ ယင်း၏ မှတ်တမ်းနှင့်တကွ ရွှေ့ပေးမည် ဖြစ်သည်။\nအမည်ဟောင်းသည် အမည်သစ်သို့ ပြန်ညွှန်းစာမျက်နှာ ဖြစ်လာမည်။\nသင်သည် မူလခေါင်းစဉ်သို့ ပြန်ညွှန်းများကို အလိုအလျောက် အပ်ဒိတ် update လုပ်နိုင်သည်။\nအကယ်၍ မပြုလုပ်လိုပါက [[Special:DoubleRedirects|နှစ်ခါထပ်]][[Special:BrokenRedirects|ပြန်ညွှန်း အပျက်များ]] ကို မှတ်သားရန် မမေ့ပါနှင့်။\nလင့်များ ညွှန်းလိုသည့် နေရာသို့ ညွှန်ပြနေရန် သင့်တွင် တာဝန် ရှိသည်။\n\nအကယ်၍ ခေါင်းစဉ်အသစ်တွင် စာမျက်နှာတစ်ခု ရှိနှင့်ပြီး ဖြစ်ပါက (သို့) ယင်းစာမျက်နှာသည် အလွတ်မဖြစ်ပါက (သို့) ပြန်ညွှန်းတစ်ခု မရှိပါက (သို့) ယခင်က ပြုပြင်ထားသော မှတ်တမ်း မရှိပါက စာမျက်နှာသည် <strong>ရွေ့မည်မဟုတ်</strong> သည်ကို သတိပြုပါ။ \nဆိုလိုသည်မှာ သင်သည် အမှားတစ်ခု ပြုလုပ်မိပါက စာမျက်နှာကို ယခင်အမည်ကို ပြန်လည် ပြောင်းလဲပေးနိုင်သည်။ ရှိပြီသားစာမျက်နှာတစ်ခုကို စာမျက်နှာ အသစ်နှင့် ပြန်အုပ် overwrite ခြင်း မပြုနိုင်။\n\n<strong>မှတ်ချက်။</strong>\nဤသည်မှာ လူဖတ်များသော စာမျက်နှာတစ်ခုဖြစ်ပါက မမျှော်လင့်ထားသော၊ ကြီးမားသော အပြောင်းအလဲတစ်ခု ဖြစ်ပေါ်လာနိုင်သည်။\nထို့ကြောင့် ဆက်လက် မဆောင်ရွက်မီ သင်သည် နောက်ဆက်တွဲ အကျိုးဆက်များကို နားလည်ကြောင်း ကျေးဇူးပြု၍ သေချာပါစေ။",
+       "movepagetext": "အောက်ပါပုံစံကို အသုံးပြုခြင်းသည် စာမျက်နှာကို အမည်ပြောင်းလဲပေးမည် ဖြစ်ပြီး အမည်သစ်သို့ ယင်း၏ မှတ်တမ်းနှင့်တကွ ရွှေ့ပေးမည် ဖြစ်သည်။\nအမည်ဟောင်းသည် အမည်သစ်သို့ ပြန်ညွှန်းစာမျက်နှာ ဖြစ်လာမည်။\nသင်သည် မူလခေါင်းစဉ်သို့ ပြန်ညွှန်းများကို အလိုအလျောက် အပ်ဒိတ် update လုပ်နိုင်သည်။\nအကယ်၍ မပြုလုပ်လိုပါက [[Special:DoubleRedirects|နှစ်ဆင့်ပြန်ညွှန်းများ]] သို့မဟုတ် [[Special:BrokenRedirects|ပြန်ညွှန်း အပျက်များ]] ကို မှတ်သားရန် မမေ့ပါနှင့်။\nလင့်များ ညွှန်းလိုသည့် နေရာသို့ ညွှန်ပြနေရန် သင့်တွင် တာဝန် ရှိသည်။\n\nအကယ်၍ ခေါင်းစဉ်အသစ်တွင် စာမျက်နှာတစ်ခု ရှိနှင့်ပြီး ဖြစ်ပါက (သို့) ယင်းစာမျက်နှာသည် အလွတ်မဖြစ်ပါက (သို့) ပြန်ညွှန်းတစ်ခု မရှိပါက (သို့) ယခင်က ပြုပြင်ထားသော မှတ်တမ်း မရှိပါက စာမျက်နှာသည် <strong>ရွေ့မည်မဟုတ်</strong> သည်ကို သတိပြုပါ။ \nဆိုလိုသည်မှာ သင်သည် အမှားတစ်ခု ပြုလုပ်မိပါက စာမျက်နှာကို ယခင်အမည်ကို ပြန်လည် ပြောင်းလဲပေးနိုင်သည်။ ရှိပြီသားစာမျက်နှာတစ်ခုကို စာမျက်နှာ အသစ်နှင့် ပြန်အုပ် overwrite ခြင်း မပြုနိုင်။\n\n<strong>မှတ်ချက်။</strong>\nဤသည်မှာ လူဖတ်များသော စာမျက်နှာတစ်ခုဖြစ်ပါက မမျှော်လင့်ထားသော၊ ကြီးမားသော အပြောင်းအလဲတစ်ခု ဖြစ်ပေါ်လာနိုင်သည်။\nထို့ကြောင့် ဆက်လက် မဆောင်ရွက်မီ သင်သည် နောက်ဆက်တွဲ အကျိုးဆက်များကို နားလည်ကြောင်း ကျေးဇူးပြု၍ သေချာပါစေ။",
+       "movepagetext-noredirectfixer": "အောက်ပါပုံစံကို အသုံးပြုခြင်းသည် စာမျက်နှာကို အမည်ပြောင်းလဲပေးမည် ဖြစ်ပြီး အမည်သစ်သို့ ယင်း၏ မှတ်တမ်းနှင့်တကွ ရွှေ့ပေးမည် ဖြစ်သည်။\n[[Special:DoubleRedirects|နှစ်ဆင့်ပြန်ညွှန်းများ]] သို့မဟုတ် [[Special:BrokenRedirects|ပြန်ညွှန်း အပျက်များ]] ကို စစ်ဆေးရန် မမေ့ပါနှင့်။\nလင့်ခ်များ ညွှန်းလိုသည့် နေရာသို့ ညွှန်ပြနေရန် သင့်တွင် တာဝန် ရှိသည်။\n\nအကယ်၍ ခေါင်းစဉ်အသစ်တွင် စာမျက်နှာတစ်ခု ရှိနေနှင့်ပြီး ပြန်ညွှန်းတစ်ခု မရှိပါက သို့မဟုတ် ယခင်က ပြုပြင်ထားသော မှတ်တမ်း ရှိနေပါက စာမျက်နှာသည် <strong>ရွေ့မည်မဟုတ်</strong> သည်ကို သတိပြုပါ။ \nဆိုလိုသည်မှာ သင်သည် အမှားတစ်ခု ပြုလုပ်မိပါက စာမျက်နှာကို ယခင်အမည်ကို ပြန်လည် ပြောင်းလဲပေးနိုင်သည်။ ရှိပြီသားစာမျက်နှာတစ်ခုကို စာမျက်နှာ အသစ်နှင့် ပြန်အုပ် overwrite ခြင်း မပြုနိုင်။\n\n<strong>မှတ်ချက်။</strong>\nဤသည်မှာ လူဖတ်များသော စာမျက်နှာတစ်ခုဖြစ်ပါက မမျှော်လင့်ထားသော၊ ကြီးမားသော အပြောင်းအလဲတစ်ခု ဖြစ်ပေါ်လာနိုင်သည်။\nထို့ကြောင့် ဆက်လက် မဆောင်ရွက်မီ သင်သည် နောက်ဆက်တွဲ အကျိုးဆက်များကို နားလည်ကြောင်း ကျေးဇူးပြု၍ သေချာပါစေ။",
        "movepagetalktext": "ဤအကွက်ကို အမှန်ခြစ်လိုက်ခြင်းဖြင့် ဗလာမဟုတ်သော ဆွေးနွေးချက်စာမျက်နှာသည် ရှိနှင့်ပြီး မဟုတ်လျှင် ဆက်နွယ်နေသော ဆွေးနွေးချက် စာမျက်နှာကို ခေါင်းစဉ်အသစ်သို့  အလိုအလျောက် ရွှေ့ပစ်မည် ဖြစ်သည်။\n\nဤကိစ္စရပ်တွင် သင် ဆန္ဒရှိလျှင် စာမျက်နှာကို မိမိကိုယ်တိုင် သွားရောက်ရွှေ့ပြောင်း ပေါင်းစပ်နိုင်သည်။",
        "newtitle": "ခေါင်းစဉ်အသစ်:",
        "move-watch": "မူရင်းစာမျက်နှာနှင့် ဦးတည်ထားသော စာမျက်နှာတို့ကို စောင့်ကြည့်ရန်",
        "pagemovedsub": "ပြောင်းရွှေ့ခြင်းအောင်မြင်သည်",
        "movepage-moved": "'''\"$1\" ကို \"$2\" သို့ ရွှေ့ပြီးဖြစ်သည်'''",
        "movepage-moved-redirect": "ပြန်ညွှန်းတစ်ခုကို ဖန်တီးပြီးဖြစ်သည်။",
+       "movepage-moved-noredirect": "ပြန်ညွှန်းဖန်တီးခြင်းအား ချေဖျက်ပြီး ဖြစ်သည်။",
        "articleexists": "ထိုအမည်ဖြင့် စာမျက်နှာတစ်ခု ရှိနှင့်ပြီးဖြစ်သည် (သို့) သင်ရွေးလိုက်သော အမည်သည် တရားမဝင်ပါ။\nကျေးဇူးပြု၍ အခြားအမည်တစ်ခုကို ရွေးပေးပါ။",
        "movetalk": "ယှက်နွယ်နေသော ဆွေးနွေးချက်စာမျက်နှာများကို ရွှေ့ရန်",
        "movepage-page-moved": "စာမျက်နှာ $1 ကို $2 သို့ ရွှေ့ပြီးပြီ ဖြစ်သည်။",
        "movepage-page-unmoved": "စာမျက်နှာ $1 ကို $2 သို့ ရွှေ့မရနိုင်ပါ။",
        "movelogpage": "ရွှေ့ပြောင်းခြင်း မှတ်တမ်း",
+       "movelogpagetext": "အောက်ပါတို့သည် စာမျက်နှာ ရွေ့ပြောင်းမှုများ အားလုံး စာရင်း ဖြစ်သည်။",
        "movereason": "အ​ကြောင်း​ပြ​ချက် -",
        "revertmove": "ပြောင်းရန်",
        "delete_and_move_confirm": "ဟုတ်ပါသည်။ စာမျက်နှာကို ဖျက်ပါ။",
        "immobile-source-page": "ဤစာမျက်နှာကို ရွှေ့မရပါ။",
+       "move-leave-redirect": "ပြန်ညွှန်းတစ်ခု ချန်ထားရန်",
        "export": "စာမျက်နှာများကို Export ထုတ်ရန်",
        "export-submit": "Export ထုတ်ရန်",
        "export-addcattext": "ကဏ္ဍမှ စာမျက်နှာများကို ပေါင်းထည့်ရန် -",
        "tooltip-ca-move": "ဤစာမျက်နှာကို ရွှေ့ပြောင်းရန်",
        "tooltip-ca-watch": "ဤစာမျက်နှာကို စောင့်ကြည့်စာရင်းသို့ ထည့်ရန်",
        "tooltip-ca-unwatch": "ဤစာမျက်နှာကို စောင့်ကြည့်စာရင်းမှ ဖြုတ်ရန်",
-       "tooltip-search": "{{SITENAME}}á\80\80á\80­á\80¯ á\80\9bá\80¾á\80¬ရန်",
+       "tooltip-search": "{{SITENAME}}á\80\90á\80½á\80\84á\80º á\80\9bá\80¾á\80¬á\80\96á\80½á\80±ရန်",
        "tooltip-search-go": "ဤအမည်နှင့် ထပ်တူညီသော စာမျက်နှာရှိပါက ယင်းသို့ သွားရန်",
        "tooltip-search-fulltext": "ဤစာပါသော စာမျက်နှာများကို ရှာရန်",
        "tooltip-p-logo": "ဗဟိုစာမျက်နှာသို့ သွားရန်",
        "newimages-legend": "စိစစ်မှု",
        "newimages-label": "ဖိုင်အမည် (သို့ ယင်း၏အစိတ်အပိုင်း) -",
        "noimages": "ကြည့်စရာဘာမှ မရှိပါ။",
-       "ilsubmit": "ရှာ​ဖွေ​ရန်​",
+       "ilsubmit": "ရှာဖွေရန်",
        "bydate": "ရက်စွဲဖြိင့်",
        "sp-newimages-showfrom": "$1 နေ့ $2 အချိန်ကစသော ဖိုင်အသစ်များကို ပြရန်",
        "bad_image_list": "ဖောမတ်ပုံစံမှာ အောက်ပါအတိုင်းဖြစ်သည်။\n\nစာရင်းတွင်ထည့်သွင်းထားသော အရာများကိုသာ ထည့်သွင်းစဉ်းစားမည်။ (ခရေပွင့် * ဖြင့်စသော စာကြောင်းများ)\nစာကြောင်း၏ ပထမဆုံး လင့်သည် ဖိုင်ညံ့ ဖြစ်ရမည်။\nယင်းစာကြောင်းတွင်ပင် နောက်ထပ်လာသောလင့်များကို ချွင်းချက်အဖြစ် စဉ်းစားမည်။ ဆိုလိုသည်မှာ ၎င်းလင့်များတွင်လည်း အဆိုပါ ဖိုင်ညံ့ ပါကောင်း ပါဝင်နေမည်။",
        "autosumm-new": "\"$1\" အစချီသော စာလုံးတို့နှင့် စာမျက်နှာကို ဖန်တီးလိုက်သည်",
        "watchlistedit-normal-title": "စောင့်ကြည့်စာရင်းကို တည်းဖြတ်ရန်",
        "watchlistedit-normal-legend": "စောင့်ကြည့်စာရင်းမှ ခေါင်းစဉ်များကို ဖျက်ရန်",
+       "watchlistedit-normal-explain": "သင်၏ စောင့်ကြည့်စာရင်းရှိ ခေါင်းစဉ်များကို အောက်တွင် ပြသထားသည်။\nခေါင်းစဉ်တစ်ခုကို ဖယ်ရှားရန် ထိုခေါင်းစဉ်ဘေးရှိ အကွက်တွင် အမှန်ခြစ်ပြီး \"{{int:Watchlistedit-normal-submit}}\" ကိုနှိပ်ပါ။\n[[Special:EditWatchlist/raw|စောင့်ကြည့်စာရင်း အကြမ်း]]ကိုလည်း ကြည့်နိုင်ပါသည်။",
        "watchlistedit-normal-submit": "ခေါင်းစဉ်များကို ဖယ်ရှားရန်",
+       "watchlistedit-normal-done": "{{PLURAL:$1|ခေါင်းစဉ်တစ်ခု|ခေါင်းစဉ် $1 ခုတို့}}ကို သင်၏ စောင့်ကြည့်စာရင်းမှ ဖယ်ရှားပြီးပြီ:",
        "watchlistedit-raw-titles": "ခေါင်းစဉ်များ -",
        "watchlisttools-view": "ကိုက်ညီသော အပြောင်းအလဲများကို ကြည့်ရန်",
        "watchlisttools-edit": "စောင့်ကြည့်စာရင်းများကို ကြည့်ပြီး တည်းဖြတ်ပါ။",
        "fileduplicatesearch": "နှစ်ခုထပ်နေသောဖိုင်များကို ရှာရန်",
        "fileduplicatesearch-legend": "နှစ်ခုထပ်နေသည်ကို ရှာရန်",
        "fileduplicatesearch-filename": "ဖိုင်အမည် -",
-       "fileduplicatesearch-submit": "ရှာ​ဖွေ​ရန်​",
+       "fileduplicatesearch-submit": "ရှာဖွေရန်",
        "specialpages": "အ​ထူး ​စာ​မျက်​နှာ​များ",
        "specialpages-group-maintenance": "ထိန်းသိမ်းမှု အစီရင်ခံချက်များ",
        "specialpages-group-other": "အခြားအထူးစာမျက်နှာများ",
        "htmlform-reset": "ပြောင်းလဲထားသည်များ မလုပ်တော့ရန်",
        "htmlform-selectorother-other": "အခြား",
        "logentry-delete-delete": "$3 စာမျက်နှာကို $1 က {{GENDER:$2|ဖျက်ပစ်ခဲ့သည်}}",
+       "logentry-delete-revision": "$3 စာမျက်နှာပေါ်ရှိ {{PLURAL:$5|တည်းဖြတ်မူတစ်ခု|တည်းဖြတ်မူ $5 ခု}}၏ အမြင်ပုံစံကို $1 က {{GENDER:$2|ပြောင်းလဲခဲ့သည်}}: $4",
+       "revdelete-content-hid": "အကြောင်းအရာ ဝှက်ခြင်း",
        "revdelete-restricted": "အက်ဒမင်များသို့ ကန့်သတ်ချက်များ သက်ရောက်ရန်",
        "revdelete-unrestricted": "အက်ဒမင်များအတွက် ကန့်သတ်ချက်များကို ဖယ်ရှားရန်",
        "logentry-move-move": "$3 စာမျက်နှာကို $4 သို့ $1က {{GENDER:$2|ရွှေ့ခဲ့သည်}}",
+       "logentry-move-move-noredirect": "$3 မှ $4 သို့ စာမျက်နှာကို ပြန်ညွှန်းချန်မထားပဲ $1 {{GENDER:$2|က ရွှေ့ခဲ့သည်}}",
        "logentry-newusers-create": "အသုံးပြုသူအကောင့် $1 ကို {{GENDER:$2|ဖန်တီးခဲ့သည်}}",
        "logentry-upload-upload": "$1 သည် $3 ကို {{GENDER:$2|upload တင်ခဲ့သည်}}",
+       "logentry-upload-overwrite": "$3 ၏ ဗားရှင်းအသစ်ကို $1 {{GENDER:$2|upload တင်ခဲ့သည်}}",
        "rightsnone": "(ဘာမှမရှိ)",
        "revdelete-summary": "အကျဉ်းချုပ်ကို တည်းဖြတ်ရန်",
        "searchsuggest-search": "ရှာဖွေရန်",
index b4fdd36..8bcfce5 100644 (file)
@@ -14,6 +14,7 @@
        "tog-hideminor": "Am chòe-kīn ê sió kái-piàn",
        "tog-hidepatrolled": "Am chòe-kīn sûn koè--ê  kái-piàn",
        "tog-newpageshidepatrolled": "Sin-ia̍h ê chheng-toaⁿ am sûn koè--ê",
+       "tog-hidecategorization": "Kā ia̍h ê lūi-pia̍t chhàng--khì-lâi",
        "tog-extendwatchlist": "thián-khui kàm-sī-toaⁿ, khoàⁿ choân-pō͘  kái ê, m̄-nā choè-kīn niā.",
        "tog-usenewrc": "共文章最近有改的佮監視列表囥做伙",
        "tog-numberheadings": "Phiau-tê chū-tōng pian-hō",
@@ -34,7 +35,7 @@
        "tog-shownumberswatching": "Hián-sī tng leh khoàⁿ ê iōng-chiá sò͘-bo̍k",
        "tog-oldsig": "Chit-má ê chhiam-miâ:",
        "tog-fancysig": "共我的簽名當做文章文字,(無需要自動連結)",
-       "tog-uselivepreview": "Ēng sui khoàⁿ-māi (chhì-giām--ê)",
+       "tog-uselivepreview": "Ēng sui khoàⁿ-māi",
        "tog-forceeditsummary": "Pian-chi̍p khài-iàu bô thiⁿ ê sî-chūn, kā goá thê-chhéⁿ",
        "tog-watchlisthideown": "Kàm-sī-toaⁿ bián hián-sī goá ê pian-chi̍p",
        "tog-watchlisthidebots": "Kàm-sī-toaⁿ bián hián-sī ki-khì pian-chi̍p",
@@ -42,6 +43,7 @@
        "tog-watchlisthideliu": "Kàm-sī-toaⁿ bián hián-sī iōng-chiá ū teng-ji̍p ê pian-chi̍p",
        "tog-watchlisthideanons": "Kàm-sī-toaⁿ bián hián-sī bû-bêng-sī ê pian-chi̍p",
        "tog-watchlisthidepatrolled": "Kàm-sī-toaⁿ bián hián-sī khoàⁿ-koè--ê pian-chi̍p",
+       "tog-watchlisthidecategorization": "Kā ia̍h ê lūi-pia̍t chhàng--khì-lâi",
        "tog-ccmeonemails": "Kià hō͘ pa̍t-lâng ê email sūn-soà kià copy hō͘ goá",
        "tog-diffonly": "Diff ē-pêng bián hián-sī ia̍h ê loē-iông",
        "tog-showhiddencats": "Hián-sī chhàng khí--lâi ê lūi-pia̍t",
        "october-date": "10月$1",
        "november-date": "11月$1",
        "december-date": "12月$1",
+       "period-am": "AM",
+       "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Lūi-pia̍t|Lūi-pia̍t}}",
        "category_header": "Tī \"$1\" chit ê lūi-pia̍t ê bûn-chiuⁿ",
        "subcategories": "Ē-lūi-pia̍t",
        "morenotlisted": "這毋是完整的表",
        "mypage": "Ia̍h",
        "mytalk": "Thó-lūn",
-       "anontalk": "Chit ê IP ê thó-lūn-ia̍h",
+       "anontalk": "Thó-lūn",
        "navigation": "Se̍h chām",
        "and": "&#32;kap",
        "qbfind": "Chhōe",
        "tagline": "Ùi {{SITENAME}}",
        "help": "Soat-bêng-su",
        "search": "Chhiau-chhoē",
-       "searchbutton": "Chhiau",
+       "searchbutton": "Chh",
        "go": "Lâi-khì",
        "searcharticle": "Lâi-khì",
        "history": "Ia̍h le̍k-sú",
        "pool-queuefull": "Tūi-lia̍t pâi moá ah",
        "pool-errorunknown": "M̄-chai siáⁿ chhò-gō͘",
        "pool-servererror": "無提供系統服務總數的統計。",
+       "poolcounter-usage-error": "Ēng-hoat chhò-gō͘: $1",
        "aboutsite": "Koan-hē {{SITENAME}}",
        "aboutpage": "Project:Koan-hē",
        "copyright": "Tû liáu ū lēng-goā kóng, nā bô loē-iông sī chiàu $1 tiâu-kiāⁿ tō thang sú-iōng.",
        "disclaimers": "Bô-hū-chek seng-bêng",
        "disclaimerpage": "Project:It-poaⁿ ê seng-bêng",
        "edithelp": "Án-choáⁿ siu-kái",
+       "helppage-top-gethelp": "soat-bêng",
        "mainpage": "Thâu-ia̍h",
        "mainpage-description": "Thâu-ia̍h",
        "policy-url": "Project:Chèng-chhek",
        "toc": "Bo̍k-lo̍k",
        "showtoc": "khui",
        "hidetoc": "siu",
-       "collapsible-collapse": "Siu",
-       "collapsible-expand": "Khui",
+       "collapsible-collapse": "Am",
+       "collapsible-expand": "Hiàn",
        "confirmable-confirm": "{{GENDER:$1|你}}敢確定唅?",
        "confirmable-yes": "著啦",
        "confirmable-no": "無啦!毋是!",
        "changeemail": "Kái tiān-chú-phoe ê tē-chí",
        "changeemail-oldemail": "Chit-má ê E-mail tē-chí:",
        "changeemail-newemail": "Sin E-mail ê chū-chí:",
+       "changeemail-password": "Lí-ê {{SITENAME}} bi̍t-bé:",
+       "changeemail-submit": "Kái-piàn tiān-chu-phoe",
+       "changeemail-throttled": "Lí chi̍t-ê-á teng-ji̍p liáu siuⁿ chē kái.\nChiáⁿ tan-thāi $1 kòe-āu chài chhì chi̍t pái.",
+       "changeemail-nochange": "Chhiáⁿ su-ji̍p chi̍t-ê bô-kâng ê sin tiān-chú-phoe chū-chí.",
        "bold_sample": "Chho·-thé bûn-jī",
        "bold_tip": "Chho·-thé jī",
        "italic_sample": "Chhú-thé ê bûn-jī",
        "recreate-moveddeleted-warn": "'''Sè-jī: Lí taⁿ chún-pī beh khui ê ia̍h, chêng bat hō͘ lâng thâi tiāu koè.''' Lí tio̍h chim-chiok soà-chiap pian-chi̍p chit ia̍h ê pit-iàu-sèng. Chia ū chit ia̍h ê san-tû kì-lo̍k (deletion log) hō͘ lí chham-khó:",
        "edit-conflict": "Siu-kái sio-chhiong",
        "defaultmessagetext": "Siat piān ê bûn-jī",
+       "content-model-wikitext": "wikitext",
+       "content-model-text": "sûn bûn-pún",
+       "content-model-javascript": "JavaScript",
+       "content-json-empty-object": "Khang bu̍t-kiāⁿ",
+       "content-json-empty-array": "Khang tīn-lia̍t",
        "post-expand-template-inclusion-warning": "'''Kéng-pò:'''Pau ji̍t lâi ê pán-bôo sioⁿ koè tsē ia̍h tuā.\nŪ chi̍t-koá-á ē bô pau ji̍t lâi.",
        "undo-success": "Pian-chi̍p í-keng chhú-siau. Chhiáⁿ khak-tēng, liáu-āu kā ē-kha ho̍k-goân ê kái-piàn pó-chûn--khí-lâi.",
        "undo-failure": "Pian-chi̍p bē-tàng chhú-siau, in-ūi chhiong tio̍h kî-kan chhah-ji̍p ê pian-chi̍p.",
        "searchprofile-advanced": "chìn-chi̍t-pō͘",
        "searchprofile-articles-tooltip": "Tī $1 chhoé",
        "searchprofile-images-tooltip": "Chhoé tóng-àn",
-       "searchprofile-everything-tooltip": "Chhiau choân-pō͘ (pau-koat thó-lūn-ia̍h)",
+       "searchprofile-everything-tooltip": "Chh choân-pō͘ (pau-koat thó-lūn-ia̍h)",
        "searchprofile-advanced-tooltip": "佇你家己設的名空間內底揣",
        "search-result-size": "$1 ({{PLURAL:$2|1 jī-goân|$2 jī-goân}})",
        "search-redirect": "(轉去 $1)",
        "search-section": "(toān-lo̍h $1)",
        "searchall": "choân-pō·",
        "showingresults": "Ē-kha tùi #<b>$2</b> khai-sí hián-sī <b>$1</b> hāng kiat-kó.",
-       "search-nonefound": "揣無",
+       "search-nonefound": "Chhoē m̄ tio̍h",
        "powersearch-legend": "Kiám-sek",
        "preferences": "Siat-tēng",
        "mypreferences": "Góa ê siat-tēng",
        "localtime": "Chāi-tē sî-kan sī",
        "servertime": "Server sî-kan hiān-chāi sī",
        "guesstimezone": "Tùi liû-lám-khì chhau--lâi",
+       "timezoneregion-africa": "Hui-chiu",
+       "timezoneregion-america": "Bí-chiu",
+       "timezoneregion-antarctica": "Lâm-ke̍k-chiu",
+       "timezoneregion-arctic": "Pak-ke̍k",
+       "timezoneregion-asia": "A-chiu",
+       "timezoneregion-atlantic": "Tāi-se-iûⁿ",
+       "timezoneregion-australia": "Australia",
+       "timezoneregion-europe": "Au-chiu",
+       "timezoneregion-indian": "Ìn-tō͘-iûⁿ",
+       "timezoneregion-pacific": "Thài-pêng-iûⁿ",
        "allowemail": "Ún-chún pa̍t-ê iōng-chiá kià email kòe-lâi",
+       "prefs-searchoptions": "Cha-sûn",
+       "prefs-namespaces": "Miâ-khong-kan",
+       "default": "kì-tēng",
        "prefs-files": "Tóng-àn",
+       "prefs-custom-css": "Chū-siat CSS",
+       "prefs-custom-js": "Chū-siat JavaScript",
+       "prefs-common-css-js": "Só͘-ū gōa-phôe kong-ke ê CSS/JavaScript",
+       "prefs-reset-intro": "Lí ē-sài ēng pún ia̍h lâi chiong lí ê siat-tì têng-siat chò pún chām kì-tēng.\nChe bē hoat-tō͘ ho̍k-goân.",
+       "prefs-emailconfirm-label": "Tiān-chú-phoe khak-tēng:",
        "youremail": "Lí ê email:",
+       "username": "{{GENDER:$1|Ēng-chiá-miâ-hō}}:",
        "yourrealname": "Lí ê chin miâ:",
        "yourlanguage": "Kài-bīn gú-giân:",
        "yournick": "Lí ê sió-miâ (chhiam-miâ iōng):",
        "group-bureaucrat-member": "{{GENDER:$1|Koaⁿ-liâu}}",
        "grouppage-sysop": "{{ns:project}}:Hêng-chèng jîn-oân",
        "grouppage-bureaucrat": "{{ns:project}}:Koaⁿ-liâu",
+       "right-move-categorypages": "Sóa tōng ia̍h-bīn lūi-lia̍t",
+       "right-movefile": "Sóa tóng-àn",
+       "right-upload": "Kā tóng-àn chiūⁿ-bāng",
+       "right-upload_by_url": "Tùi 1-ê URL thoân thóng-àn",
        "right-writeapi": "用API寫",
-       "newuserlogpage": "開賬戶日誌",
+       "right-delete": "Thâi ia̍h",
+       "newuserlogpage": "khui kháu-chō ji̍t-chì",
        "rightslogtext": "Chit-ê log lia̍t-chhut kái-piàn iōng-chiá koân-lī ê tōng-chok.",
        "action-edit": "Siu-kái chit ia̍h",
        "nchanges": "$1 {{PLURAL:$1|kái|kái}}",
        "recentchanges-label-minor": "Che sī sió siu-kái",
        "recentchanges-label-bot": "Che sī ki-khì-lâng kái--ê",
        "recentchanges-label-unpatrolled": "這个編輯抑無巡視過",
-       "recentchanges-label-plusminus": "彼頁改了;精差的位元組",
+       "recentchanges-label-plusminus": "Hit ia̍h kái liáu; cheng-chha ê ūi-goân-cho͘",
        "recentchanges-legend-heading": "<strong>Ké-soeh:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (請參考[[Special:NewPages|新頁清單]])",
        "rcnotefrom": "Ē-kha sī <b>$2</b> kàu taⁿ ê kái-piàn (ke̍k-ke hián-sī <b>$1</b> hāng).",
        "rclistfrom": "Hián-sī tùi $3 $2 kàu taⁿ ê sin kái-piàn",
        "rcshowhideminor": "$1 sió siu-kái",
-       "rcshowhideminor-hide": "藏起來",
+       "rcshowhideminor-show": "hiàn",
+       "rcshowhideminor-hide": "am",
        "rcshowhidebots": "$1 機器儂",
-       "rcshowhidebots-show": "",
+       "rcshowhidebots-show": "hiàn",
        "rcshowhideliu": "$1 teng-ji̍p ê iōng-chiá",
-       "rcshowhideliu-hide": "藏起來",
+       "rcshowhideliu-show": "hiàn",
+       "rcshowhideliu-hide": "am",
        "rcshowhideanons": "$1 bû-bêng-sī",
-       "rcshowhideanons-hide": "藏起來",
+       "rcshowhideanons-show": "hiàn",
+       "rcshowhideanons-hide": "am",
        "rcshowhidemine": "$1 góa ê pian-chi̍p",
-       "rcshowhidemine-hide": "藏起來",
+       "rcshowhidemine-show": "hiàn",
+       "rcshowhidemine-hide": "am",
        "rclinks": "Hían-sī $2 ji̍t lāi siōng sin ê $1 hāng kái-piàn<br />$3",
        "diff": "Cheng-chha",
        "hist": "ls",
        "minoreditletter": "~",
        "newpageletter": "!",
        "boteditletter": "b",
-       "rc-change-size-new": "改了後;變做$1{{PLURAL:$1|位元}}",
+       "rc-change-size-new": "Kái liáu āu, piàn-choè $1 {{PLURAL:$1|ūi-goân}}",
        "recentchangeslinked": "Siong-koan ê kái-piàn",
        "recentchangeslinked-feed": "Siong-koan ê kái-piàn",
        "recentchangeslinked-toolbox": "Siong-koan ê kái-piàn",
-       "recentchangeslinked-title": "佮 \"$1\" 相關的改變",
+       "recentchangeslinked-title": "kap \"$1\" siong-koan ê kái-piàn",
        "recentchangeslinked-summary": "這是有相接到指定頁(抑是指定分類的所有成員),而且最近家己頁的內容有改過的清單。\n遐的頁[[Special:Watchlist|佇你的監視清單]]會用<strong>粗體</strong> 標示。",
        "recentchangeslinked-page": "Ia̍h ê miâ:",
        "upload": "Kā tóng-àn chiūⁿ-bāng",
        "filehist-thumbtext": "$1版本的細圖",
        "filehist-user": "Iōng-chiá",
        "filehist-dimensions": "寸尺",
-       "filehist-comment": "說明",
+       "filehist-comment": "soat-bêng",
        "imagelinks": "tóng-àn sù-iōng ê chōng-hòng",
        "linkstoimage": "ē-kha {{PLURAL:$1|ê ia̍h}} ū iōng tio̍h chit ê iáⁿ-siōng:",
        "nolinkstoimage": "Bô poàⁿ ia̍h liân kàu chit tiuⁿ iáⁿ-siōng.",
        "doubleredirects": "Siang-thâu choán-ia̍h",
        "brokenredirects": "Choán-ia̍h kò·-chiòng",
        "brokenredirectstext": "Í-hā ê choán-ia̍h liân kàu bô chûn-chāi ê ia̍h:",
+       "brokenredirects-edit": "siu-kái",
+       "brokenredirects-delete": "thâi",
        "withoutinterwiki": "Bô gí-giân liân-kiat ê ia̍h",
        "withoutinterwiki-summary": "Ē-kha ê ia̍h bô kî-thaⁿ gí-giân pán-pún ê liân-kiat:",
+       "withoutinterwiki-legend": "Jī-thâu",
+       "withoutinterwiki-submit": "Hían-sī",
        "fewestrevisions": "Siōng bô siu-tēng ê bûn-chiuⁿ",
        "nbytes": "$1 {{PLURAL:$1|jī-goân|jī-goân}}",
        "ncategories": "$1 {{PLURAL:$1|ê lūi-pia̍t |ê lūi-pia̍t}}",
-       "nlinks": "$1 ê liân-kiat",
+       "nlinks": "$1 ê {{PLURAL:$1|liân-kiat}}",
        "nmembers": "$1{{PLURAL:$1|ê sêng-oân}}",
-       "nrevisions": "$1 ê siu-tēng-pún",
+       "nmemberschanged": "$1 → $2 ê {{PLURAL:$2|sêng-oân}}",
+       "nrevisions": "$1 ê {{PLURAL:$1|siu-tēng-pún}}",
        "lonelypages": "Ko·-ia̍h",
        "uncategorizedpages": "Bô lūi-pia̍t ê ia̍h",
        "uncategorizedcategories": "Bô lūi-pia̍t ê lūi-pia̍t",
        "deadendpages": "Khu̍t-thâu-ia̍h",
        "deadendpagestext": "Ē-kha ê ia̍h bô liân kàu wiki lāi-té ê kî-thaⁿ ia̍h.",
        "protectedpages": "Siū pó-hō͘ ê ia̍h",
+       "protectedpages-page": "Ia̍h",
        "listusers": "Iōng-chiá lia̍t-toaⁿ",
        "newpages": "Sin ia̍h",
        "newpages-username": "Iōng-chiá miâ-chheng:",
        "move-watch": "Kàm-sī chit ia̍h",
        "movepagebtn": "Sóa ia̍h",
        "pagemovedsub": "Sóa-ūi sêng-kong",
+       "movepage-moved": "<strong>\"$1\" í-keng hong sóa khì \"$2\"</strong>",
        "articleexists": "Kāng miâ ê ia̍h í-keng tī leh, a̍h-sī lí kéng ê miâ bô-hāu. Chhiáⁿ kéng pa̍t ê miâ.",
        "movetalk": "Sūn-sòa sóa thó-lūn-ia̍h",
        "movepage-page-moved": "$1 í-keng sóa khì tī $2.",
+       "movepage-page-unmoved": "$1 chit ia̍h hô hoat-tō͘ sóa khì $2.",
        "movelogpagetext": "Ē-kha lia̍t-chhut hông soá-ūi ê ia̍h.",
        "movereason": "Lí-iû:",
        "revertmove": "hôe-tńg",
        "version": "Pán-pún",
        "specialpages": "Te̍k-sû-ia̍h",
        "tag-filter": "[[Special:Tags|Piau-chhiam]] chhoē mi̍h:",
-       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|个標籤}}]]:$2)",
+       "tag-list-wrapper": "([[Special:Tags|$1 ê piau-chhiam]]: $2)",
        "logentry-move-move": "$1 {{GENDER:$2|sóa}} $3 chit ia̍h khì $4",
        "logentry-newusers-create": "已經{{GENDER:$2|開好}}用者口座 $1",
-       "searchsuggest-search": "Chhiau",
+       "searchsuggest-search": "Chh",
        "expandtemplates": "Khok-chhiong pang-bô͘",
        "expand_templates_input": "Su-ji̍p bûn-jī:",
        "expand_templates_output": "Kiat-kó:",
index 30e0e7a..8e6132e 100644 (file)
@@ -12,7 +12,8 @@
                        "아라",
                        "Candalua",
                        "Macofe",
-                       "V6rg"
+                       "V6rg",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Sottolinia 'e jonte:",
        "noemail": "Nun ce sta indirizzo e-mail pe' l'utente \"$1\".",
        "noemailcreate": "S'add'appruviggiunà n'indirizzo e-mail buono.",
        "passwordsent": "Na password nova è stata inviata a l'innerizzo e-mail riggistrato 'a ll'utente \"$1\".\nPe' piacere, trasite appena avite ricevuta sta password.",
-       "blocked-mailpassword": "Ll'IP tuoja è bloccata pe' scrivere, picciò nun se ponno usà 'e ffunzione pe te mannà na password nova.",
+       "blocked-mailpassword": "Ll'IP toja è bloccata pe' scrivere. Pe' ce sparagnà n'abbuso, nun se ponn'ausà 'e ffunzione pe ve mannà na password nova 'a st'indirizzo IP.",
        "eauthentsent": "Na mmasciata 'e conferma t'è stata mannata a l'indirizzo e-mail nzignàto.\nApprimm' 'e te mannà n'atu mail, hè 'a stà 'a ffà 'e struzione dint'a l'e-mail, pe' cunfermà ca 'o cunto fosse d' 'o tujo overo.",
        "throttled-mailpassword": "S'è mannata na mail pe te' riabbià 'a password 'a meno 'e {{PLURAL:$1|n'ora|$1 ore}}.\nPe' ce sparagnà abbuse, 'a funzione 'e riabbiamento d' 'a password se può usa sulamente na vota ogne {{PLURAL:$1|ora|$1 ore}}.",
        "mailerror": "Errore pe' tramente ca se mannava na mmasciata: $1",
        "botpasswords-insert-failed": "Nun se pò azzeccà 'o nomme bot \"$1\". Fosse stato già azzeccato?",
        "botpasswords-update-failed": "Se scassaje a carrecà 'o nomme bot \"$1\". È stato scancellato?",
        "botpasswords-created-title": "Password bot criata",
-       "botpasswords-created-body": "'A password bot \"$1\" fuje criata cu' succiesso.",
+       "botpasswords-created-body": "'A password bot \"$1\" 'a ll'utente \"$2\" fuje criata.",
        "botpasswords-updated-title": "Password bot agghiurnata",
-       "botpasswords-updated-body": "'A password bot \"$1\" è fuje agghiurnata cu' succiesso.",
+       "botpasswords-updated-body": "'A password bot \"$1\" 'a ll'utente \"$2\" fuje agghiurnata.",
        "botpasswords-deleted-title": "Password bot scancellata",
-       "botpasswords-deleted-body": "'A password bot \"$1\" è stata scancellata.",
+       "botpasswords-deleted-body": "'A password bot \"$1\" 'a ll'utente \"$2\" è stata scancellata.",
        "botpasswords-newpassword": "'A password nòva pe' puté trasì cu <strong>$1</strong> è <strong>$2</strong>. <em>Pe' piacere signatevello chesto pe' ve ffà conzurtaziune future.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider nun è disponibbele.",
        "botpasswords-restriction-failed": "'E restriziune 'e password bot nun ve permettessero st'acciesso.",
        "revdelete-unsuppress": "Scancella 'e limmete ncopp' 'e verziune arripigliate",
        "revdelete-log": "Mutivo:",
        "revdelete-submit": "Applica {{PLURAL:$1|â virziona scigliuta|a 'e virziune scigliute}}",
-       "revdelete-success": "'''Visibbelità d' 'a verziona agghiurnata e apposto.'''",
+       "revdelete-success": "Visibbelità d' 'a verziona agghiurnata e apposto.",
        "revdelete-failure": "'''Int'a sta virziona 'a visibbelità nun se può agghiurnà:'''\n$1",
-       "logdelete-success": "'''Int'a stu riggistro 'a visibbelità è stata scigliuta currettamente.'''",
+       "logdelete-success": "Visebbiletà d' 'o riggistro mpustata.",
        "logdelete-failure": "'''Int'a stu riggistro 'a visibbelità nun se può scegliere:'''\n$1",
        "revdel-restore": "càgna visiblità",
        "pagehist": "Verziune 'e primma",
        "userrights-changeable-col": "Gruppe ca putite cagnà",
        "userrights-unchangeable-col": "Gruppe ca nun putite cagnà",
        "userrights-conflict": "Conflitto 'e cagnamiento 'e deritte utente! Cuntrullate e cunfermate 'e cagnamiente vuoste.",
-       "userrights-removed-self": "Avete rimosso buono 'e deritte vuoste. Picciò nun putite trasì cchiù dint'a sta paggena.",
+       "userrights-removed-self": "Avite rimosso 'e deritte vuoste. Picciò nun putite trasì cchiù dint'a sta paggena.",
        "group": "Gruppo:",
        "group-user": "Utente",
        "group-autoconfirmed": "Utente autocunfermate",
        "recentchangeslinked-page": "Nomme d' 'a paggena",
        "recentchangeslinked-to": "Mmusta sulamente 'e cagnamiente a 'e paggene cullegate a chilla specificata",
        "recentchanges-page-added-to-category": "[[:$1]] azzeccato â categurìa",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] e {{PLURAL:$2|na paggena|$2 paggene}} azzeccate â categurìa",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|na paggena|$2 paggene}}]] azzeccate â categurìa",
        "recentchanges-page-removed-from-category": "[[:$1]] luvato d' 'a categurìa",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e {{PLURAL:$2|na paggena|$2 paggena}} luvate d' 'a categurìa",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|na paggena|$2 paggena}}]] luvate d' 'a categurìa",
        "autochange-username": "Cagnamiento automateco MediaWiki",
        "upload": "Carreca file",
        "uploadbtn": "Carreca file",
        "uploadstash-summary": "Sta paggena dà l'accesso a 'e file ca songo carrecate o ca stanno pe' se carrecà, ma nun songo pubbrecat'ancora ncopp'a sta wiki. Sti file nun songo visibbele a nisciuno, sulamente a chill'utente ca l'ha carrecato.",
        "uploadstash-clear": "Pulezza 'e file annascunnute",
        "uploadstash-nofiles": "Nun tenite file annascunnute.",
-       "uploadstash-badtoken": "L'esecuzione 'e sta azione nun ha avuto successo, forse pecché 'e credenziale 'e cagnamiento so' mmaturate. Prova n'ata vota.",
-       "uploadstash-errclear": "'A pulezzia d' 'e file nun ha avuto successo.",
+       "uploadstash-badtoken": "L'esecuzione 'e sta azione scassaje.\nForse pecché 'e credenziale 'e cagnamiento so' mmaturate.\nPruvate n'ata vota.",
+       "uploadstash-errclear": "'A pulezzia d' 'e file scassaje.",
        "uploadstash-refresh": "Agghiuorna l'elenco d' 'e file",
+       "uploadstash-thumbnail": "vide miniatura",
        "invalid-chunk-offset": "Distanza d' 'a parte nun valida",
        "img-auth-accessdenied": "Acciesso negato",
        "img-auth-nopathinfo": "PATH_INFO mancante.\n'O server nun è mpustato pe' passà sta nfurmazione.\nPuò darse ca, essenno basato ncopp'a CGI, nun putesse suppurtà img_auth.\nVide https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization",
        "changecontentmodel-title-label": "Titulo d\"a paggena",
        "changecontentmodel-model-label": "Mudello 'e cuntenute nuovo",
        "changecontentmodel-reason-label": "Mutivo:",
+       "changecontentmodel-submit": "Cagnato",
        "changecontentmodel-success-title": "'O mudello 'e cuntenuto fuje cagnato",
        "changecontentmodel-success-text": "'O tipo 'e cuntenut 'e [[:$1]] è stato cagnato.",
        "changecontentmodel-cannot-convert": "'E cuntenute dint'a [[:$1]] nun se ponno scagnà a nu tipo 'e $2.",
        "ipb-unblock": "Sblocca nomme utente o indirizzo IP",
        "ipb-blocklist": "Fà vedé 'e blocche ch'esisteno",
        "ipb-blocklist-contribs": "Contribbute 'e {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "$1 rummase",
        "unblockip": "Sblocca utente",
        "unblockiptext": "Ausa 'o modulo ccà abbascio p'arrepiglià 'e deritte 'e scrittura a l'indirizze IP o cunte utente ca primma so state bluccate.",
        "ipusubmit": "Lèva stu blocco",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|verzione|verziune}} mpurtate",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|verzione|verziune}} mpurtate 'a $2",
        "javascripttest": "Test JavaScript",
-       "javascripttest-pagetext-noframework": "Sta paggena è riservata pe' l'esecuziune d' 'e test 'e Javascript.",
-       "javascripttest-pagetext-unknownframework": "Ambiente 'e test scanusciuto \"$1\".",
        "javascripttest-pagetext-unknownaction": "Azione scanusciuta \"$1\".",
-       "javascripttest-pagetext-frameworks": "Pe' piacere sciglite uno 'e ll'ambiente 'e test ccà abbascio: $1",
-       "javascripttest-pagetext-skins": "Sciglite nu skin pe' ne fà 'e test:",
        "javascripttest-qunit-intro": "Vedite 'a [$1 documentaziona d' 'o test] ncopp'a mediawiki.org.",
        "tooltip-pt-userpage": "'A paggena {{GENDER:|utente}} vòsta",
        "tooltip-pt-anonuserpage": "'A paggena utente pe l'IP ca vuje state cagnanno cumme",
        "version-libraries-description": "Descrizzione",
        "version-libraries-authors": "Auture",
        "redirect": "Rediretto 'a nu file, n'utente, na paggena, na verziona o nu riggistro ID",
-       "redirect-legend": "Rediretto ca spuntasse a nu file o na paggena",
        "redirect-summary": "Sta pàggena speciale redireziona a nu file (dato 'o nomme d' 'o file), na pàggene (dato n'ID 'e verziona), o 'na pàggene utente (dato n'ID nummereca 'e l'utende), o na trasuta a 'o riggistro (dato 'o riggistro ID). Ause: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], o [[{{#Special:Redirect}}/user/101]], o [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Vaje",
        "redirect-lookup": "Ascìa:",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|pruteggette}} $3 $4 [cascading]",
        "logentry-protect-modify": "$1 {{GENDER:$2|cagnaje}} 'o livello 'e prutezione pe' $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|cagnaje}} 'o livello 'e prutezione pe' $3 $4 [cascading]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|cagnaje}} 'e gruppo pe' $3 'a $4 a $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|cagnaje}} 'e gruppo pe' {{GENDER:$3|$3}} 'a $4 a $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|cagnaje}} 'e gruppo pe' $3",
        "logentry-rights-autopromote": "$1 è {{GENDER:$2|stato promosso|stata promossa}} automatecamente 'a $4 a $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|ave carrecato}} $3",
        "api-error-unknownerror": "Errore scanusciuto: \"$1\"",
        "api-error-uploaddisabled": "'E carreche so' stutate dint'a sta siki.",
        "api-error-verification-error": "Stu file putesse stà nguacchiato, o tene n'estensione sbagliata.",
+       "api-error-was-deleted": "Nu file cu stu nomme s'è carrecato primma e po' s'è scancellaje.",
        "duration-seconds": "$1 {{PLURAL:$1|secondo|seconde}}",
        "duration-minutes": "$1 {{PLURAL:$1|minuto|minute}}",
        "duration-hours": "$1 {{PLURAL:$1|ora|ore}}",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "Simmule",
        "special-characters-group-greek": "Grieco",
+       "special-characters-group-greekextended": "Grieco spannuto",
        "special-characters-group-cyrillic": "Cirillico",
        "special-characters-group-arabic": "Arabo",
        "special-characters-group-arabicextended": "Arabo spannuto",
        "sessionprovider-generic": "$1 sessiune",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessiune basate ncopp' 'e cookie",
        "sessionprovider-nocookies": "'E cookie ponno stà stutate. Vedite si 'e cookie stann'appicciate e accumminciate n'ata vota.",
-       "randomrootpage": "Paggena 'e rareca a ccaso"
+       "randomrootpage": "Paggena 'e rareca a ccaso",
+       "log-action-filter-block": "Tipo 'e blocco:",
+       "log-action-filter-delete": "Tipo 'e scancellazione:",
+       "log-action-filter-patrol": "Tipo 'e verifica:",
+       "log-action-filter-protect": "Tipo 'e protezione:",
+       "log-action-filter-upload": "Tipo 'e carreca:",
+       "log-action-filter-all": "Tutte",
+       "log-action-filter-block-block": "Blocco",
+       "log-action-filter-block-reblock": "Modifica blocco",
+       "log-action-filter-block-unblock": "Sblocca",
+       "log-action-filter-delete-delete": "Scancellazione 'e paggena",
+       "log-action-filter-delete-restore": "Arrepigliament' 'e paggena",
+       "log-action-filter-delete-event": "Scancellazione d' 'o reggistro",
+       "log-action-filter-delete-revision": "Scancellazione d' 'a verziona",
+       "log-action-filter-patrol-patrol": "Verifica manuale",
+       "log-action-filter-patrol-autopatrol": "Verifica automatica",
+       "log-action-filter-protect-protect": "Prutezione",
+       "log-action-filter-protect-modify": "Cagna prutezione",
+       "log-action-filter-protect-unprotect": "Sprutezione",
+       "log-action-filter-upload-upload": "Carreca nova",
+       "log-action-filter-upload-overwrite": "Recarreca"
 }
index 4bdecee..073fe88 100644 (file)
@@ -47,7 +47,8 @@
                        "Kingu",
                        "Tarjeimo",
                        "Matma Rex",
-                       "SuperPotato"
+                       "SuperPotato",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Strek under lenker:",
        "recentchangeslinked-page": "Sidenavn:",
        "recentchangeslinked-to": "Vis endringer på sider som lenker til den gitte siden istedet",
        "recentchanges-page-added-to-category": "[[:$1]] lagt til kategori",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] og {{PLURAL:$2|én side|$2 sider}} lagt til kategori",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] og [[Special:WhatLinksHere/$1|{{PLURAL:$2|én side|$2 sider}}]] lagt til kategori",
        "recentchanges-page-removed-from-category": "[[:$1]] fjernet fra kategori",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] og {{PLURAL:$2|én side|$2 sider}} fjernet fra kategori",
        "autochange-username": "Automatisk MediaWiki-endring",
index e122c0e..49ccbf8 100644 (file)
        "nstab-template": "Mal",
        "nstab-help": "Hulpe",
        "nstab-category": "Kategorie",
+       "mainpage-nstab": "Veurblad",
        "nosuchaction": "De op-egeven haandeling besteet niet",
        "nosuchactiontext": "De opdrachte in t webadres in ongeldig.\nJe hebben t webadres misschien verkeerd in-etikt of de verkeerde verwiezing evolgd.\nDit kan oek dujen op n fout in de programmatuur van {{SITENAME}}.",
        "nosuchspecialpage": "Der besteet gien spesiale zied mit disse naam",
        "newarticle": "(Niej)",
        "newarticletext": "Disse zied besteet nog niet.\nIn t veld hieronder ku'j wat schrieven um disse zied an te maken (meer informasie vie'j op de [$1 hulpzied]).\nA'j hier per ongelok terechtekeumen bin gebruuk dan de knoppe '''veurige''' um weerumme te gaon.",
        "anontalkpagetext": "---- ''Disse overlegzied heurt bie n anonieme gebruker die nog gien gebrukersnaam hef, of t niet gebruukt. We gebruken daorumme t IP-adres um hum of heur te herkennen, mer t kan oek ween dat meerdere personen t zelfde IP-adres gebruken, en da'j hiermee berichten ontvangen die niet veur joe bedoeld bin. A'j dit veurkoemen willen, dan ku'j t best [[Special:UserLogin/signup|n gebrukersnaam anmaken]] of [[Special:UserLogin|anmelden]].''",
-       "noarticletext": "Der steet noen gien tekste op disse zied.\nJe kunnen [[Special:Search/{{PAGENAME}}|de titel opzeuken]] in aandere ziejen,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} zeuken in de logboeken],\nof [{{fullurl:{{FULLPAGENAME}}|action=edit}} disse zied bewarken]</span>.",
+       "noarticletext": "Der steet noen gien tekste op disse zied.\nJe kunnen [[Special:Search/{{PAGENAME}}|de titel opzeuken]] in aandere ziejen,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} zeuken in de logboeken],\nof [{{fullurl:{{FULLPAGENAME}}|action=edit}} disse zied anmaken]</span>.",
        "noarticletext-nopermission": "Op disse zied steet gien tekste.\nJe kunnen [[Special:Search/{{PAGENAME}}|zeuken naor disse term]] in aandere ziejen of\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} de logboeken deurzeuken]</span>, mer je hebben gien rechten um disse zied an te maken.",
        "missing-revision": "De versie #$1 van de zied \"{{FULLPAGENAME}} besteet niet.\n\nDit kömp meestentieds deur t volgen van n verouwerde verwiezing naor n zied die vortedaon is.\nWaorschienlik ku'j der meer gegevens over vienen in t [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} vortdologboek].",
        "userpage-userdoesnotexist": "Je bewarken n gebrukerszied van n gebruker die niet besteet (gebruker \"<nowiki>$1</nowiki>\"). Kiek effen nao o'j disse zied wel anmaken/bewarken willen.",
        "contributions": "{{GENDER:$1|Biedragen van disse gebruker}}",
        "contributions-title": "Biedragen van $1",
        "mycontris": "Mien biedragen",
+       "anoncontribs": "Biedragen",
        "contribsub2": "Veur {{GENDER:$3|$1}} ($2)",
        "nocontribs": "Gien wiezigingen evunnen die an de estelde criteria voldoon.",
        "uctop": "(leste wieziging)",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|versie|versies}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versie|versies}} van $2",
        "javascripttest": "JavaScript testen",
-       "javascripttest-pagetext-noframework": "Disse zied is ereserveerd veur t uutvoeren van JavaScript-testen.",
-       "javascripttest-pagetext-unknownframework": "Onbekend testraamwark \"$1\".",
-       "javascripttest-pagetext-frameworks": "Kies een van de volgende testraamwarken: $1",
-       "javascripttest-pagetext-skins": "Kies n vormgeving um de tests mee uut te voeren:",
        "javascripttest-qunit-intro": "Zie de [$1 testdokumentasie] op mediawiki.org.",
-       "tooltip-pt-userpage": "Oew gebroekersziede",
+       "tooltip-pt-userpage": "{{GENDER:|Oew}} gebroekersziede",
        "tooltip-pt-anonuserpage": "Gebroekersbladziede vuur t IP-adres da'j broekt",
-       "tooltip-pt-mytalk": "Oew oaverlegbladziede",
+       "tooltip-pt-mytalk": "{{GENDER:|Oew}} oaverlegziede",
        "tooltip-pt-anontalk": "Oaverlegbladziede van n naamlozen gebroeker van dit IP-adres",
-       "tooltip-pt-preferences": "Miene vuurkeuren",
+       "tooltip-pt-preferences": "{{GENDER:|Miene}} vuurkeuren",
        "tooltip-pt-watchlist": "Lieste van zieden die op miene volglieste stoan",
-       "tooltip-pt-mycontris": "Liest van oew biejdraegen",
+       "tooltip-pt-mycontris": "Oaverzicht van {{GENDER:|oew}} biejdreagen",
        "tooltip-pt-login": "Iej wördt van harte oetneugd um oe an te melden as gebroeker, mer t is nich verplicht",
        "tooltip-pt-logout": "Ofmaelden",
        "tooltip-pt-createaccount": "Schrief je eigen veural in en meld je an, mer t is niet verplicht.",
        "tooltip-ca-talk": "Loat n oaverlegtekst oaver disse ziede zeen",
-       "tooltip-ca-edit": "Bewaerk disse ziede",
+       "tooltip-ca-edit": "Beweark disse ziede",
        "tooltip-ca-addsection": "Niej oonderwaerp tovogen",
        "tooltip-ca-viewsource": "Disse ziede is beveiligd taegen veraanderen. Iej könt wal kieken noar de ziede",
        "tooltip-ca-history": "Oaldere versies van disse ziede",
        "tooltip-t-recentchangeslinked": "Pas verrichte veraanderingen die noar disse ziede verwiezen",
        "tooltip-feed-rss": "RSS-voer vuur disse ziede",
        "tooltip-feed-atom": "Atom-voer vuur disse ziede",
-       "tooltip-t-contributions": "Lieste met biejdraegen van disse gebroeker",
+       "tooltip-t-contributions": "Lieste met biejdreagen van {{GENDER:$1|disse gebroeker}}",
        "tooltip-t-emailuser": "Stuur disse gebroeker n netpostbericht",
        "tooltip-t-info": "Meer informasie over disse zied",
        "tooltip-t-upload": "Laad ofbeeldingen en/of geluudsmateriaal",
        "spam_reverting": "Bezig mit t weerummezetten naor de leste versie die gien verwiezing hef naor $1",
        "spam_blanking": "Alle wiezigingen mit n verwiezing naor $1 wörden vortehaold",
        "spam_deleting": "In alle versies staon verwiezingen naor $1. Zied vortedaon",
-       "simpleantispam-label": "Antispamkontraole.\nHier '''NIKS''' invullen!",
+       "simpleantispam-label": "Antispamkontraole.\nHier <strong>niks</strong> invullen!",
        "pageinfo-title": "Informasie over \"$1\"",
        "pageinfo-not-current": "Disse gegevens bin allinnig beschikbaor veur disse versie.",
        "pageinfo-header-basic": "Baosisinformasie",
        "version-entrypoints-header-entrypoint": "Ingang",
        "version-entrypoints-header-url": "Webadres",
        "redirect": "Deurverwiezen op bestaandsnaam, gebrukersnummer, ziednummer of versienummer",
-       "redirect-legend": "Deurverwiezen naor n bestaand of zied",
        "redirect-summary": "Disse spesiale zied verwis deur naor n bestaand (as de bestaandsnaam op-egeven wördt), n zied (as n zied- of versienummer op-egeven wördt) of n gebrukerszied (as t gebrukersnummer op-egeven wördt). Gebruuk: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], of [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Zeuk",
        "redirect-lookup": "Opzeuken:",
index b7e4d5b..acc2cd7 100644 (file)
@@ -73,7 +73,8 @@
                        "Matma Rex",
                        "Robin van der Vliet",
                        "Catrope",
-                       "Edoderoo"
+                       "Edoderoo",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Koppelingen onderstrepen:",
        "nocookieslogin": "{{SITENAME}} gebruikt cookies voor het aanmelden van gebruikers.\nCookies zijn uitgeschakeld in uw browser.\nSchakel deze optie in en probeer het opnieuw.",
        "nocookiesfornew": "De gebruiker is niet gemaakt omdat de bron niet bevestigd kon worden.\nZorg ervoor dat u cookies hebt ingeschakeld, herlaad deze pagina en probeer het opnieuw.",
        "noname": "U hebt geen geldige gebruikersnaam opgegeven.",
-       "loginsuccesstitle": "Aanmelden geslaagd",
+       "loginsuccesstitle": "Aangemeld",
        "loginsuccess": "<strong>U bent nu aangemeld bij {{SITENAME}} als \"$1\".</strong>",
        "nosuchuser": "De gebruiker \"$1\" bestaat niet.\nGebruikersnamen zijn hoofdlettergevoelig.\nControleer de schrijfwijze of [[Special:UserLogin/signup|maak een nieuw gebruiker aan]].",
        "nosuchusershort": "De gebruiker \"$1\" bestaat niet.\nControleer de schrijfwijze.",
        "botpasswords-newpassword": "Het nieuwe wachtwoord om aan te melden met <strong>$1</strong> is nu <strong>$2</strong>. <em>Bewaar dit goed voor toekomstig gebruik.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider is niet beschikbaar.",
        "botpasswords-restriction-failed": "Botwachtwoordbeperkingen maken het aanmelden onmogelijk.",
-       "botpasswords-invalid-name": "De gebruikersnaam mag niet het scheidingsteken van het botwachtwoord (\"$1\") bevatten.",
+       "botpasswords-invalid-name": "De gebruikersnaam bevat niet het scheidingsteken van het botwachtwoord (\"$1\").",
        "botpasswords-not-exist": "Gebruiker \"$1\" heeft geen botwachtwoord genaamd \"$2\"",
        "resetpass_forbidden": "Wachtwoorden kunnen niet gewijzigd worden",
        "resetpass-no-info": "U dient aangemeld zijn voordat u deze pagina kunt gebruiken.",
        "passwordreset-emailtext-ip": "Iemand, waarschijnlijk u, heeft vanaf het IP-adres $1 een aanvraag gedaan om uw wachtwoord voor {{SITENAME}} ($4) opnieuw in te stellen. De volgende {{PLURAL:$3|gebruiker is|gebruikers zijn}} gekoppeld aan dit e-mailadres:\n\n$2\n\n{{PLURAL:$3|Dit tijdelijke wachtwoord vervalt|Deze tijdelijke wachtwoorden vervallen}} over {{PLURAL:$5|een dag|$5 dagen}}. Meld u aan en wijzig het wachtwoord nu. Als u dit verzoek niet zelf heeft gedaan, of als u het oorspronkelijke wachtwoord nog kent en het niet wilt wijzigen, negeer dit bericht dan en blijf uw oude wachtwoord gebruiken.",
        "passwordreset-emailtext-user": "Gebruiker $1 op de site {{SITENAME}} heeft een aanvraag gedaan om uw wachtwoord voor {{SITENAME}} ($4) opnieuw in te stellen. De volgende {{PLURAL:$3|gebruiker is|gebruikers zijn}} gekoppeld aan dit e-mailadres:\n\n$2\n\n{{PLURAL:$3|Dit tijdelijke wachtwoord vervalt|Deze tijdelijke wachtwoorden vervallen}} over {{PLURAL:$5|een dag|$5 dagen}}.\nMeld u aan en wijzig het wachtwoord nu. Als u dit verzoek niet zelf heeft gedaan, of als u het oorspronkelijke wachtwoord nog kent en het niet wilt wijzigen, negeer dit bericht dan en blijf uw oude wachtwoord gebruiken.",
        "passwordreset-emailelement": "Gebruikersnaam: \n$1\n\nTijdelijk wachtwoord: \n$2",
-       "passwordreset-emailsentemail": "Als dit een e-mailadres is dat gekoppeld is aan uw account, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
+       "passwordreset-emailsentemail": "Als dit e-mailadres aan uw account gekoppeld is, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
        "passwordreset-emailsentusername": "Als er een e-mailadres geregistreerd is voor die gebruikersnaam, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
        "passwordreset-emailsent-capture": "Er is een e-mail voor het opnieuw instellen van een wachtwoord verzonden. Deze wordt hieronder weergegeven.",
        "passwordreset-emailerror-capture": "Er is een e-mail voor het opnieuw instellen van een wachtwoord aangemaakt. Deze wordt hieronder weergegeven. Het verzenden naar de {{GENDER:$2|gebruiker}} is mislukt om de volgende reden: $1",
        "recentchangeslinked-page": "Paginanaam:",
        "recentchangeslinked-to": "Wijzigingen aan pagina's met koppelingen naar deze pagina bekijken",
        "recentchanges-page-added-to-category": "[[:$1]] aan categorie toegevoegd",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] en {{PLURAL:$2|één pagina|$2 pagina's}} zijn toegevoegd aan categorie",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] en [[Special:WhatLinksHere/$1|{{PLURAL:$2|één pagina|$2 pagina's}}]] zijn toegevoegd aan categorie",
        "recentchanges-page-removed-from-category": "[[:$1]] is verwijderd uit categorie",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] en {{PLURAL:$2|één pagina|$2 pagina's}} zijn verwijderd uit categorie",
        "autochange-username": "Automatische wijziging van MediaWiki",
        "apisandbox-api-disabled": "De API is uitgeschakeld op deze site.",
        "apisandbox-intro": "Gebruik deze pagina om te experimenteren met de <strong>MediaWiki-API</strong>.\nZie de [[mw:API:Main page|API-documentatie]] voor verdere details over het gebruik van de API. Voorbeeld: [//www.mediawiki.org/wiki/API#A_simple_example hoe de inhoud van een Hoofdpagina ophalen]. Selecteer een handeling om meer voorbeelden te zien.\n\nHoewel dit een testfunctie is, kunnen sommige handelingen toch wijzigingen in de wiki maken.",
        "apisandbox-fullscreen": "Paneel uitvouwen",
-       "apisandbox-fullscreen-tooltip": "Het zandbakvenster uitvoeren om het browservenster te vullen.",
+       "apisandbox-fullscreen-tooltip": "Het zandbakpaneel zo groot als het browservenster maken.",
        "apisandbox-unfullscreen": "Pagina weergeven",
        "apisandbox-unfullscreen-tooltip": "Het zandbakvenster samenvouwen zodat de navigatie voor MediaWiki weer beschikbaar is.",
        "apisandbox-submit": "Verzoek uitvoeren",
        "changecontentmodel-title-label": "Paginanaam",
        "changecontentmodel-model-label": "Nieuw inhoudsmodel",
        "changecontentmodel-reason-label": "Reden:",
+       "changecontentmodel-submit": "Wijzigen",
        "changecontentmodel-success-title": "Het inhoudsmodel is gewijzigd",
        "changecontentmodel-success-text": "Het inhoudstype van [[:$1]] is gewijzigd.",
        "changecontentmodel-cannot-convert": "De inhoud van [[:$1]] kan niet worden omgezet in een type van $2.",
index d751514..e050eb9 100644 (file)
        "resetpass-wrong-oldpass": "Feil mellombels eller noverande passord.\nDu kan allereie ha byta passordet, eller ha bede om å få eit nytt mellombels passord.",
        "resetpass-temp-password": "Mellombels passord:",
        "resetpass-abort-generic": "Passordbytet vart stogga av ei utviding.",
+       "resetpass-validity-soft": "Passordet ditt er ikkje gyldig: $1\n\nGjer vel å velja eit nytt passord no, eller klikk «{{int:resetpass-submit-cancel}}» for å endra det seinare.",
        "passwordreset": "Attendestilling av passord",
        "passwordreset-text-one": "Fyll ut dette skjemaet for å attendestilla passordet ditt.",
        "passwordreset-disabled": "↓Tilbakestilling av passord er ikkje aktivert på denne wikien",
        "import-logentry-upload-detail": "{{PLURAL:$1|Éin versjon|$1 versjonar}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|Éin versjon|$1 versjonar}} frå $2",
        "javascripttest": "JavaScript-utrøyning",
-       "javascripttest-pagetext-noframework": "Sida er reservert for køyring av JavaScript-utrøyningar.",
-       "javascripttest-pagetext-unknownframework": "Ukjent utrøyningsrammeverk: «$1».",
        "javascripttest-pagetext-unknownaction": "Ukjend handling \"$1\".",
-       "javascripttest-pagetext-frameworks": "Vel eitt av dei fylgjande utrøyningsrammeverka: $1",
-       "javascripttest-pagetext-skins": "Vel ei drakt som utrøyningane skal køyrast med:",
        "javascripttest-qunit-intro": "Sjå [$1 utrøyningsdokumentasjon] på mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Brukarsida}} di",
        "tooltip-pt-anonuserpage": "Brukarsida for ip-adressa du endrar under",
        "version-libraries-library": "Bibliotek",
        "version-libraries-version": "Versjon",
        "redirect": "Omdiriger etter filnamn, brukar- eller versjons-ID",
-       "redirect-legend": "Omdiriger til ei fil eller ei side",
        "redirect-summary": "Denne spesialsida omdirigerer til ei fil (med eit filnamn), ei side (med ein versjons-ID) eller ei brukarside (med eit brukartal).",
        "redirect-submit": "Gå",
        "redirect-lookup": "Sjå etter:",
index 05f8f96..3a68073 100644 (file)
        "licenses-edit": "Modificar las opcions de licéncia",
        "license-nopreview": "(Previsualizacion impossibla)",
        "upload_source_url": "(lo fichièr qu'avètz causit dempuèi una URL valida e accessibla publicament)",
-       "upload_source_file": "(vòstre fichièr causit dempuèi vòstre ordenador)",
+       "upload_source_file": "(vòstre fichièr causit dempuèi vòstre ordinator)",
        "listfiles-delete": "suprimir",
        "listfiles-summary": "Aquesta pagina especiala permet de far la lista de totes los fichièrs importats.",
        "listfiles_search_for": "Recèrca del mèdia nomenat :",
index e9ff2ed..221e87c 100644 (file)
        "virus-badscanner": "ମନ୍ଦ ସଂରଚନା: ଅଜଣା ଭାଇରସ ସ୍କାନର: ''$1''",
        "virus-scanfailed": "ସ୍କାନ କରିବା ବିଫଳ ହେଲା (କୋଡ଼ $1)",
        "virus-unknownscanner": "ଅଜଣା ଆଣ୍ଟିଭାଇରସ:",
-       "logouttext": "<strong>ଲà¬\97-à¬\86à¬\89à¬\9f à¬¹à­\8bà¬\87à¬\97ଲା à¥¤</strong>\n\nà¬\86ପଣ à¬¨à¬¿à¬\9cର à¬¬à­\8dରାà¬\89à¬\9cରର à¬\85ସà­\8dଥାà­\9fà­\80 à¬¸à­\8dମତି (cache) à¬¨ à¬²à¬¿à¬­à¬¾à¬\87ବା à¬¯à¬¾à¬\8f à¬¹à­\81à¬\8fତ à¬\95ିà¬\9bି à¬ªà­\83ଷà­\8dଠାରà­\87 à¬²à¬\97-à¬\87ନ à¬¹à­\8bà¬\87 à¬°à¬¹à¬¿ପାରେ ।",
+       "logouttext": "<strong>à¬\86ପଣ à¬²à¬\97-à¬\86à¬\89à¬\9f à¬¹à­\8bà¬\87à¬\97ଲà­\87 à¥¤</strong>\n\nà¬\86ପଣ à¬¨à¬¿à¬\9cର à¬¬à­\8dରାà¬\89à¬\9cରର à¬\85ସà­\8dଥାà­\9fà­\80 à¬¸à­\8dମà­\83ତି (cache) à¬\96ାଲି à¬¨'à¬\95ରିବାଯାà¬\8f, à¬¹à­\81à¬\8fତ à¬\95ିà¬\9bି à¬ªà­\83ଷà­\8dଠାରà­\87 à¬²à¬\97-à¬\87ନ à¬¹à­\8bà¬\87ଥିବା à¬ªà¬°à¬¿ à¬¦à­\87à¬\96ାଯାà¬\87ପାରେ ।",
        "cannotlogoutnow-title": "ଲଗ ଆଉଟ ହେଇପାରିଲା ନାହିଁ",
        "cannotlogoutnow-text": "$1ବ୍ୟବହାର କରୁଥିବା ବେଳେ ଲଗ ଆଉଟ ହେଇପାରିବ ନାହିଁ ।",
        "welcomeuser": "ସ୍ଵାଗତ, $1!",
        "showpreview": "ଦେଖଣା [Preview]",
        "showdiff": "ବଦଳଗୁଡ଼ିକ ଦେଖାଇବେ",
        "blankarticle": "<strong>ଚେତାବନୀ:</strong> ଆପଣ ସମ୍ପାଦନା କରୁଥିବା ଏହି ପୃଷ୍ଠାଟି ଫାଙ୍କା ଅଛି ।\nଯଦି ଆପଣ \"{{int:savearticle}}\" ଉପରେ ଆଉଥରେ କ୍ଲିକ କରନ୍ତି, ପୃଷ୍ଠାଟି କୌଣସି ବିଷୟବସ୍ତୁ ନଥାଇ ତିଆରି ହୋଇଯିବ ।",
-       "anoneditwarning": "<strong>ସାବଧାନ:</strong> ଆପଣ ଲଗ-ଇନ କରିନାହାନ୍ତି । ଅଧିକ ସମ୍ପାଦନା କଲେ ଆପଣଙ୍କ IP Address ଟି ସମସ୍ତଙ୍କୁ ଦେଖାଯିବ । <strong>[$1ଲଗ ଇନ କଲେ]</strong> କିମ୍ବା <strong>[$2 ନୂଆ ଖାତାଟିଏ ତିଆରି କଲେ]</strong>, ଆପଣଙ୍କ ସମ୍ପାଦନାର ଶ୍ରେୟ ଅନ୍ୟାନ୍ୟ ସୁବିଧା ସହିତ ଆପଣଙ୍କ ଇଉଜର ନାମରେ ଦିଆହେବ ।",
+       "anoneditwarning": "<strong>ସାବଧାନ:</strong> ଆପଣ ଲଗ-ଇନ କରିନାହାନ୍ତି । ଅଧିକ ସମ୍ପାଦନା କଲେ ଆପଣଙ୍କ IP Address ଟି ସମସ୍ତଙ୍କୁ ଦେଖାଯିବ । <strong>[$1 ଲଗ ଇନ କଲେ]</strong> କିମ୍ବା <strong>[$2 ନୂଆ ଖାତାଟିଏ ତିଆରି କଲେ]</strong>, ଆପଣଙ୍କ ସମ୍ପାଦନାର ଶ୍ରେୟ ଅନ୍ୟାନ୍ୟ ସୁବିଧା ସହିତ ଆପଣଙ୍କ ଇଉଜର ନାମରେ ଦିଆହେବ ।",
        "anonpreviewwarning": "''ଆପଣ ଲଗ ଇନ କରି ନାହାନ୍ତି । ବଦଳକରି ସାଇତିଲେ ଆପଣଙ୍କର IP ଠିକଣା ଏହି ପୃଷ୍ଠାର ଇତିହାସରେ ସାଇତା ହୋଇଯିବ ।''",
        "missingsummary": "'''ଚେତାବନୀ:''' ଆପଣ ଏକ ସମ୍ପାଦନା ସାରକଥା ଦେଇନାହାନ୍ତି ।\nଯଦି ଆପଣ \"{{int:savearticle}}\"ରେ ଆଉଥରେ କ୍ଲିକ କରନ୍ତି, ତେବେ ଆପଣଙ୍କ ବଦଳ ସାରକଥା ବିନା ସାଇତା ହୋଇଯିବ ।",
        "selfredirect": "<strong>ସାବଧନ :</strong> ଆପଣ ଏହି ପୃଷ୍ଠାଟିକୁ ତା ମଧ୍ୟକୁ ଲେଇଟାଉଛନ୍ତି । ଆପଣ ବୋଧ ହୁଏ ଭୁଲ ଲକ୍ଷସ୍ଥଳ ଦେଇଛନ୍ତି କିମ୍ବା ଭୁଲ ପୃଷ୍ଠଟିକୁ ବଦଳାଉଛନ୍ତି । \nଆପଣ ଯଦି \"{{int:savearticle}}\"ରେ ଆଉଥରେ କ୍ଲିକ କରିବେ ତେବେ ଲେଉଟାଣିଟି ଯାହା ହେଲେ ସାଇତା ହେଇଯିବା ।",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|ଗୋଟି ସଂସ୍କରଣ|ଗୋଟି ସଂସ୍କରଣ}} ଅଣାଗଲା",
        "import-logentry-interwiki-detail": "$2ରୁ $1 {{PLURAL:$1|ଗୋଟି ସଂସ୍କରଣ|ଗୋଟି ସଂସ୍କରଣ}} ଅଣାଗଲା",
        "javascripttest": "ଜାଭାସ୍କ୍ରିପ୍ଟ ପରଖ",
-       "javascripttest-pagetext-noframework": "ଏହି ପୃଷ୍ଠାଟି ଜାଭାସ୍କ୍ରିପ୍ଟ ପରଖ ପାଇଁ ସଂରକ୍ଷଣ କରି ରଖାଯାଇଛି ।",
-       "javascripttest-pagetext-unknownframework": "\"$1\" ଅଜଣା ପରଖ ଗତିବିଧି ।",
-       "javascripttest-pagetext-frameworks": "ଦୟାକରି ନିମ୍ନରେ ଥିବା ଏକ ପରଖ ପ୍ରକ୍ରିୟାକୁ ବାଛନ୍ତୁ :$1",
-       "javascripttest-pagetext-skins": "ଏହି ପରଖକୁ ଚାଲୁ କରିବା ପାଇଁ ଏକ ଆବରଣ ବାଛନ୍ତୁ ।",
        "javascripttest-qunit-intro": "mediawiki.orgରେ [$1 testing documentation]କୁ ଦେଖନ୍ତୁ ।",
        "tooltip-pt-userpage": "{{GENDER:|ଆପଣଙ୍କ}} ବ୍ୟବହାରକାରୀ ପୃଷ୍ଠା",
        "tooltip-pt-anonuserpage": "ଆପଣ ଯେଉଁ IP ଠିକଣାର ବ୍ୟବହାରକାରୀ ପୃଷ୍ଠାଟି ବଦଳାଇବା ପାଇଁ ଚେଷ୍ଟା କରୁଛନ୍ତି",
        "version-libraries-library": "ପାଠାଗାର",
        "version-libraries-version": "ସଂସ୍କରଣ",
        "redirect": "ଫାଇଲ, ସଭ୍ୟ, ପୃଷ୍ଠା କିମ୍ବା ସଂସ୍କରଣ ID ଅନୁସାରେ ପୁନପ୍ରେରଣ",
-       "redirect-legend": "ଏକ ଫାଇଲ କିମ୍ବା ପୃଷ୍ଠାକୁ ପୁନପ୍ରେରଣ କରନ୍ତୁ",
        "redirect-summary": "(ଫାଇଲ ନାମ ଥିଲେ), (ଏକ ସଂସ୍କରଣ ID କିମ୍ବା ପୃଷ୍ଠା ID ଥିଲେ) କିମ୍ବା ଏକ ସଭ୍ୟ ଖାତା ଥିଲେ (ଏକ ସାଂଖିକ ସଭ୍ୟ ID)ଏହି ବିଶେଷ ପୃଷ୍ଠାଟି ଏକ ଫାଇଲକୁ ଲେଉଟାଇ ଦେଇଥାଏ । ବ୍ୟବହାର: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], କିମ୍ବା [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "ଯାଆନ୍ତୁ",
        "redirect-lookup": "ଖୋଜନ୍ତୁ:",
index ec42bff..608b0d1 100644 (file)
        "statistics-header-users": "Nummere vun Yuuser",
        "statistics-pages": "Bledder",
        "doubleredirects": "Zweefache Weiderleidinge",
-       "double-redirect-fixer": "Xqbot",
        "brokenredirects": "Kaputte Weiderleidinge",
        "brokenredirects-edit": "ennere",
        "brokenredirects-delete": "verwische",
        "contribslink": "Ardickele",
        "move-page": "„$1“ ziehe",
        "move-page-legend": "Blatt ziehe",
-       "movearticle": "Blatt ziehe:",
        "move-watch": "watsch des Blatt",
        "movepagebtn": "Blatt ziehe",
        "pagemovedsub": "Blatt iss gezoge warre",
index 7399539..5b22de3 100644 (file)
                        "Doctore",
                        "PiotrAntosz",
                        "The Polish",
-                       "Expert3222"
+                       "Expert3222",
+                       "Mateuszek045",
+                       "Sethakill",
+                       "Mateon1"
                ]
        },
        "tog-underline": "Podkreślenie linków:",
        "resetpass_submit": "Ustaw hasło i zaloguj się",
        "changepassword-success": "Twoje hasło zostało zmienione!",
        "changepassword-throttled": "Ostatnio zbyt wiele razy próbowałeś zalogować się na to konto.\nOdczekaj $1, zanim ponowisz próbę.",
+       "botpasswords": "Hasła bota",
+       "botpasswords-summary": "<em>Hasła bota</em> pozwalają na dostęp do konta użytkownika za pośrednictwem interfejsu API bez korzystania z danych konta. Uprawnienia uczestnika przy użyciu hasła bota mogą być ograniczone.\n\nJeśli nie wiesz, dlaczego miałbyś je tworzyć, nie powinieneś tego robić. Nikt nie powinien prosić Cię o utworzyć i podanie tego hasła.",
+       "botpasswords-disabled": "Hasła robotów zostały wyłączone.",
+       "botpasswords-no-central-id": "Aby użyć hasła robotów, musisz być zalogowany na koncie uniwersalnym.",
+       "botpasswords-existing": "Istniejące hasło bota",
+       "botpasswords-createnew": "Stwórz nowe hasło bota",
+       "botpasswords-editexisting": "Edytuj istniejące hasło bota",
        "botpasswords-label-appid": "Nazwa bota:",
        "botpasswords-label-create": "Utwórz",
        "botpasswords-label-update": "Aktualizuj",
        "botpasswords-label-cancel": "Anuluj",
        "botpasswords-label-delete": "Usuń",
        "botpasswords-label-resetpassword": "Zresetuj hasło",
+       "botpasswords-label-grants": "Zastosowane uprawnienia:",
+       "botpasswords-label-grants-column": "Przyznane",
+       "botpasswords-bad-appid": "Nazwa bota \"$1\" nie jest prawidłowa.",
+       "botpasswords-created-title": "Hasło bota stworzone",
+       "botpasswords-created-body": "Hasło bota \"$1\" użytkownika \"$2\" zostało utworzone.",
+       "botpasswords-updated-title": "Hasło bota zaktualizowane",
+       "botpasswords-updated-body": "Hasło bota \"$1\" użytkownika \"$2\" zostało zaktualizowane.",
+       "botpasswords-deleted-title": "Hasło bota usunięte",
+       "botpasswords-deleted-body": "Hasło bota \"$1\" użytkownika \"$2\" zostało usunięte.",
+       "botpasswords-not-exist": "Użytkownik \"$1\" nie ma hasła dla bota o nazwie \"$2\".",
        "resetpass_forbidden": "Hasła nie mogą zostać zmienione",
        "resetpass-no-info": "Musisz być zalogowany, by uzyskać bezpośredni dostęp do tej strony.",
        "resetpass-submit-loggedin": "Zmień hasło",
        "mergehistory-fail-bad-timestamp": "Znacznik czasu jest nieprawidłowy.",
        "mergehistory-fail-invalid-source": "Strona źródłowa jest nieprawidłowa.",
        "mergehistory-fail-invalid-dest": "Strona docelowa jest nieprawidłowa.",
+       "mergehistory-fail-permission": "Brak uprawnień aby połączyć historię.",
        "mergehistory-fail-self-merge": "Strona źródłowa i docelowa są takie same.",
        "mergehistory-fail-toobig": "Nie można połączyć historii, gdyż wymagałoby to przeniesienia więcej niż maksymalnej dopuszczalnej liczby $1 {{PLURAL:$1|wersji}}.",
        "mergehistory-no-source": "Strona źródłowa $1 nie istnieje.",
        "recentchangeslinked-page": "Tytuł strony:",
        "recentchangeslinked-to": "Pokaż zmiany nie na stronach linkowanych, a na stronach linkujących do podanej strony",
        "recentchanges-page-added-to-category": "dodano [[:$1]] do kategorii",
-       "recentchanges-page-added-to-category-bundled": "dodano [[:$1]] oraz {{PLURAL:$2|jedną stronę|$2 strony|$2 stron}} do kategorii",
+       "recentchanges-page-added-to-category-bundled": "dodano [[:$1]] oraz [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedną stronę|$2 strony|$2 stron}}]] do kategorii",
        "recentchanges-page-removed-from-category": "usunięto [[:$1]] z kategorii",
-       "recentchanges-page-removed-from-category-bundled": "usunięto [[:$1]] oraz {{PLURAL:$2|jedną stronę|$2 strony|$2 stron}} z kategorii",
+       "recentchanges-page-removed-from-category-bundled": "usunięto [[:$1]] oraz [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedną stronę|$2 strony|$2 stron}}]] z kategorii",
        "autochange-username": "Automatyczna zmiana MediaWiki",
        "upload": "Prześlij plik",
        "uploadbtn": "Prześlij plik",
        "upload-description": "Opis pliku",
        "upload-options": "Opcje przesyłania",
        "watchthisupload": "Obserwuj ten plik",
-       "filewasdeleted": "Plik o tej nazwie istniał, ale został usunięty.\nZanim załadujesz go ponownie, sprawdź $1.",
+       "filewasdeleted": "Plik o tej nazwie już istniał, ale został usunięty.\nZanim załadujesz go ponownie, sprawdź $1.",
        "filename-thumb-name": "Nazwa pliku wskazuje na to, że próbujesz przesłać miniaturkę obrazka. Prosimy nie przesyłać miniaturek w ramach tej samej wiki. Jeśli jest to konieczne, to zmień nazwę na bardziej opisową (w szczególności taką, w której nie ma prefiksu typowego dla miniaturek).",
        "filename-bad-prefix": "Nazwa pliku, który przesyłasz, zaczyna się od '''„$1”'''. Jest to nazwa zazwyczaj przypisywana automatycznie przez cyfrowe aparaty fotograficzne, która nie informuje o zawartości pliku.\nZmień nazwę pliku na bardziej opisową.",
        "filename-prefix-blacklist": " #<!-- nie modyfikuj tej linii --> <pre>\n# Składnia jest następująca:\n#  * Wszystko od znaku \"#\" do końca linii uznawane jest za komentarz\n#  * Każda niepusta linia zawiera początek nazwy pliku domyślnie wykorzystywany przez aparaty cyfrowe\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # niektóre telefony komórkowe\nIMG # ogólny\nJD # Jenoptik\nMGP # Pentax\nPICT # wiele różnych\n  #</pre> <!-- nie modyfikuj tej linii -->",
        "uploadstash-badtoken": "Operacja nie powiodła się. Być może Twoje upoważnienie do edytowania wygasło. Spróbuj ponownie.",
        "uploadstash-errclear": "Czyszczenie plików nie powiodło się.",
        "uploadstash-refresh": "Odśwież listę plików",
+       "uploadstash-thumbnail": "pokaż miniaturkę",
        "invalid-chunk-offset": "Nieprawidłowe przesunięcie fragmentu",
        "img-auth-accessdenied": "Odmowa dostępu",
        "img-auth-nopathinfo": "Brak PATH_INFO.\nSerwer nie został skonfigurowany, tak aby przekazywał tę informację.\nMożliwe, że jest oparty na CGI i nie może obsługiwać img_auth.\nWięcej o informacji o autoryzacji grafik na https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "changecontentmodel-title-label": "Tytuł strony",
        "changecontentmodel-model-label": "Nowy model zawartości",
        "changecontentmodel-reason-label": "Powód:",
+       "changecontentmodel-submit": "Zmień",
        "changecontentmodel-success-title": "Model zawartości został zmieniony",
        "changecontentmodel-success-text": "Typ zawartości [[:$1]] został zmieniony.",
        "changecontentmodel-cannot-convert": "Zawartość [[:$1]] nie może być przekształcona do typu $2.",
        "ipb-unblock": "Odblokuj użytkownika lub adres IP",
        "ipb-blocklist": "Zobacz istniejące blokady",
        "ipb-blocklist-contribs": "Wkład {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "pozostało $1",
        "unblockip": "Odblokuj użytkownika",
        "unblockiptext": "Użyj poniższego formularza, by przywrócić możliwość edycji z wcześniej zablokowanego adresu IP lub użytkownikowi.",
        "ipusubmit": "Odblokuj",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|wersja|wersje|wersji}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|wersja|wersje|wersji}} z $2",
        "javascripttest": "Testowanie JavaScript",
-       "javascripttest-pagetext-noframework": "Ta strona jest zarezerwowana dla wykonywania testów JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Nieznany framework testowania „$1”.",
        "javascripttest-pagetext-unknownaction": "Nieznana akcja \"$1\".",
-       "javascripttest-pagetext-frameworks": "Wybierz jeden z następujących frameworków testowania: $1",
-       "javascripttest-pagetext-skins": "Wybierz skórkę, na której chcesz uruchomić testy:",
        "javascripttest-qunit-intro": "Zobacz [$1 dokumentację testów] na mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Moja}} strona osobista",
        "tooltip-pt-anonuserpage": "Strona użytkownika dla adresu IP, spod którego edytujesz",
        "autoredircomment": "Przekierowanie do [[$1]]",
        "autosumm-new": "Utworzono nową stronę \"$1\"",
        "autosumm-newblank": "Utworzono pustą stronę",
-       "size-bytes": "$1&nbsp;B",
+       "size-bytes": "$1 {{PLURAL:$1|bajt|bajty|bajtów}}",
        "size-kilobytes": "$1&nbsp;KB",
        "size-megabytes": "$1&nbsp;MB",
        "size-gigabytes": "$1&nbsp;GB",
        "version-libraries-description": "Opis",
        "version-libraries-authors": "Autorzy",
        "redirect": "Przekierowanie z identyfikatora pliku, użytkownika, strony, wersji lub wpisu rejestru",
-       "redirect-legend": "Przekieruj do pliku lub strony",
-       "redirect-summary": "Ta strona specjalna przekierowuje do: pliku (o podanej nazwie), do strony (o podanym numerze wersji lub identyfikatorze strony) 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-summary": "Ta strona specjalna przekierowuje do: pliku (o podanej nazwie), do strony (o podanym numerze wersji lub identyfikatorze strony), do strony użytkownika (o podanym identyfikatorze numerycznym) albo do rejestru (o podanym numerze akcji). Sposób użycia: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]] albo [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Przejdź",
        "redirect-lookup": "Wyszukaj:",
        "redirect-value": "Wartość:",
        "redirect-page": "Identyfikator strony",
        "redirect-revision": "Wersja strony",
        "redirect-file": "Nazwa pliku",
+       "redirect-logid": "ID rejestru",
        "redirect-not-exists": "Nie znaleziono wartości",
        "fileduplicatesearch": "Wyszukiwanie duplikatów pliku",
        "fileduplicatesearch-summary": "Wyszukiwanie duplikatów pliku na podstawie wartości funkcji skrótu.",
        "api-error-stashfailed": "Błąd wewnętrzny – serwer nie mógł zapisać pliku tymczasowego.",
        "api-error-publishfailed": "Błąd wewnętrzny: serwer nie mógł zapisać pliku tymczasowego.",
        "api-error-stasherror": "Wystąpił błąd podczas przesyłania pliku.",
-       "api-error-stashedfilenotfound": "Nie odnaleziono pliku zapasowego podczas próby jego pobrania z archiwum.",
+       "api-error-stashedfilenotfound": "Nie odnaleziono pliku podczas próby pobrania go ze schowka.",
        "api-error-stashpathinvalid": "Ścieżka do pliku zapasowego jest błędna.",
        "api-error-stashfilestorage": "Wystąpił błąd podczas przesyłania pliku do archiwum.",
        "api-error-stashzerolength": "Serwer nie może zapisać pliku zapasowego do archiwum, gdyż ma on zerową długość.",
        "api-error-unknownerror": "Nieznany błąd: „$1”",
        "api-error-uploaddisabled": "Na tej wiki przesyłanie zostało wyłączone.",
        "api-error-verification-error": "Plik może być uszkodzony lub nazwa pliku ma nieprawidłowe rozszerzenie.",
+       "api-error-was-deleted": "Plik o tej nazwie już istniał, ale został usunięty.",
        "duration-seconds": "$1 {{PLURAL:$1|sekunda|sekundy|sekund}}",
        "duration-minutes": "$1 {{PLURAL:$1|minuta|minuty|minut}}",
        "duration-hours": "$1 {{PLURAL:$1|godzina|godziny|godzin}}",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "Symbole",
        "special-characters-group-greek": "Greckie",
+       "special-characters-group-greekextended": "Greckie (rozszerzony)",
        "special-characters-group-cyrillic": "Cyrylica",
        "special-characters-group-arabic": "Arabskie",
        "special-characters-group-arabicextended": "Arabskie (rozszerzony)",
        "mw-widgets-titleinput-description-new-page": "strona jeszcze nie istnieje",
        "mw-widgets-titleinput-description-redirect": "przekierowanie do $1",
        "api-error-blacklisted": "Wybierz inny, opisowy tytuł.",
-       "randomrootpage": "Losowa strona (bez podstron)"
+       "randomrootpage": "Losowa strona (bez podstron)",
+       "log-action-filter-block": "Rodzaj blokady:",
+       "log-action-filter-delete": "Rodzaj usunięcia:",
+       "log-action-filter-protect": "Rodzaj zabezpieczenia:",
+       "log-action-filter-upload": "Rodzaj przesłanych:",
+       "log-action-filter-all": "Wszystkie",
+       "log-action-filter-block-block": "Zablokowanie",
+       "log-action-filter-block-reblock": "Zmiana blokady",
+       "log-action-filter-block-unblock": "Odblokowanie",
+       "log-action-filter-delete-delete": "Usunięcie strony",
+       "log-action-filter-delete-restore": "Odtworzenie strony",
+       "log-action-filter-delete-event": "Usunięcie wpisu rejestru",
+       "log-action-filter-delete-revision": "Usunięcie wersji",
+       "log-action-filter-protect-protect": "Zabezpieczenie",
+       "log-action-filter-protect-modify": "Zmiana zabezpieczenia",
+       "log-action-filter-protect-unprotect": "Odbezpieczenie",
+       "log-action-filter-upload-upload": "Nowe przesłane",
+       "log-action-filter-upload-overwrite": "Przesłane ponownie"
 }
index adb63dc..228c091 100644 (file)
        "nocookiesnew": "ستاسې گڼون جوړ شو، خو تاسې لا غونډال ته نه ياست ورننوتلي.\n{{SITENAME}} کې د ننوتلو لپاره کوکيز کارېږي.\nاو ستاسې د کتنمل کوکيز ناچارن دي.\nلطفاً خپل د کتنمل کوکيز چارن کړۍ او بيا د خپل کارن-نوم او پټنوم په کارولو سره غونډال ته ورننوځی.",
        "nocookieslogin": "{{SITENAME}} کې د ننوتلو لپاره کوکيز کارېږي.\nاو ستاسې د کتنمل کوکيز ناچارن دي.\nلطفاً خپل د کتنمل کوکيز چارن کړۍ او بيا د خپل کارن-نوم او پټنوم په کارولو سره غونډال ته ورننوځی.",
        "noname": "تاسې تر اوسه پورې کوم کره کارن نوم نه دی ځانگړی کړی.",
-       "loginsuccesstitle": "غونډال کې بريالی ورننوتلۍ",
+       "loginsuccesstitle": "غونډال کې ورننوتلۍ",
        "loginsuccess": "'''تاسې اوس {{SITENAME}} کې د \"$1\" په نوم ننوتي ياست.'''",
        "nosuchuser": "د \"$1\" په نوم هېڅ کارن نشته.\nد کارنانو نومونه د غټو او واړو تورو سره حساس دي.\nخپل حجا وڅارۍ، او يا هم [[Special:UserLogin/signup|يو نوی گڼون جوړ کړی]].",
        "nosuchusershort": "د \"$1\" په نوم هېڅ کوم گڼون نشته. لطفاً خپل د نوم ليکلې بڼې ته ځير شی چې پکې تېروتنه نه وي.",
        "createaccount-title": "د {{SITENAME}} د گڼون جوړېدنه",
        "createaccount-text": "يو چا د {{SITENAME}} په وېبځي ($4) کې ستاسې د برېښليک پتې لپاره د \"$2\" په نامه يو گڼون جوړ کړی چې پټنوم يې \"$3\" دی.\nتاسې بايد غونډال ته ورننوځۍ او همدا اوس خپل پټنوم بدل کړی.\n\nکه چېرته دا کړنه په تېروتنه کې شوی وي نو تاسې کولای شی چې دا پيغام بابېزه وگڼۍ.",
        "login-throttled": "تاسې څو واره هڅه کړې چې غونډال ته ورننوځۍ.\nلطفاً د بيا هڅې نه مخکې $1 شېبې تم شۍ.",
-       "login-abort-generic": "غونډال کې مو ننوتل نابريالی شو - ناڅاپي بند شو",
+       "login-abort-generic": "غونډال کې مو ننوتل نابرياله شوه - ناڅاپي بند شو",
        "loginlanguagelabel": "ژبه: $1",
        "pt-login": "ننوتل",
        "pt-login-button": "ننوتل",
        "newpassword": "نوی پټنوم:",
        "retypenew": "نوی پټنوم بيا وليکه:",
        "resetpass_submit": "پټنوم مو وټاکۍ او بيا غونډال ته ورننوځۍ",
-       "changepassword-success": "ستاسې پټنوم په برياليتوب سره بدل شو!",
+       "changepassword-success": "ستاسې پټنوم بدل شو!",
        "changepassword-throttled": "تاسې څو واره هڅه کړې چې غونډال ته ورننوځۍ.\nلطفاً د بيا هڅې نه مخکې $1 شېبې تم شۍ.",
        "botpasswords": "روباټ پټنومونه",
        "botpasswords-label-appid": "روباټ نوم:",
        "revdelete-unsuppress": "له بيازېرمل شويو بڼو څخه محدوديتونه لرې کول",
        "revdelete-log": "سبب:",
        "revdelete-submit": "{{PLURAL:$1|ټاکلې بڼه|ټاکلو بڼو}} کې پلي کول",
-       "revdelete-success": "د بڼې ښکارېدنه په برياليتوب سره هممهاله شوه.",
+       "revdelete-success": "د بياکتنې ښکارېدنه هممهاله شوه.",
        "revdelete-failure": "د بڼې ښکارېدنه نه شي هممهاله کېدای:\n$1",
-       "logdelete-success": "د ښکارېدنې يادښت په برياليتوب سره جوړ شو.",
+       "logdelete-success": "د يادښت ښکارېدنه ځانگړې شوه.",
        "logdelete-failure": "د ښکارېدنې يادښت نه شي جوړېدلی:\n$1",
        "revdel-restore": "ښکارېدنه بدلول",
        "pagehist": "د مخ پېښليک",
        "editcomment": "د سمون لنډيز دا و: \"''$1''\".",
        "changecontentmodel-title-label": "مخ سرليک",
        "changecontentmodel-reason-label": "سبب:",
+       "changecontentmodel-submit": "بدلول",
        "logentry-contentmodel-change-revertlink": "په څټ گرځول",
        "logentry-contentmodel-change-revert": "په څټ گرځول",
        "protectlogpage": "د ژغورنې يادښت",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|بڼه|بڼې}} راولېږدېدې",
        "javascripttest": "د جاوا سکرېپټ آزمېښت",
        "javascripttest-pagetext-unknownaction": "ناڅرگنده کړنه \"$1\".",
-       "javascripttest-pagetext-skins": "د آزمېښتونو د پلي کولو لپاره يوه پوښۍ وټاکئ:",
        "tooltip-pt-userpage": "{{GENDER:|ستاسې کارن}} مخ",
        "tooltip-pt-mytalk": "{{GENDER:|ستاسې}} د خبرواترو مخ",
        "tooltip-pt-preferences": "{{GENDER:|ستاسې}} غوره توبونه",
        "tags-deactivate-submit": "نافعالول",
        "tags-edit-title": "نښلنونه سمول",
        "tags-edit-manage-link": "نښلنونه مهارول",
-       "tags-edit-existing-tags-none": "''هېڅ''",
+       "tags-edit-existing-tags-none": "<em>هېڅ</em>",
        "tags-edit-new-tags": "نوي نښلنونه:",
        "tags-edit-add": "دا نښلنونه ورگډول:",
        "tags-edit-remove": "دا نښلنونه غورځول:",
        "mw-widgets-dateinput-placeholder-month": "کککک-م م",
        "mw-widgets-titleinput-description-new-page": "تر اوسه پورې دا مخ نشته",
        "mw-widgets-titleinput-description-redirect": "$1 ته ورگرځېدنه",
-       "randomrootpage": "د ناټاکلې ريښې مخ"
+       "randomrootpage": "د ناټاکلې ريښې مخ",
+       "log-action-filter-all": "ټول",
+       "log-action-filter-block-block": "بنديز لگول"
 }
index 138010a..f2e1eb5 100644 (file)
                        "Eduardo Addad de Oliveira",
                        "Raphaelras",
                        "Arthurteb303",
-                       "Rffontenelle"
+                       "Rffontenelle",
+                       "HenriqueCrang",
+                       "Caçador de Palavras",
+                       "Luk3",
+                       "Ryuu",
+                       "Luan"
                ]
        },
        "tog-underline": "Sublinhar links:",
        "nocookieslogin": "Você tem os <i>cookies</i> desativados no seu navegador, e a {{SITENAME}} utiliza <i>cookies</i> para ligar os usuários às suas contas. Por favor os ative e tente novamente.",
        "nocookiesfornew": "A conta de usuário não foi criada porque não foi possível confirmar a sua origem.\nCertifique-se de que tem os cookies ativados, recarregue esta página e tente novamente.",
        "noname": "Você não colocou um nome de usuário válido.",
-       "loginsuccesstitle": "Login bem sucedido",
+       "loginsuccesstitle": "Autenticado",
        "loginsuccess": "'''Agora você está {{GENDER:autenticado|autenticada}} ao wiki {{SITENAME}} como \"$1\"'''.",
        "nosuchuser": "Não existe nenhum usuário com o nome \"$1\".\nOs nomes de usuário são sensíveis a letras maiúsculas.\nVerifique o que foi digitado ou [[Special:UserLogin/signup|crie uma nova conta]].",
        "nosuchusershort": "Não existe um usuário com o nome \"$1\". Verifique o nome que introduziu.",
        "botpasswords-insert-failed": "Falha ao adicionar o nome de robô \"$1\". Ele já foi adicionado?",
        "botpasswords-update-failed": "Falha ao atualizar o nome do robô \"$1\". Elo já foi apagado?",
        "botpasswords-created-title": "Senha de robô criada",
-       "botpasswords-created-body": "A senha do robô \"$1\" foi criada com sucesso.",
+       "botpasswords-created-body": "A senha de robo para o robô de nome \"$1\" do usuário \"$2\" foi criada.",
        "botpasswords-updated-title": "Senha de robô atualizada",
-       "botpasswords-updated-body": "A senha de robô \"$1\" foi atualizada com sucesso.",
+       "botpasswords-updated-body": "A senha de robô para o robô de nome \"$1\" do usuário \"$2\" foi atualizada.",
        "botpasswords-deleted-title": "Senha de bot apagada",
-       "botpasswords-deleted-body": "A senha de bot \"$1\" foi apagada.",
+       "botpasswords-deleted-body": "A senha de robô para o robô de nome \"$1\" do usuário \"$2\" foi apagada.",
+       "botpasswords-newpassword": "A nova senha para se autenticar com <strong>$1</strong> é <strong>$2</strong>. <em>Por favor, guarde isto para referência futura.",
        "botpasswords-no-provider": "BotPasswordsSessionProvider não está disponível.",
        "botpasswords-restriction-failed": "Restrições de senha de robô evitam esta autenticação.",
        "botpasswords-invalid-name": "O nome de usuário especificado não contém o separador de senha de robô (\"$1\").",
        "newarticle": "(Nova)",
        "newarticletext": "Você seguiu um link para uma página que ainda não existe.\nPara criá-la, comece escrevendo na caixa abaixo (veja [$1 a página de ajuda] para mais informações).\nSe você chegou aqui por engano, clique no botão '''voltar''' do seu navegador.",
        "anontalkpagetext": "---- ''Esta é a página de discussão para um usuário anônimo que ainda não criou uma conta ou que não a usa, de forma que temos de utilizar o endereço de IP para identificá-lo(a). Tal endereço de IP pode ser compartilhado por vários usuários. Se você é um usuário anônimo e acha que comentários irrelevantes foram direcionados a você, por gentileza, [[Special:UserLogin/signup|crie uma conta]] ou [[Special:UserLogin|autentique-se]], a fim de evitar futuras confusões com outros usuários anônimos.''",
-       "noarticletext": "No momento, não há conteúdo nesta página.\nVocê pode [[Special:Search/{{PAGENAME}}|pesquisar pelo título desta página]] em outras páginas, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar por registros relacionados],\nou [{{fullurl:{{FULLPAGENAME}}|action=edit}} criar esta página]</span>.",
+       "noarticletext": "Não há conteúdo nesta página no momento.\nVocê pode [[Special:Search/{{PAGENAME}}|pesquisar pelo título desta página]] em outras páginas, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar por registros relacionados],\nou [{{fullurl:{{FULLPAGENAME}}|action=edit}} criar esta página]</span>.",
        "noarticletext-nopermission": "No momento, não há conteúdo nesta página\nVocê pode [[Special:Search/{{PAGENAME}}|pesquisar pelo título desta página]] em outras páginas,\nou <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} buscar por registros relacionados] </span>. Note que, no entanto, você não tem permissão para criar esta página.",
        "missing-revision": "A revisão #$1 da página denominada \"{{FULLPAGENAME}}\" não existe.\n\nIsto é geralmente causado por seguir um link de histórico desatualizado para uma página que foi eliminada.\nOs detalhes podem ser encontrados no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de eliminação].",
        "userpage-userdoesnotexist": "A conta \"<nowiki>$1</nowiki>\" não se encontra registrada.\nVerifique se deseja mesmo criar/editar esta página.",
        "continue-editing": "Ir para a área de edição",
        "previewconflict": "Esta previsão reflete o texto que está na área de edição acima e como ele aparecerá se você escolher salvar.",
        "session_fail_preview": "Pedimos desculpas, mas não foi possível processar a sua edição devido à perda de dados da sua sessão.\n'''Por favor, verifique se você ainda está autenticado e tente novamente.'''\nCaso continue não funcionando, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e cheque se seu navegador permite cookies desse site.",
-       "session_fail_preview_html": "'''Desculpe-nos! Não foi possível processar a sua edição devido a uma perda de dados de sessão.'''\n\n''Como o projeto {{SITENAME}} possui HTML bruto ativo, a previsão não será exibida, como uma precaução contra ataques por JavaScript.''\n\n'''Se esta é uma tentativa de edição legítima, por favor tente novamente.\nCaso continue não funcionando, tente [[Special:UserLogout|desautenticar-se]] e voltar a entrar na sua conta.'''",
+       "session_fail_preview_html": "Desculpe! Não foi possível processar a sua edição devido a uma perda de dados de sessão.\n\n<em>Como {{SITENAME}} possui HTML bruto ativo, a previsão não será exibida como uma precaução contra ataques por JavaScript.\n\n<strong>Se esta é uma tentativa de edição legítima, por favor tente novamente.</strong>\nCaso continue não funcionando, tente [[Special:UserLogout|desautenticar-se]] e voltar a entrar na sua conta, e cheque se seu navegador permite cookies vindo deste site.",
        "token_suffix_mismatch": "'''A sua edição foi rejeitada uma vez que seu software de navegação mutilou os sinais de pontuação do sinal de edição. A edição foi rejeitada para evitar perdas no texto da página.\nIsso acontece ocasionalmente quando se usa um serviço de proxy anonimizador mal configurado.'''",
        "edit_form_incomplete": "'''Algumas partes do formulário de edição não chegaram ao servidor; verifique que a sua edição continua intacta e tente novamente, por favor.'''",
        "editing": "Editando $1",
        "permissionserrors": "Erro de permissão",
        "permissionserrorstext": "Você não possui permissão de fazer isso, {{PLURAL:$1|pelo seguinte motivo|pelos seguintes motivos}}:",
        "permissionserrorstext-withaction": "Você não possui permissão para $2, {{PLURAL:$1|pelo seguinte motivo|pelos motivos a seguir}}:",
+       "contentmodelediterror": "Você não pode editar essa revisão pois seu modelo de conteúdo é <code>$1</code>, que difere do modelo de conteúdo atual da página <code>$2</code>.",
        "recreate-moveddeleted-warn": "'''Atenção: Você está recriando uma página já eliminada em outra ocasião.'''\n\nConsidere se é realmente adequado continuar editando esta página.\nOs registros de eliminação e de movimentação desta página são exibidos a seguir, para sua comodidade:",
        "moveddeleted-notice": "Esta página foi eliminada.\nOs registros de eliminação e de movimentação para esta página estão disponibilizados abaixo, para referência.",
        "moveddeleted-notice-recent": "Desculpe, esta página foi eliminada recentemente (nos últimos 24 horas). A eliminação e se mover para a página de log são fornecidos abaixo para referência.",
        "content-json-empty-object": "Objeto vazio",
        "content-json-empty-array": "Array vazia",
        "duplicate-args-warning": "<strong> Aviso: </strong> [[:$1]] está chamando [[:$2]] com mais de um valor para o parâmetro \"$3\". Será utilizado apenas o último valor fornecido.",
-       "duplicate-args-category": "Páginas que utilizam argumentos duplicados ao chamar predefinições",
+       "duplicate-args-category": "Páginas com argumentos de predefinições duplicados",
        "duplicate-args-category-desc": "A pagina contem modelos que usam argumentos duplicados, como <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> ou <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "Aviso: Esta página contém muitas chamadas a funções do analisador \"parser\".\n\nDeveria ter menos de $2 {{PLURAL:$2|chamada|chamadas}}. Neste momento {{PLURAL:$1|há $1 chamada|existem $1 chamadas}}.",
        "expensive-parserfunction-category": "Páginas com muitas chamadas a funções do analisador \"parser\"",
        "post-expand-template-inclusion-warning": "'''Aviso''': a soma do tamanho de inclusão de predefinições é muito grande.\nAlgumas predefinições não serão processadas.",
-       "post-expand-template-inclusion-category": "Páginas onde a soma do tamanho de inclusão de predefinições é excedido",
+       "post-expand-template-inclusion-category": "Páginas com excesso de predefinições",
        "post-expand-template-argument-warning": "Aviso: Esta página contém pelo menos um argumento de predefinição com um tamanho muito grande.\nEstes argumentos foram omitidos.",
-       "post-expand-template-argument-category": "Páginas com omissões de argumentos em predefinições",
+       "post-expand-template-argument-category": "Páginas com argumentos de predefinições descartados",
        "parser-template-loop-warning": "Ciclo de predefinições detectado: [[$1]]",
        "parser-template-recursion-depth-warning": "O limite de profundidade de recursividade de predefinição foi ultrapassado ($1)",
        "language-converter-depth-warning": "O limite de profundidade do conversor de línguas excedeu a ($1)",
        "revdelete-unsuppress": "Remover restrições das edições restauradas",
        "revdelete-log": "Motivo:",
        "revdelete-submit": "Aplicar {{PLURAL:$1|à revisão selecionada|às revisões selecionadas}}",
-       "revdelete-success": "'''A visibilidade da revisão foi atualizada.'''",
+       "revdelete-success": "Visibilidade da revisão atualizada.",
        "revdelete-failure": "'''A visibilidade da revisão não foi atualizada:'''\n$1",
-       "logdelete-success": "'''Visibilidade de evento definida com sucesso.'''",
+       "logdelete-success": "Visibilidade do registro definida.",
        "logdelete-failure": "'''A visibilidade do registro não pôde ser estabelecida:'''\n$1",
        "revdel-restore": "alterar visibilidade",
        "pagehist": "Histórico da página",
        "mergehistory-empty": "Não existem edições habilitadas a serem fundidas.",
        "mergehistory-done": "$3 {{PLURAL:$3|revisão|revisões}} de $1 fundidas em [[:$2]] com sucesso.",
        "mergehistory-fail": "Não foi possível fundir os históricos; por gentileza, verifique a página e os parâmetros de tempo.",
+       "mergehistory-fail-bad-timestamp": "Informação data/hora inválida.",
+       "mergehistory-fail-invalid-source": "Página de origem inválida.",
+       "mergehistory-fail-invalid-dest": "Página de destino é inválida.",
+       "mergehistory-fail-no-change": "A fusão de histórico não fundiu nenhuma revisão. Por favor reavalie os parâmetros página e tempo.",
+       "mergehistory-fail-permission": "Permissões insuficientes para fundir histórico.",
+       "mergehistory-fail-self-merge": "As páginas de origem e destino são as mesmas.",
+       "mergehistory-fail-timestamps-overlap": "As revisões fonte sobrescrevem ou vêm após as revisões de destino",
        "mergehistory-fail-toobig": "Não é possível fundir o histórico, já que um número de revisão(ões) acima do limite ($1 {{PLURAL:$1|revisão|revisões}}) seriam movidos.",
        "mergehistory-no-source": "A página de origem ($1) não existe.",
        "mergehistory-no-destination": "A página de destino ($1) não existe.",
        "userrights-changeable-col": "Grupos que pode alterar",
        "userrights-unchangeable-col": "Grupos que não pode alterar",
        "userrights-conflict": "Há um comflito de permissões de usuário! Por favor, revise e confirme as alterações novamente.",
-       "userrights-removed-self": "Você removeu com sucesso seus direitos de usuário. Como tal, você agora está impossibilitado de acessar esta página.",
+       "userrights-removed-self": "Você removeu seus privilégios. Portanto, você agora não pode mais acessar esta página.",
        "group": "Grupo:",
        "group-user": "Usuários",
        "group-autoconfirmed": "Usuários autoconfirmados",
        "right-managechangetags": "Criar e apagar [[Special:Tags|tags]] na base de dados",
        "right-applychangetags": "Aplicar [[Special:Tags|etiquetas]] juntamente com as alterações de alguém",
        "right-changetags": "Adicionar e remover [[Special:Tags|etiquetas]] arbitrárias em revisões e ''logs'' individuais",
+       "grant-generic": "conjunto de direitos \"$1\"",
        "grant-group-page-interaction": "Interagir com páginas",
+       "grant-group-file-interaction": "Interagir com multimídia",
        "grant-group-watchlist-interaction": "Interagir com sua lista de páginas vigiadas",
        "grant-group-email": "Enviar e-mail",
        "grant-group-high-volume": "Realizar grande volume de atividades",
        "grant-createaccount": "Criar contas",
        "grant-createeditmovepage": "Criar, editar e mover páginas",
        "grant-delete": "Excluir páginas, revisões e entradas de registro",
+       "grant-editinterface": "Editar o domínio MediaWiki e o CSS/JavaScript do usuário",
+       "grant-editmycssjs": "Editar o seu CSS/JavaScript de usuário",
        "grant-editmyoptions": "Editar suas preferências de usuário",
        "grant-editmywatchlist": "Editar sua lista de páginas vigiadas",
        "grant-editpage": "Editar páginas existentes",
        "rcshowhidemine": "$1 minhas edições",
        "rcshowhidemine-show": "Exibir",
        "rcshowhidemine-hide": "Ocultar",
+       "rcshowhidecategorization": "$1 categorização de páginas",
        "rcshowhidecategorization-show": "Exibir",
        "rcshowhidecategorization-hide": "Esconder",
        "rclinks": "Exibir as $1 alterações recentes feitas nos últimos $2 dias<br />$3",
        "recentchangeslinked-page": "Nome da página:",
        "recentchangeslinked-to": "Inversamente, mostrar mudanças nas páginas que contêm ligações para esta",
        "recentchanges-page-added-to-category": "[[:$1]]adicionada à categoria",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|uma página|$2 páginas}}]] adicionadas à categoria",
+       "recentchanges-page-removed-from-category": "[[:$1]] removida da categoria",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|uma página|$2 páginas}}]] removidas da categoria",
        "autochange-username": "Alteração automática do MediaWiki",
        "upload": "Enviar arquivo",
        "uploadbtn": "Enviar arquivo",
        "uploaded-script-svg": "Encontrado elemento de script \"$1\" no arquivo SVG carregado.",
        "uploaded-hostile-svg": "Encontrado CSS inseguro no elemento de estilo do arquivo SVG carregado.",
        "uploaded-event-handler-on-svg": "Não é permitido configurar atributos que manipulem eventos  <code>$1=\"$2\"</code> em arquivos SVG.",
+       "uploaded-href-attribute-svg": "os atributos href nos ficheiros SVG só están autorizados a ligar a direccións http:// ou https://, atopado <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-href-unsafe-target-svg": "Encontrado href para dados não seguros: alvo URI <code>&lt;$1 $2=\"$3\"&gt;</code> no arquivo SVG carregado.",
        "uploadscriptednamespace": "Este aruivo SVG contém um espaço nominal probido \"$1\"",
        "uploadinvalidxml": "O XML no arquivo enviado não pôde ser analisado.",
        "uploadvirus": "O arquivo contém vírus!\nDetalhes: $1",
        "uploadstash-badtoken": "Não foi possível executar essa operação, talvez porque as suas credenciais de edição expiraram. Tente novamente.",
        "uploadstash-errclear": "Não foi possível apagar os arquivos.",
        "uploadstash-refresh": "Atualizar a lista de arquivos",
+       "uploadstash-thumbnail": "ver miniatura",
        "invalid-chunk-offset": "Deslocamento de fragmento inválido",
        "img-auth-accessdenied": "Acesso negado",
        "img-auth-nopathinfo": "PATH_INFO em falta.\nO seu servidor não está configurado para passar esta informação.\nPode ser baseado em CGI e não consegue suportar img_auth.\nConsulte a documentação em [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization Image Authorization].",
        "import-logentry-upload-detail": "{{PLURAL:$1|uma edição|$1 edições}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|$1 edição|$1 edições}} de $2",
        "javascripttest": "Teste de JavaScript",
-       "javascripttest-pagetext-noframework": "Esta página é exclusiva para testes de JavaScript.",
-       "javascripttest-pagetext-unknownframework": "A estrutura de testes \"$1\" é desconhecida.",
        "javascripttest-pagetext-unknownaction": "Ação desconhecida de $1",
-       "javascripttest-pagetext-frameworks": "Escolha uma das seguintes estruturas de teste: $1",
-       "javascripttest-pagetext-skins": "Escolha o tema para executar os testes:",
        "javascripttest-qunit-intro": "Veja a [$1 documentação de testes] no mediawiki.org.",
        "tooltip-pt-userpage": "Sua página de {{GENDER:|usuário|usuária|usuário(a)}}",
        "tooltip-pt-anonuserpage": "A página de usuário para o ip com o qual você está editando",
        "watchlisttools-edit": "Ver e editar a lista de páginas vigiadas",
        "watchlisttools-raw": "Edição crua da lista de páginas vigiadas",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussão]])",
-       "timezone-local": "Localização",
+       "timezone-local": "Local",
        "duplicate-defaultsort": "Aviso: A chave de ordenação padrão \"$2\" sobrepõe-se à anterior chave de ordenação padrão \"$1\".",
        "duplicate-displaytitle": "<strong>Aviso:</strong> O título exibido \"$2\" substituí o título anterior \"$1\".",
        "invalid-indicator-name": "<strong>Erro:</strong> O atributo indicador do status da página <code>name</code> não deve estar vazio.",
        "version-libraries-description": "Descrição",
        "version-libraries-authors": "Autores",
        "redirect": "Redirecionar por arquivo, usuário, página, revisão ou registro de identificação.",
-       "redirect-legend": "Redirecionar para um arquivo ou página",
        "redirect-summary": "Esta página especial redireciona a um arquivo (dado o nome do arquivo), a uma página (dado um ID de revisão ou ID da página) ou a uma página de usuário (dado o ID do usuário). Uso: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Ir",
        "redirect-lookup": "Buscar",
        "logentry-protect-protect": "$1 {{GENDER:$2|protegeu}} $3 $4",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|protegeu}} $3 $4 [em cascata]",
        "logentry-protect-modify": "$1 {{GENDER:$2|alterou}} o nível de proteção para $3 $4",
+       "logentry-protect-modify-cascade": "$1 {{GENDER:$2|alterou}} o nível de proteção para $3 $4 [em cascata]",
        "logentry-rights-rights": "$1 alterou os grupos de usuário de $3 de $4 para $5",
        "logentry-rights-rights-legacy": "$1 alterou os grupos de $3",
        "logentry-rights-autopromote": "$1 foi promovido automaticamente de $4 para $5",
-       "logentry-upload-upload": "$1 {{GENDER:$2|carregado}} $3",
+       "logentry-upload-upload": "$1 {{GENDER:$2|carregou}} $3",
        "logentry-upload-overwrite": "$1 {{GENDER:$2|carregada}} uma nova versão de $3",
        "logentry-upload-revert": "$1 {{GENDER:$2|carregado}} $3",
        "log-name-managetags": "Registo de gestão de etiquetas",
index 304fd47..c592b28 100644 (file)
                        "He7d3r",
                        "Ti4goc",
                        "Jkb8",
-                       "Önni"
+                       "Önni",
+                       "Diniscoelho",
+                       "Josep Maria Roca Peña",
+                       "Luan"
                ]
        },
        "tog-underline": "Sublinhar ligações:",
        "nocookieslogin": "A {{SITENAME}} utiliza ''cookies'' para autenticar os utilizadores.\nOs ''cookies'' estão desativados no seu navegador.\nAtive-os e tente novamente, por favor.",
        "nocookiesfornew": "A conta de utilizador não foi criada, porque não foi possível confirmar a sua origem.\nCertifique-se de que tem os ''cookies'' ativados, recarregue esta página e tente novamente.",
        "noname": "Não especificou um nome de utilizador válido.",
-       "loginsuccesstitle": "Início de sessão bem sucedido",
+       "loginsuccesstitle": "Autenticação bem sucedida",
        "loginsuccess": "'''Encontra-se agora ligado à {{SITENAME}} como \"$1\"'''.",
        "nosuchuser": "Não existe nenhum utilizador com o nome \"$1\".\nOs nomes de utilizador são sensíveis à capitalização.\nVerifique a ortografia, ou [[Special:UserLogin/signup|crie uma nova conta]].",
        "nosuchusershort": "Não existe um utilizador com o nome \"$1\". Verifique o nome que introduziu.",
        "noemail": "Não foi registado um endereço de correio eletrónico para o utilizador \"$1\".",
        "noemailcreate": "Tem de fornecer um endereço de correio eletrónico válido.",
        "passwordsent": "Foi enviada uma palavra-passe nova para o endereço de correio eletrónico do utilizador \"$1\".\nVolte a iniciar sessão após recebê-la, por favor.",
-       "blocked-mailpassword": "O seu endereço IP foi bloqueado e, portanto, não será possível utilizar a função de recuperação da palavra-passe, para prevenir o uso abusivo.",
+       "blocked-mailpassword": "O seu endereço IP está bloqueado para edição. Para evitar abusos, não é permitido a utilização da recuperação de palavra-passe a partir deste endereço IP.",
        "eauthentsent": "Foi enviada uma mensagem de confirmação para o endereço de correio eletrónico que especificou.\nAntes que seja enviada qualquer outra mensagem para a conta, terá de seguir as instruções na mensagem enviada, de modo a confirmar que a conta lhe pertence.",
        "throttled-mailpassword": "Já foi enviada um email de recuperação de palavra-passe {{PLURAL:$1|na última hora|nas últimas $1 horas}}.\nPara prevenir abusos, só um email de recuperação de palavra-passe pode ser enviado a cada {{PLURAL:$1|hora|$1 horas}}.",
        "mailerror": "Erro ao enviar correio electrónico: $1",
        "createaccount-title": "Criação de conta na {{SITENAME}}",
        "createaccount-text": "Alguém criou uma conta com o nome $2 para o seu endereço de correio eletrónico, na wiki {{SITENAME}} ($4), com a palavra-passe \"$3\".\nDeve agora iniciar sessão e alterar a sua palavra-passe.\n\nSe a conta foi criada por engano, pode ignorar esta mensagem.",
        "login-throttled": "Realizou demasiadas tentativas de início de sessão com esta conta.\nAguarde $1 antes de tentar novamente, por favor.",
-       "login-abort-generic": "O início de sessão não teve êxito - Cancelado",
+       "login-abort-generic": "O início de sessão falhou - Cancelado",
        "login-migrated-generic": "A sua conta foi migrada e o seu nome de utilizador já não existe nesta wiki.",
        "loginlanguagelabel": "Idioma: $1",
        "suspicious-userlogout": "O seu pedido para sair foi negado porque parece ter sido enviado por um navegador danificado ou por um proxy com cache.",
        "botpasswords-insert-failed": "Falhou ao adicionar o nome do robô \"$1\". Já foi adicionado?",
        "botpasswords-update-failed": "Falha ao atualizar o nome do robô \"$1\". Será que foi eliminado?",
        "botpasswords-created-title": "Criada palavra-passe para o robô",
-       "botpasswords-created-body": "A palavra-passe para o robô \"$1\" foi criada com sucesso.",
+       "botpasswords-created-body": "O robô palavra-passe para o nome do robô \"$1\" do utilizador \"$2\" foi criado.",
        "botpasswords-updated-title": "A palavra-passe de robô foi actualizada.",
-       "botpasswords-updated-body": "A palavra-passe de robô \"$1\" foi actualizada com sucesso.",
+       "botpasswords-updated-body": "O robô palavra-passe para o nome do robô \"$1\" do utilizador \"$2\" foi atualizado.",
        "botpasswords-deleted-title": "Palavra-passe de robô eliminada",
-       "botpasswords-deleted-body": "A palavra-passe de robô \"$1\" foi eliminada.",
+       "botpasswords-deleted-body": "O robô palavra-passe para o nome do robô \"$1\"do utilizador \"$2\" foi eliminado.",
        "botpasswords-newpassword": "A nova palavra-passe para iniciar sessão com <strong>$1</strong> é <strong>$2</strong>. Por favor, recorde-se dela para futura referência.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider não está disponível.",
        "resetpass_forbidden": "Não é possível alterar palavras-passe",
        "resetpass-no-info": "Precisa de iniciar sessão para aceder diretamente a esta página.",
        "resetpass-submit-loggedin": "Alterar palavra-passe",
        "resetpass-submit-cancel": "Cancelar",
-       "resetpass-wrong-oldpass": "Palavra-passe temporária ou atual inválida.\nPode ter já alterado com sucesso a sua palavra-passe ou solicitado uma nova palavra-passe temporária.",
+       "resetpass-wrong-oldpass": "Palavra-passe temporária ou atual inválida.\nPode ter já alterado a sua palavra-passe ou solicitado uma nova palavra-passe temporária.",
        "resetpass-recycled": "Redefina a sua palavra-passe para uma diferente da atual, por favor.",
        "resetpass-temp-emailed": "Iniciou a sessão com um código temporário.\nPara completar a autenticação, tem de definir uma palavra-passe nova aqui:",
        "resetpass-temp-password": "Palavra-passe temporária:",
        "content-json-empty-object": "Objeto vazio",
        "content-json-empty-array": "Matriz vazia",
        "duplicate-args-warning": "<strong>Aviso:</strong> [[:$1]] chama [[:$2]] com mais de um valor para o parâmetro \"$3\". Somente o último valor fornecido será utilizado.",
-       "duplicate-args-category": "Páginas que utilizam argumentos duplicados ao chamar predefinições",
+       "duplicate-args-category": "Páginas com argumentos de predefinições duplicados",
        "duplicate-args-category-desc": "A página contém campos de predefinições que utilizam duplicatas de argumentos, tais como <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> ou <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "'''Aviso:''' Esta página contém demasiadas chamadas de funções exigentes do analisador sintático.\n\nDevia ter menos de $2 {{PLURAL:$2|chamada|chamadas}}. Neste momento tem $1 {{PLURAL:$1|chamada|chamadas}}.",
        "expensive-parserfunction-category": "Páginas com demasiadas chamadas a funções exigentes",
        "post-expand-template-inclusion-warning": "Aviso: O tamanho de inclusão de predefinições é demasiado grande, algumas predefinições não serão incluídas.",
-       "post-expand-template-inclusion-category": "Páginas onde o tamanho de inclusão de predefinições é excedido",
+       "post-expand-template-inclusion-category": "Páginas com excesso de predefinições",
        "post-expand-template-argument-warning": "Aviso: Esta página contém pelo menos um argumento de predefinição com um tamanho expandido demasiado grande.\nEstes argumentos foram omitidos.",
-       "post-expand-template-argument-category": "Páginas com omissão de argumentos para predefinições",
+       "post-expand-template-argument-category": "Páginas com argumentos de predefinições descartados",
        "parser-template-loop-warning": "Ciclo de predefinições detetado: [[$1]]",
        "parser-template-recursion-depth-warning": "Foi excedido o limite da profundidade de recursividade nas predefinições ($1)",
        "language-converter-depth-warning": "O limite de profundidade do conversor de idiomas excedeu a ($1)",
        "revdelete-unsuppress": "Remover restrições das revisões restauradas",
        "revdelete-log": "Motivo:",
        "revdelete-submit": "Aplicar {{PLURAL:$1|à revisão selecionada|às revisões selecionadas}}",
-       "revdelete-success": "'''A visibilidade da revisão foi atualizada.'''",
+       "revdelete-success": "Visibilidade da revisão atualizada.",
        "revdelete-failure": "'''A visibilidade da revisão não foi atualizada:'''\n$1",
-       "logdelete-success": "'''A visibilidade da entrada do registo foi definida.'''",
+       "logdelete-success": "Visibilidade da entrada do registo definida.",
        "logdelete-failure": "'''Não foi possível definir a visibilidade da entrada do registo:'''\n$1",
        "revdel-restore": "Alterar visibilidade",
        "pagehist": "Histórico da página",
        "userrights-changeable-col": "Grupos que pode alterar",
        "userrights-unchangeable-col": "Grupos que não pode alterar",
        "userrights-conflict": "Conflito entre alterações de privilégios de utilizador! Por favor, reveja e confirme as suas mudanças.",
-       "userrights-removed-self": "Removeu com sucesso os seus privilégios. Como resultado disso, já não consegue aceder a esta página.",
+       "userrights-removed-self": "Removeu os seus privilégios. Como resultado disto, já não consegue aceder a esta página.",
        "group": "Grupo:",
        "group-user": "Utilizadores",
        "group-autoconfirmed": "Utilizadores autoconfirmados",
        "recentchangeslinked-page": "Nome da página:",
        "recentchangeslinked-to": "Inversamente, mostrar mudanças às páginas que contêm ligações para esta",
        "recentchanges-page-added-to-category": "[[:$1]] foi adicionada à categoria",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] e {{PLURAL:$2|uma outra página|$2 outras páginas}} foram adicionadas à categoria",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|uma outra página|$2 outras páginas}}]] foram adicionadas à categoria",
        "recentchanges-page-removed-from-category": "[[:$1]] foi removida da categoria",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e {{PLURAL:$2|uma outra página|$2 outras páginas}} foram removidas da categoria",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] e [[Special:WhatLinksHere/$1|{{PLURAL:$2|uma outra página|$2 outras páginas}}]] foram removidas da categoria",
        "autochange-username": "Alteração automática do MediaWiki",
        "upload": "Carregar ficheiro",
        "uploadbtn": "Carregar ficheiro",
        "uploadstash-summary": "Esta página dá acesso aos ficheiros enviados (ou que estão no processo de envio) mas que ainda não foram publicados na wiki. Estes ficheiros não são visíveis para ninguém, exceto para o utilizador que os enviou.",
        "uploadstash-clear": "Apagar os ficheiros escondidos",
        "uploadstash-nofiles": "Não tem ficheiros escondidos.",
-       "uploadstash-badtoken": "Não foi possível executar essa operação, talvez porque as suas credenciais de edição expiraram. Tente novamente.",
+       "uploadstash-badtoken": "Não foi possível executar a operação. Talvez as suas credenciais de edição tenham expirado. Tente novamente.",
        "uploadstash-errclear": "Não foi possível apagar os ficheiros.",
        "uploadstash-refresh": "Atualizar a lista de ficheiros",
+       "uploadstash-thumbnail": "ver miniatura",
        "invalid-chunk-offset": "Deslocamento de fragmento inválido",
        "img-auth-accessdenied": "Acesso negado",
        "img-auth-nopathinfo": "PATH_INFO em falta.\nO seu servidor não está configurado para passar esta informação.\nPode ser baseado em CGI e não consegue suportar img_auth.\nConsulte a documentação em https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "listgrants-summary": "Esta é uma lista de atribuições com os respetivos acessos às permissões de utilizador. Os utilizadores podem autorizar aplicações a utilizar suas contas, mas com permissões limitadas baseadas nas atribuições dadas pelos utilizadores a cada aplicação. No entanto, uma aplicação agindo em nome de um utilizador não pode utilizar permissões que o utilizador não possui.\nPode haver [[{{MediaWiki:Listgrouprights-helppage}}|informação adicional]] sobre permissões individuais.",
        "listgrants-grant": "Atribuição",
        "listgrants-rights": "Direitos",
-       "trackingcategories": "Categorias de monitorização",
+       "trackingcategories": "Categorias de rastreamento",
        "trackingcategories-summary": "Esta página lista as categorias monitoradas que foram geradas automaticamente pelo software MediaWiki. Os seus nomes podem ser alterados ao editar sua mensagem correspondente no domínio {{ns:8}}.",
        "trackingcategories-msg": "Categoria monitorada",
        "trackingcategories-name": "Nome da mensagem",
        "changecontentmodel-title-label": "Título da página",
        "changecontentmodel-model-label": "Novo modelo de conteúdo",
        "changecontentmodel-reason-label": "Motivo:",
+       "changecontentmodel-submit": "Alterar",
        "changecontentmodel-success-title": "O modelo de conteúdo foi alterado",
        "changecontentmodel-success-text": "O tipo de conteúdo de [[:$1]] foi alterado.",
        "logentry-contentmodel-change-revertlink": "reverter",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|edição importada|edições importadas}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|edição importada|edições importadas}} de $2",
        "javascripttest": "Teste de JavaScript",
-       "javascripttest-pagetext-noframework": "Esta página é reservada para a execução de testes de JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Estrutura de testes \"$1\" desconhecida.",
        "javascripttest-pagetext-unknownaction": "Ação \"$1\" desconhecida.",
-       "javascripttest-pagetext-frameworks": "Escolha, por favor, uma das seguintes estruturas de teste: $1",
-       "javascripttest-pagetext-skins": "Escolher um tema para executar os testes com:",
        "javascripttest-qunit-intro": "Consulte a [ $1 documentação de testes] no mediawiki.org.",
        "tooltip-pt-userpage": "A sua página de {{GENDER:|utilizador|utilizadora|utilizador(a)}}",
        "tooltip-pt-anonuserpage": "A página de utilizador para o endereço IP que está a usar",
        "version-libraries-description": "Descrição",
        "version-libraries-authors": "Autores",
        "redirect": "Redirecionar por ficheiro, utilizador, página, revisão, ou ID de registo",
-       "redirect-legend": "Redirecionar para um ficheiro ou página",
-       "redirect-summary": "Esta página especial redireciona para um ficheiro (dado o nome do ficheiro), para uma página (dado um ID de revisão ou página) ou para uma página de utilizador (dado um ID numérico do utilizador), ou para uma entrada do registo (dado o ID do registo). Utilização: [[{{#Special:Redirect}}/file/Example.jpg]], \n[[{{#Special:Redirect}}/page/64308]], [{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], ou [[{{#Special:Redirect}}/logid/186]].",
+       "redirect-summary": "Esta página especial redireciona para um ficheiro (dado o nome do ficheiro), para uma página (dado um ID de revisão ou página) ou para uma página de utilizador (dado um ID numérico do utilizador), ou para uma entrada do registo (dado o ID do registo). Utilização: [[{{#Special:Redirect}}/file/Example.jpg]], \n[[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], ou [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Ir",
        "redirect-lookup": "Pesquisa:",
        "redirect-value": "Valor:",
        "tags-delete-not-allowed": "Etiquetas definidas por uma extensão não podem ser eliminadas, a menos que a extensão, especificamente, o permita.",
        "tags-delete-not-found": "A etiqueta \"$1\" não existe.",
        "tags-delete-too-many-uses": "A etiqueta \"$1\" está aplicada em mais que $2 {{PLURAL:$2|edição|edições}}, o que significa que não pode ser eliminada.",
-       "tags-delete-warnings-after-delete": "A etiqueta \"$1\" foi eliminada com sucesso, mas {{PLURAL:$2|o seguinte aviso foi encontrado|os seguintes avisos foram encontrados}}:",
+       "tags-delete-warnings-after-delete": "A etiqueta \"$1\" foi eliminada, mas {{PLURAL:$2|o seguinte aviso foi encontrado|os seguintes avisos foram encontrados}}:",
        "tags-activate-title": "Ativar etiqueta",
        "tags-activate-question": "Está prestes a ativar a etiqueta \"$1\".",
        "tags-activate-reason": "Motivo:",
        "tags-edit-reason": "Motivo:",
        "tags-edit-revision-submit": "Aplicar alterações a {{PLURAL:$1|esta revisões|$1 revisões}}",
        "tags-edit-logentry-submit": "Aplicar alterações a {{PLURAL:$1|esta entrada de registo|$1 entradas de registo}}",
-       "tags-edit-success": "As alterações foram aplicadas com sucesso.",
+       "tags-edit-success": "As alterações foram aplicadas.",
        "tags-edit-failure": "As alterações não puderam ser aplicadas:\n$1",
        "tags-edit-nooldid-title": "Revisão de página inválida",
        "tags-edit-nooldid-text": "Não foi especificada nenhuma revisão na qual será realizada esta ação, ou a revisão especificada não existe.",
        "logentry-protect-protect": "$1 {{GENDER:$2|protegeu}} $3 $4",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|protegeu}} $3 $4 [em cascata]",
        "logentry-protect-modify": "$1 {{GENDER:$2|alterou}} o nível de proteção para $3 $4",
-       "logentry-protect-modify-cascade": "$1 {{GENDER:$2|alterado}} nível de proteção para us$3 $4 [cascading]",
+       "logentry-protect-modify-cascade": "$1 {{GENDER:$2|alterou}} o nível de proteção para $3 $4 [em cascata]",
        "logentry-rights-rights": "$1 modificou os privilégios do utilizador $3 de $4 para $5",
        "logentry-rights-rights-legacy": "$1 alterou os grupos de $3",
        "logentry-rights-autopromote": "$1 foi automaticamente {{GENDER:$2|promovido|promovida}} de $4 a $5",
        "sessionprovider-generic": "Sessões $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sessões baseadas em cookie",
        "sessionprovider-nocookies": "Os cookies podem estar desativados. Certifique-se de que os cookies estão ativados e inicie novamente.",
-       "randomrootpage": "Página raiz aleatória"
+       "randomrootpage": "Página raiz aleatória",
+       "log-action-filter-block": "Tipo de bloqueio:",
+       "log-action-filter-delete": "Tipo de eliminação:",
+       "log-action-filter-patrol": "Tipo de patrulha:",
+       "log-action-filter-protect": "Tipo de proteção:",
+       "log-action-filter-upload": "Tipo de carregamento:",
+       "log-action-filter-all": "Todas",
+       "log-action-filter-block-block": "Bloquear",
+       "log-action-filter-block-reblock": "Alteração de bloqueio",
+       "log-action-filter-block-unblock": "Desbloquear",
+       "log-action-filter-delete-delete": "Eliminação de página",
+       "log-action-filter-delete-restore": "Restauro de página",
+       "log-action-filter-delete-event": "Eliminação de registo",
+       "log-action-filter-delete-revision": "Eliminação de revisão",
+       "log-action-filter-patrol-patrol": "Patrulha manual",
+       "log-action-filter-patrol-autopatrol": "Patrulha automática",
+       "log-action-filter-protect-protect": "Proteção",
+       "log-action-filter-protect-modify": "Alteração da proteção",
+       "log-action-filter-protect-unprotect": "Desproteção",
+       "log-action-filter-upload-upload": "Novo carregamento",
+       "log-action-filter-upload-overwrite": "Recarregar"
 }
index 301e5a6..b817a0e 100644 (file)
        "botpasswords-insert-failed": "Error message when saving a new bot password failed. It's likely that the failure was because the user resubmitted the form after a previous successful save. Parameters:\n* $1 - Bot name",
        "botpasswords-update-failed": "Error message when saving changes to an existing bot password failed. It's likely that the failure was because the user deleted the bot password in another browser window. Parameters:\n* $1 - Bot name",
        "botpasswords-created-title": "Title of the success page when a new bot password is created.",
-       "botpasswords-created-body": "Success message when a new bot password is created. Parameters:\n* $1 - Bot name",
+       "botpasswords-created-body": "Success message when a new bot password is created. Parameters:\n* $1 - Bot name\n* $2 - User name",
        "botpasswords-updated-title": "Title of the success page when a bot password is updated.",
-       "botpasswords-updated-body": "Success message when a bot password is updated. Parameters:\n* $1 - Bot name",
+       "botpasswords-updated-body": "Success message when a bot password is updated. Parameters:\n* $1 - Bot name\n* $2 - User name",
        "botpasswords-deleted-title": "Title of the success page when a bot password is deleted.",
-       "botpasswords-deleted-body": "Success message when a bot password is deleted. Parameters:\n* $1 - Bot name",
+       "botpasswords-deleted-body": "Success message when a bot password is deleted. Parameters:\n* $1 - Bot name\n* $2 - User name",
        "botpasswords-newpassword": "Success message to display the new password when a bot password is created or updated. Parameters:\n* $1 - User name to be used for login.\n* $2 - Password to be used for login.",
        "botpasswords-no-provider": "Error message when login is attempted but the BotPasswordsSessionProvider is not included in <code>$wgSessionProviders</code>.",
        "botpasswords-restriction-failed": "Error message when login is rejected because the configured restrictions were not satisfied.",
        "undo-summary-username-hidden": "Edit summary for an undo action where the username of the old revision is hidden.\n\nParameters:\n* $1 - the revision ID being undone\nSee also:\n* {{msg-mw|Undo-summary}}",
        "cantcreateaccounttitle": "Used as title of the error message {{msg-mw|Cantcreateaccount-text}}.",
        "cantcreateaccount-text": "Used as error message, with the title {{msg-mw|Cantcreateaccounttitle}}.\n* $1 - target IP address\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\nSee also:\n* {{msg-mw|Cantcreateaccount-range-text}}",
-       "cantcreateaccount-range-text": "Used as more detailed version of the {{msg-mw|Cantcreateaccount-text}} error message, with the title {{msg-mw|Cantcreateaccounttitle}}.\n* $1 - target IP range\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\n* $4 - current user's IP address",
+       "cantcreateaccount-range-text": "Used as more detailed version of the {{msg-mw|Cantcreateaccount-text}} error message, with the title {{msg-mw|Cantcreateaccounttitle}}.\n* $1 - target IP address range\n* $2 - reason or {{msg-mw|Blockednoreason}}\n* $3 - username\n* $4 - current user's IP address",
        "createaccount-hook-aborted": "Placeholder message to return with API errors on account create; passes through the message from a hook {{notranslate}}",
        "viewpagelogs": "Link displayed in history of pages",
        "nohistory": "Message shown when there are no history to list. See [{{canonicalurl:x|action=history}} example history].\n----\nAlso used as title of error message when the feed is empty. See [{{canonicalurl:x|action=history&feed=atom}} example feed].\n\nSee the error message:\n* {{msg-mw|history-feed-empty}}",
        "grant-group-page-interaction": "{{Related|grant-group}}",
        "grant-group-file-interaction": "{{Related|grant-group}}",
        "grant-group-watchlist-interaction": "{{Related|grant-group}}",
-       "grant-group-email": "{{Related|grant-group}}\n{{Identical|E-mail}}",
-       "grant-group-high-volume": "{{Related|grant-group}}",
-       "grant-group-customization": "{{Related|grant-group}}",
-       "grant-group-administration": "{{Related|grant-group}}",
-       "grant-group-other": "{{Related|grant-group}}",
+       "grant-group-email": "{{Related|Grant-group}}\n{{Identical|E-mail}}",
+       "grant-group-high-volume": "{{Related|Grant-group}}",
+       "grant-group-customization": "{{Related|Grant-group}}",
+       "grant-group-administration": "{{Related|Grant-group}}",
+       "grant-group-other": "{{Related|Grant-group}}",
        "grant-blockusers": "Name for grant \"blockusers\".\n{{Related|grant}}",
        "grant-createaccount": "Name for grant \"createaccount\".\n{{Related|grant}}",
        "grant-createeditmovepage": "Name for grant \"createeditmovepage\".\n{{Related|grant}}",
        "uploadstash-badtoken": "Used as error message in [[Special:UploadStash]].",
        "uploadstash-errclear": "Used as error message in [[Special:UploadStash]].",
        "uploadstash-refresh": "Used as link text in [[Special:UploadStash]].",
+       "uploadstash-thumbnail": "Used as link text in [[Special:UploadStash]].",
        "invalid-chunk-offset": "Error that can happen if chunks get uploaded out of order.\nAs a result of this error, clients can continue from an offset provided or restart the upload.\nUsed on [[Special:UploadWizard]].",
        "img-auth-accessdenied": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Access Denied\n{{Identical|Access denied}}",
        "img-auth-nopathinfo": "[[mw:Manual:Image Authorization|Manual:Image Authorization]]: Missing PATH_INFO - see english description\n{{Doc-important|This is plain text. Do not use any wiki syntax.}}",
        "changecontentmodel-title-label": "Label for the input field where the target page title should be entered\n{{Identical|Page title}}",
        "changecontentmodel-model-label": "Label of the dropdown listing available content model types the user can change a page to",
        "changecontentmodel-reason-label": "{{Identical|Reason}}",
+       "changecontentmodel-submit": "Label of the form \"submit\" button for [[Special:ChangeContentModel]]\n{{Identical|Change}}",
        "changecontentmodel-success-title": "Title of the success page of the change content model special page",
        "changecontentmodel-success-text": "Message telling user that their change has been successfully done.\n* $1 - Target page title",
        "changecontentmodel-cannot-convert": "Error message shown if the content model cannot be changed to the specified type. $1 is the page title, $2 is the localized content model name.",
        "ipb-unblock": "Used as page title in [[Special:Block]], if the target user is not specified.\n\nSee also:\n* {{msg-mw|Ipb-unblock-addr}}",
        "ipb-blocklist": "Used as link text in [[Special:Block]].\n\nThe link points to Specil:BlockList.",
        "ipb-blocklist-contribs": "Used in [[Special:Block]].\n* $1 - target username",
+       "ipb-blocklist-duration-left": "Used on [[Special:BlockList]] to show the remaining time (years, months, days, hours, minutes) until the block expires.\n$1 - The duration left",
        "unblockip": "Used as legend for the form in [[Special:Unblock]].",
        "unblockiptext": "Used in the {{msg-mw|Unblockip}} form on [[Special:Unblock]].",
        "ipusubmit": "Used as button text on [{{canonicalurl:Special:BlockList|action=unblock}} Special:BlockList?action=unblock]. To see the message:\n* Go to [[Special:BlockList]]\n* Click \"unblock\" for any block (but you can only see \"unblock\" if you have administrator rights)\n* It is now the button below the form",
        "ipb_expiry_temp": "Warning message displayed on [[Special:BlockIP]] if the option \"hide username\" is selected but the expiry time is not infinite.",
        "ipb_hide_invalid": "Used as error message in [[Special:Block]].\n* $1 - Number of edits (Value of [[mw:Manual:$wgHideUserContribLimit]])",
        "ipb_already_blocked": "{{Identical|$1 is already blocked}}",
-       "ipb-needreblock": "Used in [[Special:Block]].\n* $1 - target username",
+       "ipb-needreblock": "Used in [[Special:Block]].\n* $1 - target username, can be used for GENDER support",
        "ipb-otherblocks-header": "[[File:Special.Block with other blocks from GlobalBlocking and TorBlocks.png|thumb|Example]]\nUsed on [[Special:Block]] as header for other blocks, i.e. from GlobalBlocking or TorBlocks\n\nParameters:\n* $1 - number of blocks\nSee also:\n* {{msg-mw|Ipblocklist-otherblocks}}",
        "unblock-hideuser": "{{doc-singularthey}}",
        "ipb_cant_unblock": "Used as error message in [[Special:Unblock]]. Parameters:\n* $1 - block ID",
-       "ipb_blocked_as_range": "Used when unblock of a single IP fails. Parameters:\n* $1 - IP address\n* $2 - IP range",
+       "ipb_blocked_as_range": "Used when unblock of a single IP fails. Parameters:\n* $1 - IP address\n* $2 - IP address range",
        "ip_range_invalid": "Used as error message in [[Special:Block]].\n\nSee also:\n* {{msg-mw|Range block disabled}}\n* {{msg-mw|Ip range invalid}}\n* {{msg-mw|Ip range toolarge}}",
        "ip_range_toolarge": "Used as error message in [[Special:Block]]. Parameters:\n* $1 - a number from 0 to 32 for IPv4 (from 0 to 128 for IPv6); a part of CIDR (Classless Inter-Domain Routing) notation.\nSee also:\n* {{msg-mw|Range block disabled}}\n* {{msg-mw|Ip range invalid}}\n* {{msg-mw|Ip range toolarge}}",
        "proxyblocker": "Used in [[Special:BlockMe]].\n\nSee also:\n* {{msg-mw|proxyblocker-disabled}}\n* {{msg-mw|proxyblockreason}}\n* {{msg-mw|proxyblocksuccess}}",
        "import-logentry-interwiki": "{{ignored}}This is a ''logentry'' message only used on IRC. Parameters:\n* $1 - page title",
        "import-logentry-interwiki-detail": "Used as success message and log entry. Parameters:\n* $1 - number of succeeded revisions\n* $2 - interwiki name\nSee also:\n* {{msg-mw|Import-logentry-upload-detail}}",
        "javascripttest": "Title of the special page [[Special:JavaScriptTest]].\n\nSee also:\n* {{msg-mw|Javascripttest|title}}\n* {{msg-mw|Javascripttest-pagetext-noframework|summary}}\n* {{msg-mw|Javascripttest-pagetext-unknownframework|error message}}",
-       "javascripttest-backlink": "{{optional}}\nUsed as subtitle in [[Special:JavaScriptTest]]. Parameters:\n* $1 - page title",
-       "javascripttest-title": "{{Ignore}}",
-       "javascripttest-pagetext-noframework": "Used as summary when no framework specified.\n\nSee also:\n* {{msg-mw|Javascripttest|title}}\n* {{msg-mw|Javascripttest-pagetext-noframework|summary}}\n* {{msg-mw|Javascripttest-pagetext-unknownframework|error message}}",
-       "javascripttest-pagetext-unknownframework": "Error message when given framework ID is not found. Parameters:\n* $1 - the ID of the framework\nSee also:\n* {{msg-mw|Javascripttest|title}}\n* {{msg-mw|Javascripttest-pagetext-noframework|summary}}\n* {{msg-mw|Javascripttest-pagetext-unknownframework|error message}}",
        "javascripttest-pagetext-unknownaction": "Error message when url specifies an unknown action. Parameters:\n* $1 - the action specified in the url.",
-       "javascripttest-pagetext-frameworks": "Parameters:\n* $1 - frameworks list which contain a link text {{msg-mw|Javascripttest-qunit-name}}",
-       "javascripttest-pagetext-skins": "Used as label in [[Special:JavaScriptTest]].",
-       "javascripttest-qunit-name": "{{Ignore}}",
        "javascripttest-qunit-intro": "Used as summary. Parameters:\n* $1 - the configured URL to the documentation\nSee also:\n* {{msg-mw|Javascripttest-qunit-heading}}",
        "accesskey-pt-userpage": "{{doc-accesskey}}\nSee also:\n<!--* username-->\n* {{msg-mw|Accesskey-pt-userpage}}\n* {{msg-mw|Tooltip-pt-userpage}}",
        "accesskey-pt-anonuserpage": "{{doc-accesskey}}",
        "version-libraries-description": "Column header for the library's description\n{{Identical|Description}}",
        "version-libraries-authors": "Column header for the library's authors\n{{Identical|Author}}",
        "redirect": "{{doc-special|Redirect}}\nThis means \"Redirect by file '''name''', user '''ID''', page '''ID''', revision '''ID''', or log '''ID'''\".",
-       "redirect-legend": "Legend of fieldset around input box in [[Special:Redirect]]",
        "redirect-text": "Inside fieldset for [[Special:Redirect]]",
        "redirect-summary": "Shown at top of [[Special:Redirect]]",
        "redirect-submit": "Button label in [[Special:Redirect]].\n{{Identical|Go}}",
        "redirect-not-exists": "Used as error message in [[Special:Redirect]]",
        "fileduplicatesearch": "Name of special page [[Special:FileDuplicateSearch]].",
        "fileduplicatesearch-summary": "Summary of [[Special:FileDuplicateSearch]]",
-       "fileduplicatesearch-legend": "Legend of the fieldset around the input form of [[Special:FileDuplicateSearch]]",
        "fileduplicatesearch-filename": "Input form of [[Special:FileDuplicateSearch]]:\n\n{{Identical|Filename}}",
        "fileduplicatesearch-submit": "Button label on [[Special:FileDuplicateSearch]].\n\n{{Identical|Search}}",
        "fileduplicatesearch-info": "Information beneath the thumbnail on the right side shown after a successful search via [[Special:FileDuplicateSearch]].\n\nParameters:\n* $1 - width of the file\n* $2 - height of the file\n* $3 - File size\n* $4 - MIME type",
        "logentry-protect-protect-cascade": "{{Logentry|[[Special:Log/protect]]}}\n\n* $4 - protect expiry (formatted with {{msg-mw|protect-summary-desc}}, multiple possible)\nFor word \"cascading\" see {{msg-mw|protect-summary-cascade}}",
        "logentry-protect-modify": "{{Logentry|[[Special:Log/protect]]}}\n\n* $4 - protect expiry (formatted with {{msg-mw|protect-summary-desc}}, multiple possible)",
        "logentry-protect-modify-cascade": "{{Logentry|[[Special:Log/protect]]}}\n\n* $4 - protect expiry (formatted with {{msg-mw|protect-summary-desc}}, multiple possible)\nFor word \"cascading\" see {{msg-mw|protect-summary-cascade}}",
-       "logentry-rights-rights": "* $1 - username\n* $2 - (see below)\n* $3 - username\n* $4 - list of user groups or {{msg-mw|Rightsnone}}\n* $5 - list of user groups or {{msg-mw|Rightsnone}}\n----\n{{Logentry|[[Special:Log/rights]]}}",
+       "logentry-rights-rights": "* $1 - username\n* $2 - (see below)\n* $3 - username, also used for GENDER support\n* $4 - list of user groups or {{msg-mw|Rightsnone}}\n* $5 - list of user groups or {{msg-mw|Rightsnone}}\n----\n{{Logentry|[[Special:Log/rights]]}}",
        "logentry-rights-rights-legacy": "* $1 - username\n* $2 - (see below)\n* $3 - username\n----\n{{Logentry|[[Special:Log/rights]]}}",
        "logentry-rights-autopromote": "* $1 - username\n* $2 - (see below)\n* $3 - (see below)\n* $4 - comma separated list of old user groups or {{msg-mw|Rightsnone}}\n* $5 - comma separated list of new user groups\n----\n{{Logentry|[[Special:Log/rights]]}}",
        "logentry-upload-upload": "{{Logentry|[[Special:Log/upload]]}}",
        "api-error-unknownerror": "API error message that can be used for client side localisation of API errors.\n\nParameters:\n* $1 - an unknown error message\n{{Identical|Unknown error}}",
        "api-error-uploaddisabled": "API error message that can be used for client side localisation of API errors.",
        "api-error-verification-error": "The word \"extension\" refers to the part behind the last dot in a file name, that by convention gives a hint about the kind of data format which a files contents are in.",
+       "api-error-was-deleted": "API error message that can be used for client side localisation of API errors.",
        "duration-seconds": "Used as duration. Parameters:\n* $1 - number of seconds\n{{Related|Duration}}\n{{Identical|Second}}",
        "duration-minutes": "Used as duration. Parameters:\n* $1 - number of minutes\n{{Related|Duration}}\n{{Identical|Minute}}",
        "duration-hours": "Used as duration. Parameters:\n* $1 - number of hours\n{{Related|Duration}}",
        "special-characters-group-ipa": "IPA means a script: \"international phonetic alphabet\" here, and not \"international phonetic association\", the organization behind it.",
        "special-characters-group-symbols": "The section name for symbols\n\n{{Identical|Symbol}}",
        "special-characters-group-greek": "This is the name of a script, or alphabet, not a language.",
+       "special-characters-group-greekextended": "The name of the Greek Extended character set.",
        "special-characters-group-cyrillic": "This is the name of a script, or a group of alphabets, used mainly in Eastern Europe and North and Central Asia.\n{{related|Special-characters-group}}",
        "special-characters-group-arabic": "This is the name of a script, or alphabet, not a language.\n{{related|Special-characters-group}}",
        "special-characters-group-arabicextended": "This is a description of the additional group of Arabic script characters for languages such as a Persian, Urdu, Pashto and others. This message is supposed to be similar to {{msg-mw|special-characters-group-latinextended}}.\n{{related|Special-characters-group}}",
        "sessionprovider-generic": "Used to create a generic session type description when one isn't provided via the proper message. Should be phrased to make sense when added to a message such as {{msg-mw|cannotloginnow-text}}.\n\nParameters:\n* $1 - PHP classname.",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "Description of the sessions provided by the CookieSessionProvider class, which use HTTP cookies. Should be phrased to make sense when added to a message such as {{msg-mw|cannotloginnow-text}}.",
        "sessionprovider-nocookies": "Used to inform the user that sessions may be missing due to lack of cookies.",
-       "randomrootpage": "{{doc-special|RandomRootPage}}"
+       "randomrootpage": "{{doc-special|RandomRootPage}}",
+       "log-action-filter-block": "Which type of action to filter for in this log",
+       "log-action-filter-contentmodel": "Which type of action to filter for in this log",
+       "log-action-filter-delete": "Which type of action to filter for in this log",
+       "log-action-filter-import": "Which type of action to filter for in this log",
+       "log-action-filter-managetags": "Which type of action to filter for in this log",
+       "log-action-filter-move": "Which type of action to filter for in this log",
+       "log-action-filter-newusers": "Which type of action to filter for in this log",
+       "log-action-filter-patrol": "Which type of action to filter for in this log",
+       "log-action-filter-protect": "Which type of action to filter for in this log",
+       "log-action-filter-rights": "Which type of action to filter for in this log",
+       "log-action-filter-suppress": "Which type of action to filter for in this log",
+       "log-action-filter-upload": "Which type of action to filter for in this log",
+       "log-action-filter-all": "All types of action are allowed\n{{Identical|All}}",
+       "log-action-filter-block-block": "Action to filter for in this log\n{{Identical|Block}}",
+       "log-action-filter-block-reblock": "Action to filter for in this log",
+       "log-action-filter-block-unblock": "Action to filter for in this log\n{{Identical|Unblock}}",
+       "log-action-filter-contentmodel-change": "Action to filter for in this log",
+       "log-action-filter-contentmodel-new": "Action to filter for in this log",
+       "log-action-filter-delete-delete": "Action to filter for in this log",
+       "log-action-filter-delete-restore": "Action to filter for in this log",
+       "log-action-filter-delete-event": "Action to filter for in this log",
+       "log-action-filter-delete-revision": "Action to filter for in this log",
+       "log-action-filter-import-interwiki": "Action to filter for in this log",
+       "log-action-filter-import-upload": "Action to filter for in this log",
+       "log-action-filter-managetags-create": "Action to filter for in this log",
+       "log-action-filter-managetags-delete": "Action to filter for in this log",
+       "log-action-filter-managetags-activate": "Action to filter for in this log",
+       "log-action-filter-managetags-deactivate": "Action to filter for in this log",
+       "log-action-filter-move-move": "Action to filter for in this log",
+       "log-action-filter-move-move_redir": "Action to filter for in this log",
+       "log-action-filter-newusers-create": "Action to filter for in this log",
+       "log-action-filter-newusers-create2": "Action to filter for in this log",
+       "log-action-filter-newusers-autocreate": "Action to filter for in this log",
+       "log-action-filter-newusers-byemail": "Action to filter for in this log",
+       "log-action-filter-patrol-patrol": "Action to filter for in this log",
+       "log-action-filter-patrol-autopatrol": "Action to filter for in this log",
+       "log-action-filter-protect-protect": "Action to filter for in this log",
+       "log-action-filter-protect-modify": "Action to filter for in this log",
+       "log-action-filter-protect-unprotect": "Action to filter for in this log",
+       "log-action-filter-protect-move_prot": "Action to filter for in this log",
+       "log-action-filter-rights-rights": "Action to filter for in this log",
+       "log-action-filter-rights-autopromote": "Action to filter for in this log",
+       "log-action-filter-suppress-event": "Action to filter for in this log",
+       "log-action-filter-suppress-revision": "Action to filter for in this log",
+       "log-action-filter-suppress-delete": "Action to filter for in this log",
+       "log-action-filter-suppress-block": "Action to filter for in this log",
+       "log-action-filter-suppress-reblock": "Action to filter for in this log",
+       "log-action-filter-upload-upload": "Action to filter for in this log",
+       "log-action-filter-upload-overwrite": "Action to filter for in this log"
 }
index c1137ba..19358ce 100644 (file)
@@ -28,7 +28,8 @@
                        "Macofe",
                        "ImGelu",
                        "Wintereu",
-                       "Rsocol"
+                       "Rsocol",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "Sublinierea legăturilor:",
        "nocookieslogin": "{{SITENAME}} folosește module cookie pentru a autentifica utilizatorii. Browser-ul dvs. are cookie-urile dezactivate. Vă rugăm să le activați și să incercați din nou.",
        "nocookiesfornew": "Contul de utilizator nu a fost creat, deoarece nu am putut confirma sursa.\nAsigurați-vă că aveți cookie-urile activate, reîncărcați pagina și încercați din nou.",
        "noname": "Numele de utilizator pe care l-ați introdus nu este valid.",
-       "loginsuccesstitle": "Autentificare reușită",
+       "loginsuccesstitle": "Autentificat(ă)",
        "loginsuccess": "'''Ați fost autentificat la {{SITENAME}} ca „$1”.'''",
        "nosuchuser": "Nu există nici un utilizator cu numele „$1”.\nNumele de utilizatori sunt sensibile la majuscule.\nVerifică dacă ai scris corect sau [[Special:UserLogin/signup|creează un nou cont de utilizator]].",
        "nosuchusershort": "Nu există niciun utilizator cu numele „$1”.\nVerificați ortografierea.",
        "createaccount-title": "Creare de cont la {{SITENAME}}",
        "createaccount-text": "Cineva a creat un cont asociat adresei dumneavoastră de e-mail pe {{SITENAME}} ($4) numit „$2” și având parola „$3”.\nEste de dorit să vă autentificați și să schimbați parola cât mai repede.\n\nIgnorați acest mesaj dacă crearea contului s-a produs în urma unei greșeli.",
        "login-throttled": "Ați avut prea multe încercări recente de a vă autentifica.\nVă rugăm să așteptați $1 până să reîncercați.",
-       "login-abort-generic": "Procesul de autentificare a eșuat și a fost abandonat",
+       "login-abort-generic": "Procesul de autentificare a eșuat - Abandonat",
        "login-migrated-generic": "Contul dumneavoastră a fost migrat, iar numele de utilizator nu mai există pe acest wiki.",
        "loginlanguagelabel": "Limba: $1",
        "suspicious-userlogout": "Cererea dumneavoastră de a închide sesiunea a fost refuzată întrucât pare că a fost trimisă printr-o eroare a navigatorului sau de un proxy memorat în cache.",
        "newpassword": "Parola nouă:",
        "retypenew": "Reintroduceți noua parolă:",
        "resetpass_submit": "Setează parola și autentifică",
-       "changepassword-success": "Parola dumneavoastră a fost schimbată cu succes!",
+       "changepassword-success": "Parola dumneavoastră a fost schimbată!",
        "changepassword-throttled": "Ați avut prea multe încercări recente de a vă autentifica.\nVă rugăm să așteptați $1 până să reîncercați.",
        "botpasswords": "Parole roboți",
        "botpasswords-summary": "<em>Parolele de roboți</em> permit accesul la un cont de utilizator prin intermediul API-ului fără utilizarea identificatorilor de conectare principali ai contului. Este posibil ca drepturile de utilizator disponibile după conectarea cu parole de roboți să fie restricționate.\n\nDacă nu știți exact de ce ați recurge la această metodă, probabil ar trebui să nu o faceți. Nimeni nu ar trebui să vă ceară vreodată să generați acest tip de parolă și să le-o furnizați.",
        "recentchangeslinked-page": "Numele paginii:",
        "recentchangeslinked-to": "Arată în schimb modificările asupra paginilor care se leagă de pagina indicată",
        "recentchanges-page-added-to-category": "[[:$1]] a fost adăugată în categorii",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] și încă {{PLURAL:$2|o pagină|$2 pagini|$2 de pagini}} au fost adăugate în categorii",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] și încă [[Special:WhatLinksHere/$1|{{PLURAL:$2|o pagină|$2 pagini|$2 de pagini}}]] au fost adăugate în categorii",
        "recentchanges-page-removed-from-category": "[[:$1]] eliminată din categorii",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] și încă {{PLURAL:$2|o pagină|$2 pagini|$2 de pagini}} au fost eliminate din categorii",
        "autochange-username": "Modificare automată a MediaWiki",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|versiune importată|versiuni importate|de versiuni importate}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versiune|versiuni|de versiuni}} importate de la $2",
        "javascripttest": "Testare JavaScript",
-       "javascripttest-pagetext-noframework": "Această pagină este rezervată rulării testelor JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Cadru de testare „$1” necunoscut.",
        "javascripttest-pagetext-unknownaction": "Acțiunea „$1” necunoscută.",
-       "javascripttest-pagetext-frameworks": "Alegeți unul din următoarele cadre de testare: $1",
-       "javascripttest-pagetext-skins": "Alegeți un aspect pentru care să rulați teste:",
        "javascripttest-qunit-intro": "A se vedea [$1 documentația de testare] pe mediawiki.org.",
        "tooltip-pt-userpage": "Pagina {{GENDER:|dumneavoastră}} de utilizator",
        "tooltip-pt-anonuserpage": "Pagina de utilizator pentru adresa IP curentă",
        "version-libraries-description": "Descriere",
        "version-libraries-authors": "Autori",
        "redirect": "Redirecționare după fișier, utilizator, ID-ul paginii, al versiunii sau al jurnalului",
-       "redirect-legend": "Redirecționare către un fișier sau o pagină",
        "redirect-summary": "Această pagină specială vă redirecționează către un fișier (dat fiind un nume de fișier), o pagină (dat fiind ID-ul unei versiuni sau ID-ul unei pagini) sau o pagină de utilizator (dat fiind un ID numeric al utilizatorului). Utilizare: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] sau [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Du-te",
        "redirect-lookup": "Căutare:",
index 75d7c49..4e92f87 100644 (file)
        "noemail": "Для участника с именем $1 электронный адрес указан не был.",
        "noemailcreate": "Вам необходимо указать корректный адрес электронной почты",
        "passwordsent": "Новый пароль был выслан на адрес электронной почты, указанный для участника $1.\n\nПожалуйста, представьтесь системе заново после получения пароля.",
-       "blocked-mailpassword": "Редактирование с вашего IP-адреса запрещено, поэтому заблокирована и функция восстановления пароля.",
+       "blocked-mailpassword": "Редактирование с вашего IP-адреса запрещено. Для предотвращения злоупотреблений для этого IP-адреса заблокирована и функция восстановления пароля.",
        "eauthentsent": "На указанный адрес электронной почты отправлено письмо. \nЧтобы получать письма в дальнейшем, следуйте изложенным там инструкциям для подтверждения, что этот адрес действительно принадлежит вам.",
        "throttled-mailpassword": "Функция напоминания пароля уже использовалась в течение {{PLURAL:$1|1=последнего часа|последних $1 часов}}.\nДля предотвращения злоупотреблений, разрешено запрашивать не более одного напоминания {{PLURAL:$1|за $1 час|за $1 часов|за $1 часа|1=в час}}.",
        "mailerror": "Ошибка при отправке почты: $1",
        "botpasswords-insert-failed": "Не удалось добавить бота с именем «$1». Возможно, он был уже добавлен?",
        "botpasswords-update-failed": "Не удалось обновить бота с именем «$1». Возможно, он был удалён?",
        "botpasswords-created-title": "Пароль бота создан",
-       "botpasswords-created-body": "Пароль бота «$1» был создан.",
+       "botpasswords-created-body": "Пароль бота для бота «$1» участника «$2» был создан.",
        "botpasswords-updated-title": "Пароль бота обновлён",
-       "botpasswords-updated-body": "Пароль бота «$1» был обновлён.",
+       "botpasswords-updated-body": "Пароль бота для бота «$1» участника «$2» был обновлён.",
        "botpasswords-deleted-title": "Пароль бота удалён",
-       "botpasswords-deleted-body": "Пароль бота «$1» был удалён.",
+       "botpasswords-deleted-body": "Пароль бота для бота «$1» участника «$2» был удалён.",
        "botpasswords-newpassword": "Новый пароль для входа под <strong>$1</strong> — <strong>$2</strong>. <em>Запишите его для последующего использования.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider недоступен.",
        "botpasswords-restriction-failed": "Из-за ограничений, связанных с паролем бота, вход не произведён.",
        "recentchanges-label-bot": "Эта правка сделана ботом",
        "recentchanges-label-unpatrolled": "Эта правка ещё никем не патрулировалась",
        "recentchanges-label-plusminus": "изменение размера в байтах",
-       "recentchanges-legend-heading": "<strong>Легенда:</strong>",
+       "recentchanges-legend-heading": "<strong>Легенда:&nbsp;</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (см. также [[Special:NewPages|список новых страниц]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Показать",
        "recentchangeslinked-page": "Название страницы:",
        "recentchangeslinked-to": "Наоборот, показать изменения на страницах, которые ссылаются на указанную страницу",
        "recentchanges-page-added-to-category": "[[:$1]] добавлена в категорию",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] и {{PLURAL:$2|одна страница|$2 страниц}} добавлены в категорию",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] и [[Special:WhatLinksHere/$1|$2 {{PLURAL:$2|страница|страниц|страницы}}]] добавлены в категорию",
        "recentchanges-page-removed-from-category": "[[:$1]] убрана из категории",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] и {{PLURAL:$2|одна страница|$2 страниц}} убраны из категории",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] и [[Special:WhatLinksHere/$1|$2 {{PLURAL:$2|страница|страниц|страницы}}]] удалены из категории",
        "autochange-username": "Автоматическое изменение MediaWiki",
        "upload": "Загрузить файл",
        "uploadbtn": "Загрузить файл",
        "uploadstash-badtoken": "Не удалось выполнить указанные действия. Возможно, истёк срок действия ваших учётных данных. Пожалуйста, пробуйте ещё раз.",
        "uploadstash-errclear": "Очистка файлов не удалась.",
        "uploadstash-refresh": "Обновить список файлов",
+       "uploadstash-thumbnail": "показать миниатюру",
        "invalid-chunk-offset": "Недопустимое смещение фрагмента",
        "img-auth-accessdenied": "Доступ запрещён",
        "img-auth-nopathinfo": "Отсутствует <code>PATH_INFO</code>.\nВаш сервер не настроен для передачи этих сведений.\nВозможно, он работает на основе CGI и не поддерживает <code>img_auth</code>.\nСм. https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "changecontentmodel-title-label": "Заголовок страницы",
        "changecontentmodel-model-label": "Новая модель содержимого",
        "changecontentmodel-reason-label": "Причина:",
+       "changecontentmodel-submit": "Изменить",
        "changecontentmodel-success-title": "Модель содержимого была изменена",
        "changecontentmodel-success-text": "Модель содержимого [[:$1]] была изменена.",
        "changecontentmodel-cannot-convert": "Содержимое [[:$1]] не может быть преобразовано к типу $2.",
        "ipb-unblock": "Разблокировать участника или IP-адрес",
        "ipb-blocklist": "Показать действующие блокировки",
        "ipb-blocklist-contribs": "Вклад {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "осталось $1",
        "unblockip": "Разблокировать участника",
        "unblockiptext": "Используйте форму ниже, чтобы восстановить возможность редактирования с ранее заблокированного IP-адреса или учётной записи.",
        "ipusubmit": "Снять эту блокировку",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|версия импортирована|версии импортировано|версий импортировано}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версия импортирована|версии импортировано|версий  импортировано}} из $2",
        "javascripttest": "Проверка JavaScript",
-       "javascripttest-pagetext-noframework": "Эта страница зарезервирована для запуска JavaScript-тестов.",
-       "javascripttest-pagetext-unknownframework": "Неизвестная среда тестирования «$1».",
        "javascripttest-pagetext-unknownaction": "Неизвестное действие «$1».",
-       "javascripttest-pagetext-frameworks": "Пожалуйста, выберите одну из следующих сред тестирования: $1",
-       "javascripttest-pagetext-skins": "Выберите тему оформления для запуска тестов:",
        "javascripttest-qunit-intro": "См. [$1 документацию по тестированию] на mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Ваша}} страница участника",
        "tooltip-pt-anonuserpage": "Страница участника для моего IP",
        "version-libraries-description": "Описание",
        "version-libraries-authors": "Авторы",
        "redirect": "Перенаправление с идентификатора файла, участника, страницы, версии или журнала",
-       "redirect-legend": "Перенаправление на файл или страницу",
        "redirect-summary": "Эта служебная страница перенаправляет на файл (с имени файла), страницу (с идентификатора версии или страницы), страницу участника (с числового идентификатора участника) или запись журнала (с идентификатора журнала). Использование: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]] или [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Перейти",
        "redirect-lookup": "Поиск:",
        "logentry-protect-protect-cascade": "$1 защитил{{GENDER:$2||а}} $3 $4 [каскадно]",
        "logentry-protect-modify": "$1 изменил{{GENDER:$2||а}} уровень защиты $3 $4",
        "logentry-protect-modify-cascade": "$1 изменил{{GENDER:$2||а}} уровень защиты $3 $4 [каскадно]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|изменил|изменила}} членство в группах для $3 с $4 на $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|изменил|изменила}} членство в группах для {{GENDER:$3|$3}} с $4 на $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|изменил|изменила}} членство в группах для $3",
        "logentry-rights-autopromote": "$1 был{{GENDER:$2||а}} автоматически переведен{{GENDER:$2||а}} из $4 в $5",
        "logentry-upload-upload": "$1 загрузил{{GENDER:$2||а}} $3",
        "api-error-unknownerror": "Неизвестная ошибка: «$1».",
        "api-error-uploaddisabled": "В этой вики отключена возможность загрузки файлов.",
        "api-error-verification-error": "Возможно, этот файл повреждён или имеет неправильное расширение.",
+       "api-error-was-deleted": "Файл с таким именем был уже ранее загружен и впоследствии удалён.",
        "duration-seconds": "$1 {{PLURAL:$1|секунда|секунды|секунд}}",
        "duration-minutes": "$1 {{PLURAL:$1|минута|минуты|минут}}",
        "duration-hours": "$1 {{PLURAL:$1|час|часа|часов}}",
        "special-characters-group-ipa": "МФА (IPA)",
        "special-characters-group-symbols": "Символы",
        "special-characters-group-greek": "Греческие",
+       "special-characters-group-greekextended": "Расширенный греческий",
        "special-characters-group-cyrillic": "Кириллица",
        "special-characters-group-arabic": "Арабские",
        "special-characters-group-arabicextended": "Арабские расширенные",
        "sessionprovider-generic": "$1 сессий",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "сессий на основе куки",
        "sessionprovider-nocookies": "Могут быть отключены куки. Убедитесь, что у вас включены куки и начните заново.",
-       "randomrootpage": "Случайная корневая страница"
+       "randomrootpage": "Случайная корневая страница",
+       "log-action-filter-block": "Тип блокировки:",
+       "log-action-filter-delete": "Тип удаления:",
+       "log-action-filter-patrol": "Тип патрулирования:",
+       "log-action-filter-protect": "Тип защиты:",
+       "log-action-filter-upload": "Тип загрузки:",
+       "log-action-filter-all": "Все",
+       "log-action-filter-block-block": "Блокировка",
+       "log-action-filter-block-reblock": "Изменение блокировки",
+       "log-action-filter-block-unblock": "Разблокировка",
+       "log-action-filter-delete-delete": "Удаления страницы",
+       "log-action-filter-delete-restore": "Восстановление страницы",
+       "log-action-filter-delete-event": "Удаление журнала",
+       "log-action-filter-delete-revision": "Удаление версии",
+       "log-action-filter-patrol-patrol": "Ручное патрулирование",
+       "log-action-filter-patrol-autopatrol": "Автоматическое патрулирование",
+       "log-action-filter-protect-protect": "Защита",
+       "log-action-filter-protect-modify": "Изменение защиты",
+       "log-action-filter-protect-unprotect": "Снятие защиты",
+       "log-action-filter-upload-upload": "Новая загрузка",
+       "log-action-filter-upload-overwrite": "Повторно загрузить"
 }
index e62d931..9eae5d1 100644 (file)
        "newarticle": "(नूतनम्)",
        "newarticletext": "भवान्/भवती अनिर्मिते पृष्ठे अस्ति । \nपृष्ठं स्रष्टुम् अधः प्रदत्तायां पेटिकायां टङ्कनं प्रारभताम् (साहाय्यार्थं [$1 अत्र]) नुदतु ।\nभवान्/भवती यदि क्षतिकारणात् एतत् पृष्ठं प्रति आगच्छत्, तर्हि अस्य गवेषकस्य (browser) Back नुदतु ।",
        "anontalkpagetext": "----\n<em>एतत् सम्भाषणपृष्ठम् अनामकसदस्येभ्यः अस्ति । एतत् तेभ्यः अनामकसदस्येभ्यः रचितमस्ति, यैः सदस्यता न प्राप्ता अस्ति तथा च अस्य पृष्ठस्य उपयोगं न कुर्वन्तः सन्ति ।</em>\nतेषां व्यक्तिगतसूचनां प्राप्तुमेव वयं तस्य/तस्याः अन्तर्जालसंविदः उपयोगं कुर्मः । केचन सदस्याः स्वस्य अन्तर्जालसंविदम् अन्यान् सदस्यान् कथयन्ति । \nयद्यपि अनामकसदस्यः अहं नास्मि, तथापि अयोग्यसूचनाः मम पार्श्वे आगच्छन्त्यः सन्ति इति यदि भवान्/भवती शङ्कते, तर्हि एतत् [[Special:UserLogin/signup|create an account]] एतत् [[Special:UserLogin|log in]] वा कृत्वा भविष्यस्य अनामकसदस्यानां सन्देशेभ्यः स्वस्य रक्षणं करोतु ।",
-       "noarticletext": "à¤\85सà¥\8dमिनà¥\8d à¤ªà¥\83षà¥\8dठà¥\87 à¤\85धà¥\81ना à¤\95िमपि à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87 à¥¤ [[Special:Search/{{PAGENAME}}|à¤\8fषà¤\83 à¤¶à¤¬à¥\8dदà¤\83]] à¤¯à¥\87षà¥\81 à¤ªà¥\83षà¥\8dठà¥\87षà¥\81 à¤\85नà¥\8dतरà¥\8dभवति, à¤¤à¤¾à¤¨à¤¿ à¤ªà¥\83षà¥\8dठानि à¤\85नà¥\8dवà¥\87षà¥\8dà¤\9fà¥\81à¤\82 à¤¶à¤\95à¥\8dयनà¥\8dतà¥\87 à¥¤ \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  à¤¸à¤®à¥\8dबदà¥\8dधà¥\87षà¥\81 à¤ªà¥\83षà¥\8dठà¥\87षà¥\81 à¤\85नà¥\8dवà¥\87षणà¤\82]\n[{{fullurl:{{FULLPAGENAME}}|action=edit}} à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤¸à¤®à¥\8dपादनं] वा  शक्यम्</span>.",
+       "noarticletext": "à¤\85सà¥\8dमिनà¥\8d à¤ªà¥\83षà¥\8dठà¥\87 à¤\85धà¥\81ना à¤\95िमपि à¤¨ à¤µà¤¿à¤¦à¥\8dयतà¥\87 à¥¤ [[Special:Search/{{PAGENAME}}|à¤\8fषà¤\83 à¤¶à¤¬à¥\8dदà¤\83]] à¤¯à¥\87षà¥\81 à¤ªà¥\83षà¥\8dठà¥\87षà¥\81 à¤\85नà¥\8dतरà¥\8dभवति, à¤¤à¤¾à¤¨à¤¿ à¤ªà¥\83षà¥\8dठानि à¤\85नà¥\8dवà¥\87षà¥\8dà¤\9fà¥\81à¤\82 à¤¶à¤\95à¥\8dयनà¥\8dतà¥\87 à¥¤ \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  à¤¸à¤®à¥\8dबदà¥\8dधà¥\87षà¥\81 à¤ªà¥\83षà¥\8dठà¥\87षà¥\81 à¤\85नà¥\8dवà¥\87षणà¤\82]\n[{{fullurl:{{FULLPAGENAME}}|action=edit}} à¤\85सà¥\8dय à¤ªà¥\83षà¥\8dठसà¥\8dय à¤¨à¤¿à¤°à¥\8dमाणं] वा  शक्यम्</span>.",
        "noarticletext-nopermission": "अस्मिन् पृष्ठे अधुना किमपि न विद्यते । [[Special:Search/{{PAGENAME}}|एषः शब्दः]] येषु पृष्ठेषु अन्तर्भवति, तानि पृष्ठानि अन्वेष्टुं शक्यन्ते । \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  सम्बद्धेषु पृष्ठेषु अन्वेषणं]\n[{{fullurl:{{FULLPAGENAME}}|action=edit}} अस्य पृष्ठस्य सम्पादनं] वा  शक्यम्</span>.",
        "missing-revision": "\"{{FULLPAGENAME}}\" पृष्ठस्य संस्करणं #$1 नोपलभ्यम् ।\nयस्य पृष्ठस्य इतिहासे परिसन्धयः कालातीताः सन्ति, तेषु पृष्ठेषु एवं भवति ।\nअधिकसूचनाः अत्र प्राप्तुं शक्यते [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} अपाकृतानाम् आवलिः].",
        "userpage-userdoesnotexist": "\"$1\" इति सदस्यनाम पञ्जीकृतं न विद्यते । अस्य\nनवरचनायै/सम्पादनाय तत् पश्यतु ।",
        "listfiles-delete": "अपाक्रियताम्",
        "listfiles-summary": "एतद्विशेषपुटम् उत्तारितसञ्चिकाः प्रदर्शयति । \nयोजकेन शुद्धाः अतिनूतनं सञ्चिकाः केवलम् अत्र प्रदर्शयति ।",
        "listfiles_search_for": "माध्यमनामधेयार्थम् अन्विषतु ।",
-       "listfiles-userdoesnotexist": "\"$1\" à¤\87तà¥\8dयषा à¤¸à¤¦à¤¸à¥\8dयलà¥\87à¤\96ा à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83तà¤\82 नास्ति ।",
+       "listfiles-userdoesnotexist": "\"$1\" à¤\87तà¥\8dयषा à¤¸à¤¦à¤¸à¥\8dयलà¥\87à¤\96ा à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83ता नास्ति ।",
        "imgfile": "संचिका",
        "listfiles": "सञ्चिकावली ।",
        "listfiles_thumb": "अंगुष्ठनखाकारम् ।",
        "mycontris": "योगदानानि",
        "anoncontribs": "अंशदाता",
        "contribsub2": "($2) कृते {{GENDER:$3|$1}}",
-       "contributions-userdoesnotexist": "\"$1\" à¤\87तà¥\8dयषा à¤¸à¤¦à¤¸à¥\8dयलà¥\87à¤\96ा à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83तà¤\82 नास्ति ।",
+       "contributions-userdoesnotexist": "\"$1\" à¤\87तà¥\8dयषा à¤¸à¤¦à¤¸à¥\8dयलà¥\87à¤\96ा à¤ªà¤\9eà¥\8dà¤\9cà¥\80à¤\95à¥\83ता नास्ति ।",
        "nocontribs": "एतादृशयोग्यताभिः समं परिवर्तनानि न दृष्टानि ।",
        "uctop": "वर्तमानः",
        "month": "अस्मात् मासात् (प्राक्तनानि च):",
        "javascripttest-pagetext-frameworks": "अधो दत्तेषु कञ्चिदेकां परीक्षाप्रक्रियां चिनोतु : $1",
        "javascripttest-pagetext-skins": "अनेन सह परीक्षां सञ्चालयितुं  काचित् त्वक् चिनोतु ।",
        "javascripttest-qunit-intro": "mediawiki.org. [$1 अभिलेखपरीक्षा] इत्यत्र पश्यतु ।",
-       "tooltip-pt-userpage": "भवतः/भवत्याः सदस्यपृष्ठम्",
+       "tooltip-pt-userpage": "{{GENDER:|भवतः/भवत्याः सदस्यपृष्ठम्}}",
        "tooltip-pt-anonuserpage": "ऐपिसङ्केतार्थं योजकपुटं भवान् सम्पादयति एवम्..",
-       "tooltip-pt-mytalk": "भवतः/भवत्याः सम्भाषणपृष्ठम्",
+       "tooltip-pt-mytalk": "{{GENDER:|भवतः/भवत्याः}} सम्भाषणपृष्ठम्",
        "tooltip-pt-anontalk": "एतस्मात् ऐपिसङ्केतात् सम्पादनस्य परिचर्चा ।",
-       "tooltip-pt-preferences": "भवतः/भवत्याः इष्टतमानि",
+       "tooltip-pt-preferences": "{{GENDER:|भवतः/भवत्याः}} इष्टतमानि",
        "tooltip-pt-watchlist": "भवतः/भवत्याः निरीक्षासूच्यां विद्यमानानां पृष्ठानाम् आवलिः",
-       "tooltip-pt-mycontris": "भवतः/भवत्याः योगदानानाम् आवलिः",
+       "tooltip-pt-mycontris": "{{GENDER:|भवतः/भवत्याः}} योगदानानाम् आवलिः",
        "tooltip-pt-login": "प्रवेशाय प्रोत्सहामहे । परन्तु प्रवेशः ऐच्छिकः ।",
        "tooltip-pt-logout": "निर्गम्यताम्",
        "tooltip-pt-createaccount": "नूतनसदस्यतां प्राप्य प्रविश्यताम् इति सूच्यते किन्तु न एतद् अनिवार्यम्",
        "tooltip-t-recentchangeslinked": "एतत्पृष्ठसम्बद्धेषु पृष्ठेषु जातानि नवीनपरिवर्तनानि",
        "tooltip-feed-rss": "अस्मै पृष्ठाय आर-एस-एस-पूरणम्",
        "tooltip-feed-atom": "अस्मै पृष्ठाय अणुपूरणम्",
-       "tooltip-t-contributions": "अनेन सदस्येन कृतानां योगदानानाम् आवलिः",
+       "tooltip-t-contributions": "{{GENDER:$1|अनेन सदस्येन}} कृतानां योगदानानाम् आवलिः",
        "tooltip-t-emailuser": "एतस्मै योजकाय वि-पत्रं प्रेष्यताम्",
        "tooltip-t-info": "एतस्य पृष्ठस्य विषये अधिकं विवरणम्",
        "tooltip-t-upload": "सञ्चिकाः उपारोप्यन्ताम्",
index ffbdea6..0e2e3f2 100644 (file)
        "recentchangeslinked-page": "Сирэй аата:",
        "recentchangeslinked-to": "Төттөрүтүн, ыйыллыбыт сирэйгэ сигэнэр сирэйдэри көрдөр",
        "recentchanges-page-added-to-category": "[[:$1]] категорияҕа эбилиннэ",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] уонна {{PLURAL:$2|биир сирэй|$2 сирэй}} категорияҕа эбилиннэ",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] уонна [[Special:WhatLinksHere/$1|{{PLURAL:$2|биир сирэй|$2 сирэй}}]] категорияҕа эбилиннэ",
        "recentchanges-page-removed-from-category": "[[:$1]] категорияттан сотулунна",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] уонна {{PLURAL:$2|биир сирэй|$2 сирэй}} категорияттан сотулунна",
        "autochange-username": "MediaWiki аптамаатынан уларыйыыта",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|барыл угулунна|барылы уктубут}}",
        "import-logentry-interwiki-detail": "Барыта $2 барылтан $1 барыл угулунна",
        "javascripttest": "JavaScript тургутуу",
-       "javascripttest-pagetext-noframework": "Бу сирэй JavaScript тургутууларга анаммыт.",
-       "javascripttest-pagetext-unknownframework": "\"$1\" тургутуу биллибэт эйгэтэ.",
        "javascripttest-pagetext-unknownaction": "Биллибэт дьайыы «$1».",
-       "javascripttest-pagetext-frameworks": "Бука диэн, бу тургуутуу эйгэлэриттэн биирин тал: $1",
-       "javascripttest-pagetext-skins": "Тургутууну ыытарга тас көрүҥүн бастаан тал:",
        "javascripttest-qunit-intro": "[$1 тургутуу документациятын] манна mediawiki.org көр.",
        "tooltip-pt-userpage": "{{GENDER:|Кыттааччы}} быһыытынан тус сириҥ",
        "tooltip-pt-anonuserpage": "Билигин киирбит IP-м сирэйэ",
        "version-libraries-description": "Ойуулааһын",
        "version-libraries-authors": "Ааптар",
        "redirect": "Билэттэн, кыттааччыттан, сирэйтэн эбэтэр барыл идентификаторыттан утаарыы",
-       "redirect-legend": "Билэҕэ эбэтэр сирэйгэ утаарыы",
        "redirect-summary": "Бу аналлаах сирэй билэҕэ (билэ аатыттан), сирэйгэ (барыл эбэтэр сирэй идентификааторыттан) эбэтэр кыттааччы сирэйигэр (кыттааччы идентификаторыттан) утаарар. Туһаныы: \n[[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], \n[[{{#Special:Redirect}}/revision/328429]] эбэтэр\n[[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Толор",
        "redirect-lookup": "Көрдөт:",
index 754df97..17ef183 100644 (file)
        "recentchangeslinked-page": "Naslov stranice:",
        "recentchangeslinked-to": "Pokaži promjene stranica koji su povezane sa datom stranicom",
        "recentchanges-page-added-to-category": "[[:$1]] pridodano kategoriji",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] i {{PLURAL:$2|stranica|$2 stranica}} {{PLURAL:$2|pridodana|pridodane}} kategoriji",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] i [[Special:WhatLinksHere/$1|{{PLURAL:$2|stranica|$2 stranica}} {{PLURAL:$2|pridodana|pridodane}}]] kategoriji",
        "recentchanges-page-removed-from-category": "[[:$1]] uklonjeno iz kategorije",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] i {{PLURAL:$2|stranica|$2 stranica}} {{PLURAL:$2|uklonjena|uklonjenne}} iz kategorije",
        "autochange-username": "MediaWiki automatska promjena",
index 0034434..01ff533 100644 (file)
        "accmailtitle": "Heslo bolo odoslané.",
        "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.\nStránku vytvoríte tak, že začnete písať do dolného poľa a potom stlačíte tlačidlo „Uložiť stránku“.\n(Viac informácií nájdete na stránkach [$1 Pomocníka]).\nAk ste sa sem dostali nechtiac, iba kliknite na tlačidlo '''späť''' vo svojom prehliadači.",
+       "newarticletext": "Sledovali ste odkaz na stránku, ktorá zatiaľ neexistuje.\nStránku vytvoríte tak, že začnete písať do poľa nižšie (viac informácií nájdete na stránkach [$1 nápovedy]).\nAk ste sa sem dostali nechtiac, kliknite na tlačidlo <strong>späť</strong> vo svojom prehliadači.",
        "anontalkpagetext": "----''Toto je diskusná stránka anonymného používateľa, ktorý nemá vytvorené svoje konto alebo ho nepoužíva.\nPreto musíme na jeho identifikáciu použiť numerickú IP adresu. Je možné, že takúto IP adresu používajú viacerí používatelia.\nAk 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.\nMôžete [[Special:Search/{{PAGENAME}}|vyhľadávať názov tejto stránky]] v obsahu iných stránok,\n<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": "Na tejto stránke sa momentálne nenachádza žiadny text.\nMôžete [[Special:Search/{{PAGENAME}}|vyhľadávať názov tejto stránky]] v obsahu iných stránok,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} vyhľadávať v súvisiacich záznamoch] alebo [{{fullurl:{{FULLPAGENAME}}|action=edit}} vytvoriť túto stránku]</span>.",
        "noarticletext-nopermission": "Táto stránka momentálne neobsahuje žiadny text.\nMôžete [[Special:Search/{{PAGENAME}}|hľadať názov tejto stránky]] v texte iných stránok\nalebo <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ť.",
        "missing-revision": "Revízia #$1 stránky s názvom „{{FULLPAGENAME}}“ neexistuje.\n\nPravdepodobne ste nasledovali zastaraný odkaz na historickú verziu stránky, ktorá bola medzičasom odstránená.\nPodrobnosti nájdete v [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} zázname zmazaní].",
        "userpage-userdoesnotexist": "Používateľský účet „<nowiki>$1</nowiki>“ nie je registrovaný. Prosím, skontrolujte, či naozaj chcete vytvoriť/upravovať túto stránku.",
        "recentchangeslinked-page": "Názov stránky:",
        "recentchangeslinked-to": "Zobraziť zmeny na stránkach, ''ktoré odkazujú na'' zadanú stránku",
        "recentchanges-page-added-to-category": "[[:$1]] zaradená do kategórie",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] a {{PLURAL:$2|jedna ďalšia zaradené|$2 ďalšie zaradené|$2 ďalších zaradených}} do kategórie",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] a [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedna ďalšia zaradené|$2 ďalšie zaradené|$2 ďalších zaradených}}]] do kategórie",
        "recentchanges-page-removed-from-category": "[[:$1]] vyradená z kategórie",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] a {{PLURAL:$2|jedna ďalšia vyradené|$2 ďalšie vyradené|$2 ďalších vyradených}} z kategórie",
        "autochange-username": "Automatická úprava MediaWiki",
        "log-edit-tags": "Editovať značky zvolených položiek záznamu",
        "checkbox-select": "Zvoliť: $1",
        "checkbox-all": "Všetky",
-       "checkbox-none": "Ždiadne",
+       "checkbox-none": "Žiadne",
        "checkbox-invert": "Invertovať",
        "allpages": "Všetky stránky",
        "nextpage": "Ďalšia stránka ($1)",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|revízia|revízie|revízií}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revízia|revízie|revízií}} z $2",
        "javascripttest": "Testovanie JavaScriptu",
-       "javascripttest-pagetext-noframework": "Táto stránka je vyhradená pre testy JavaScriptu.",
-       "javascripttest-pagetext-unknownframework": "Neznáma testovacia platfoma „$1“.",
        "javascripttest-pagetext-unknownaction": "Neznáma akcia: „$1“.",
-       "javascripttest-pagetext-frameworks": "Prosím vyberte jednu z nasledovných testovacích platforiem: $1",
-       "javascripttest-pagetext-skins": "Vyberte tému vzhľadu, na ktorej chcete spustiť testy:",
        "javascripttest-qunit-intro": "Pozri [$1 dokumentácia testovania] na mediawiki.org.",
        "tooltip-pt-userpage": "Vaša používateľská stránka",
        "tooltip-pt-anonuserpage": "Používateľská stránka pre ip adresu, ktorú upravujete ako",
        "version-libraries-description": "Popis",
        "version-libraries-authors": "Autori",
        "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 ID stránky alebo revízie) alebo používateľa (podľa číselného ID). Použitie: [[{{#Special:Redirect}}/file/Test.jpg]], [[{{#Special:Redirect}}/revision/328429]], resp. [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Ísť",
        "redirect-lookup": "Vyhľadať:",
index 7e7ebe7..b5febf8 100644 (file)
        "noemail": "Elektronska pošta uporabnika »$1« ni zapisana.",
        "noemailcreate": "Vnesti morate veljaven e-poštni naslov",
        "passwordsent": "Na naslov elektronske pošte, vpisanega za »$1«, smo poslali novo geslo.\nKo ga boste prejeli, se ponovno prijavite.",
-       "blocked-mailpassword": "Urejanje z vašega IP-naslova je blokirano. Da bi preprečili zlorabe, vam ni dovoljeno tudi uporabljati funkcije za povrnitev pozabljenega gesla.",
+       "blocked-mailpassword": "Urejanje z vašega IP-naslova je blokirano. Da bi preprečili zlorabe, vam s tega IP-naslova ni dovoljeno uporabljati funkcije za obnovitev pozabljenega gesla.",
        "eauthentsent": "E-sporočilo je bilo poslano na navedeni e-naslov.\nČe želite tja poslati še katero, sledite navodilom v e-sporočilu, da potrdite lastništvo računa.",
        "throttled-mailpassword": "E-pošto za ponastavitev gesla smo v {{PLURAL:$1|zadnji uri|zadnjih $1 urah}} že poslali.\nZa preprečevanje zlorab lahko na {{PLURAL:$1|uro|$1 uri|$1 ure|$1 ur}} pošljemo samo eno sporočilo za ponastavitev gesla.",
        "mailerror": "Napaka pri pošiljanju pošte: $1",
        "botpasswords-insert-failed": "Dodajanje imena bota »$1« ni uspelo. Ste ga že dodali?",
        "botpasswords-update-failed": "Posodobitev imena bota »$1« je spodletelo. Ste ga izbrisali?",
        "botpasswords-created-title": "Ustvarili smo geslo bota",
-       "botpasswords-created-body": "Ustvarili smo geslo bota »$1«.",
+       "botpasswords-created-body": "Ustvarili smo geslo bota »$1« uporabnika »$2«.",
        "botpasswords-updated-title": "Posodobili smo geslo bota",
-       "botpasswords-updated-body": "Posodobili smo geslo bota »$1«.",
+       "botpasswords-updated-body": "Posodobili smo geslo bota »$1« uporabnika »$2«.",
        "botpasswords-deleted-title": "Izbrisali smo geslo bota",
-       "botpasswords-deleted-body": "Uspešno smo izbrisali geslo bota »$1«.",
+       "botpasswords-deleted-body": "Izbrisali smo geslo bota »$1« uporabnika »$2«.",
        "botpasswords-newpassword": "Novo geslo za prijavo z imenom <strong>$1</strong> je <strong>$2</strong>. <em>Prosimo, zabeležite si to za uporabo v prihodnje.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider ni na voljo.",
        "botpasswords-restriction-failed": "Omejitve gesla bota preprečujejo to prijavo.",
        "recentchangeslinked-page": "Naslov strani:",
        "recentchangeslinked-to": "Prikaži spremembe na določeno stran povezanih strani",
        "recentchanges-page-added-to-category": "[[:$1]] dodano v kategorijo",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] in $2 {{PLURAL:$2|stran dodana|strani dodani|strani dodane|strani dodanih}} v kategorijo",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] in [[Special:WhatLinksHere/$1|$2 {{PLURAL:$2|stran|strani}}]] {{PLURAL:$2|dodana|dodani|dodane|dodanih}} v kategorijo",
        "recentchanges-page-removed-from-category": "[[:$1]] odstranjeno iz kategorije",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] in $2 {{PLURAL:$2|stran odstranjena|strani odstranjeni|strani odstranjene|strani odstranjenih}} iz kategorije",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] in [[Special:WhatLinksHere/$1|$2 {{PLURAL:$2|stran|strani}}]] {{PLURAL:$2|odstranjena|odstranjeni|odstranjene|odstranjenih}} iz kategorije",
        "autochange-username": "Samodejna sprememba MediaWiki",
        "upload": "Naloži datoteko",
        "uploadbtn": "Naloži datoteko",
        "uploadstash-badtoken": "Izvedba dejanja je spodletela. Morda zaradi izteklih poverilnic za urejanje. Prosimo, poskusite znova.",
        "uploadstash-errclear": "Čiščenje datotek je spodletelo.",
        "uploadstash-refresh": "Osveži seznam datotek",
+       "uploadstash-thumbnail": "ogled sličice",
        "invalid-chunk-offset": "Neveljaven odmik delčka",
        "img-auth-accessdenied": "Dostop zavrnjen",
        "img-auth-nopathinfo": "Manjka PATH_INFO.\nVaš strežnik ne poda te informacije.\nMorda temelji na CGI in ne more podpirati img_auth.\nOglejte si  https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "changecontentmodel-title-label": "Naslov strani",
        "changecontentmodel-model-label": "Novi model vsebine",
        "changecontentmodel-reason-label": "Razlog:",
+       "changecontentmodel-submit": "Spremeni",
        "changecontentmodel-success-title": "Spremenili smo model vsebine",
        "changecontentmodel-success-text": "Spremenili smo vrsto vsebine [[:$1]].",
        "changecontentmodel-cannot-convert": "Vsebine na [[:$1]] ni mogoče pretvoriti v vrsto $2.",
        "ipb-unblock": "Odblokirajte uporabniško ime ali IP-naslov",
        "ipb-blocklist": "Ogled obstoječih blokad",
        "ipb-blocklist-contribs": "Prispevki za {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "še $1",
        "unblockip": "Deblokirajte uporabnika",
        "unblockiptext": "Z naslednjim obrazcem obnovite možnost urejanja z blokiranega IP-naslova ali uporabniškega računa.",
        "ipusubmit": "Odstrani blokado",
        "import-logentry-upload-detail": "{{PLURAL:$1|Uvožena $1 redakcija|Uvoženi $1 redakciji|Uvožene $1 redakcije|Uvoženih $1 redakcij}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|Uvožena $1 redakcija|Uvoženi $1 redakciji|Uvožene $1 redakcije|Uvoženih $1 redakcij}} z $2",
        "javascripttest": "Preizkušanje JavaScripta",
-       "javascripttest-pagetext-noframework": "Stran je rezervirana za poganjanje preizkusov JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Neznano ogrodje za preizkušanje »$1«.",
        "javascripttest-pagetext-unknownaction": "Neznano dejanje »$1«.",
-       "javascripttest-pagetext-frameworks": "Prosimo, izberite enega od naslednjih ogrodjev za preizkušanje: $1",
-       "javascripttest-pagetext-skins": "Izberite kožo, v kateri želite pognati preizkuse:",
        "javascripttest-qunit-intro": "Oglejte si [$1 dokumentacijo o preizkušanju] na mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Vaša}} uporabniška stran",
        "tooltip-pt-anonuserpage": "Uporabniška stran IP-naslova, ki ga uporabljate",
        "exif-orientation-8": "Zasukano za 90° v desno",
        "exif-planarconfiguration-1": "grudast format",
        "exif-planarconfiguration-2": "ravninski format",
-       "exif-xyresolution-i": "$1 dpi ({{PLURAL:$1|točka/palec|točki/palec|točke/palec|točk/palec|točk/palec}})",
-       "exif-xyresolution-c": "$1 dpc ({{PLURAL:$1|točka/centimeter|točki/centimeter|točke/centimeter|točk/centimeter|točk/centimeter}})",
+       "exif-xyresolution-i": "$1 dpi ({{PLURAL:$1|točka/palec|točki/palec|točke/palec|točk/palec}})",
+       "exif-xyresolution-c": "$1 dpc ({{PLURAL:$1|točka/centimeter|točki/centimeter|točke/centimeter|točk/centimeter}})",
        "exif-colorspace-65535": "Neumerjeno",
        "exif-componentsconfiguration-0": "ne obstaja",
        "exif-exposureprogram-0": "Ni določen",
        "version-libraries-description": "Opis",
        "version-libraries-authors": "Avtorji",
        "redirect": "Preusmeri po datoteki ali ID-ju uporabnika, strani, redakcije ali dnevnika",
-       "redirect-legend": "Preusmeritev na datoteko ali stran",
        "redirect-summary": "Posebna stran preusmeri na datoteko (če podate ime datoteke), stran (če podate ID redakcije ali ID strani), uporabniško stran (če podate številski ID uporabnika) ali dnevniški vnos (če podate ID dnevnika). Uporaba: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]][[{{#Special:Redirect}}/user/101]] ali [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Pojdi",
        "redirect-lookup": "Iskanje:",
        "logentry-protect-protect-cascade": "$1 je {{GENDER:$2|zaščitil|zaščitila|zaščitil(-a)}} $3 $4 [kaskadno]",
        "logentry-protect-modify": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} stopnjo zaščite $3 $4",
        "logentry-protect-modify-cascade": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} stopnjo zaščite $3 $4 [kaskadno]",
-       "logentry-rights-rights": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} uporabniške pravice uporabnika $3 z $4 na $5",
+       "logentry-rights-rights": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} uporabniške pravice {{GENDER:$3|uporabnika|uporabnice}} $3 z $4 na $5",
        "logentry-rights-rights-legacy": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} uporabniške pravice uporabnika $3",
        "logentry-rights-autopromote": "$1 je {{GENDER:$2|bil samodejno povišan|bila samodejno povišana|bil(-a) samodejno povišan(-a)}} z $4 na $5",
        "logentry-upload-upload": "$1 je {{GENDER:$2|naložil|naložila|naložil(-a)}} $3",
        "api-error-unknownerror": "Neznana napaka: »$1«.",
        "api-error-uploaddisabled": "Nalaganje je onemogočeno na tem wikiju.",
        "api-error-verification-error": "Ta datoteka je morda poškodovana ali ima napačno končnico.",
+       "api-error-was-deleted": "Datoteko s tem imenom je v preteklosti nekdo že naložil, ampak je bila nato izbrisana.",
        "duration-seconds": "$1 {{PLURAL:$1|sekunda|sekundi|sekunde|sekund}}",
        "duration-minutes": "$1 {{PLURAL:$1|minuta|minuti|minute|minut}}",
        "duration-hours": "$1 {{PLURAL:$1|ura|uri|ure|ur}}",
        "special-characters-group-ipa": "Mednarodna fonetična abeceda (IPA)",
        "special-characters-group-symbols": "Simboli",
        "special-characters-group-greek": "Grški",
+       "special-characters-group-greekextended": "Grščina, razširjeno",
        "special-characters-group-cyrillic": "Cirilica",
        "special-characters-group-arabic": "Arabski",
        "special-characters-group-arabicextended": "Razširjena arabščina",
        "sessionprovider-generic": "sej $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sej, ki temeljijo na piškotkih",
        "sessionprovider-nocookies": "Piškotki so morda onemogočeni. Prepričaje se, da imate piškotke omogočene, in začnite znova.",
-       "randomrootpage": "Naključna korenska stran"
+       "randomrootpage": "Naključna korenska stran",
+       "log-action-filter-block": "Vrsta blokade:",
+       "log-action-filter-delete": "Vrsta izbrisa:",
+       "log-action-filter-patrol": "Vrsta nadzora:",
+       "log-action-filter-protect": "Vrsta zaščite:",
+       "log-action-filter-upload": "Vrsta nalaganja:",
+       "log-action-filter-all": "Vse",
+       "log-action-filter-block-block": "Blokada",
+       "log-action-filter-block-reblock": "Sprememba blokade",
+       "log-action-filter-block-unblock": "Odstranitev blokade",
+       "log-action-filter-delete-delete": "Izbris strani",
+       "log-action-filter-delete-restore": "Obnovitev strani",
+       "log-action-filter-delete-event": "Dnevnik brisanja",
+       "log-action-filter-delete-revision": "Izbris redakcije",
+       "log-action-filter-patrol-patrol": "Ročni nadzor",
+       "log-action-filter-patrol-autopatrol": "Samodejni nadzor",
+       "log-action-filter-protect-protect": "Zaščita",
+       "log-action-filter-protect-modify": "Sprememba zaščite",
+       "log-action-filter-protect-unprotect": "Odstranitev zaščite",
+       "log-action-filter-upload-upload": "Novo nalaganje",
+       "log-action-filter-upload-overwrite": "Ponovno nalaganje"
 }
index 04b8a53..d49fa65 100644 (file)
        "october-date": "$1 окотобар",
        "november-date": "$1 новембар",
        "december-date": "$1 децембар",
+       "period-am": "преподне",
+       "period-pm": "поподне",
        "pagecategories": "{{PLURAL:$1|Категорија|Категорије}}",
        "category_header": "Странице у категорији „$1“",
        "subcategories": "Поткатегорије",
        "newarticle": "(нови)",
        "newarticletext": "Дошли сте на страницу која још не постоји.\nДа бисте је направили, почните да куцате у прозор испод овог текста (погледајте [$1 страницу за помоћ]).\nАко сте овде дошли грешком, вратите се на претходну страницу.",
        "anontalkpagetext": "---- Ово је страница за разговор с анонимним корисником који још нема налог или га не користи.\nЗбог тога морамо да користимо бројчану ИП адресу како бисмо га препознали.\nТакву адресу може делити више корисника.\nАко сте анонимни корисник и мислите да су вам упућене примедбе, [[Special:UserLogin/signup|отворите налог]] или се [[Special:UserLogin|пријавите]] да бисте избегли будућу забуну с осталим анонимним корисницима.",
-       "noarticletext": "На овој страници тренутно нема садржаја.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне извештаје] или [{{fullurl:{{FULLPAGENAME}}|action=edit}} уредити страницу]</span>.",
+       "noarticletext": "На овој страници тренутно нема садржаја.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне извештаје] или [{{fullurl:{{FULLPAGENAME}}|action=edit}} направити ову страницу]</span>.",
        "noarticletext-nopermission": "На овој страници тренутно нема садржаја.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама или <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне дневнике]</span>, али немате дозволу да направите ову страницу.",
        "missing-revision": "Не могу да пронађем измену бр. $1 на страници под називом „{{FULLPAGENAME}}“.\n\nОво се обично дешава када пратите застарелу везу до странице која је обрисана.\nВише информација можете пронаћи у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневнику брисања].",
        "userpage-userdoesnotexist": "Кориснички налог „<nowiki>$1</nowiki>“ није отворен.\nРазмислите да ли заиста желите да направите/уредите ову страницу.",
        "grant-group-file-interaction": "Уређивање датотека",
        "grant-group-watchlist-interaction": "Уређивање вашег списка надгледања",
        "grant-group-email": "Пошаљи имејл",
+       "grant-blockusers": "Блокирање и деблокирање корисника",
        "grant-createaccount": "Отварање налога",
        "grant-createeditmovepage": "Прављење, уређивање и премештање страница",
        "grant-delete": "Брисање страница, измена и уноса у дневницима",
        "grant-editinterface": "Уређивање Медијавики именског простора и корисничких CSS/JavaScript страница",
+       "grant-editmyoptions": "Уређивање ваших подешавања",
        "grant-editmywatchlist": "Уређивање вашег списка надгледања",
        "grant-editpage": "Уређивање постојећих страница",
        "grant-editprotected": "Уређивање заштићених страница",
+       "grant-protect": "Закључавање и откључавање страница",
+       "grant-rollback": "Враћање измена",
        "grant-uploadeditmovefile": "Отпремање, замена и премештање датотека",
        "grant-uploadfile": "Слање нових датотека",
+       "grant-basic": "Основна права",
+       "grant-viewdeleted": "Преглед обрисаних страница и датотека",
+       "grant-viewmywatchlist": "Преглед вашег списак надгледања",
        "newuserlogpage": "Дневник нових корисника",
        "newuserlogpagetext": "Ово је дневник нових корисника.",
        "rightslog": "Дневник корисничких права",
        "recentchangeslinked-page": "Назив странице:",
        "recentchangeslinked-to": "Прикажи измене страница које су повезане с датом страницом",
        "recentchanges-page-added-to-category": "[[:$1]] је додата у категорију",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] и још {{PLURAL:$2|једна страница|$2 странице}} су додате у категорију",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] и још [[Special:WhatLinksHere/$1|{{PLURAL:$2|једна страница|$2 странице}}]] су додате у категорију",
        "recentchanges-page-removed-from-category": "[[:$1]] је уклоњена из категорије",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] и још {{PLURAL:$2|једна страница|$2 странице}} су уклоњене из категорије",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] и још [[Special:WhatLinksHere/$1|{{PLURAL:$2|једна страница|$2 странице}}]] су уклоњене из категорије",
        "autochange-username": "Медијавики аутоматска измена",
        "upload": "Пошаљи датотеку",
        "uploadbtn": "Пошаљи датотеку",
        "delete-toobig": "Ова страница има велику историју, преко $1 {{PLURAL:$1|измене|измене|измена}}.\nБрисање таквих страница је ограничено да би се спречило случајно оптерећење сервера.",
        "delete-warning-toobig": "Ова страница има велику историју, преко $1 {{PLURAL:$1|измене|изменe|измена}}.\nЊено брисање може пореметити базу података, стога поступајте с опрезом.",
        "deleteprotected": "Не можете обрисати ову страницу зато што је заштићена.",
-       "deleting-backlinks-warning": "'''Упозорење:''' бришете страницу која је укључена у [[Special:WhatLinksHere/{{FULLPAGENAME}}|друге странице]] или друге странице воде на њу.",
+       "deleting-backlinks-warning": "<strong>Упозорење:</strong> бришете страницу која је укључена у [[Special:WhatLinksHere/{{FULLPAGENAME}}|друге странице]] или друге странице воде на њу.",
        "rollback": "Врати измене",
        "rollbacklink": "врати",
        "rollbacklinkcount": "врати $1 {{PLURAL:$1|измену|измене|измена}}",
        "changecontentmodel-title-label": "Наслов странице",
        "changecontentmodel-model-label": "Нови модел садржаја",
        "changecontentmodel-reason-label": "Разлог:",
+       "changecontentmodel-submit": "Промени",
        "changecontentmodel-success-title": "Модел садржаја је промењен",
        "changecontentmodel-success-text": "Модел садржаја странице [[:$1]] је промењен.",
        "changecontentmodel-cannot-convert": "Модел садржаја странице [[:$1]] се не може претворити у врсту $2.",
        "move-leave-redirect": "Остави преусмерење",
        "protectedpagemovewarning": "'''Упозорење:''' ова страница је заштићена, тако да само корисници с администраторским овлашћењима могу да је преместе.\nЗа више информација, последњи запис у дневнику измена је приказан испод:",
        "semiprotectedpagemovewarning": "'''Напомена:''' ова страница је заштићена, тако да само регистровани корисници могу да је преместе.\nЗа више информација, последњи запис у дневнику измена је приказан испод:",
-       "move-over-sharedrepo": "== Датотека постоји ==\n[[:$1]] се налази на дељеном складишту. Ако преместите датотеку на овај наслов, то ће заменити дељену датотеку.",
+       "move-over-sharedrepo": "[[:$1]] се налази на дељеном складишту. Ако преместите датотеку на овај наслов, то ће заменити дељену датотеку.",
        "file-exists-sharedrepo": "Наведени назив датотеке се већ користи у дељеном складишту.\nИзаберите други назив.",
        "export": "Извоз страница",
        "exporttext": "Можете извести текст и историју измена одређене странице или групе страница у формату XML.\nОво онда може бити увезено у други вики који користи Медијавики софтвер преко [[Special:Import|странице за увоз]].\n\nДа бисте извезли странице, унесите називе у оквиру испод, с једним насловом по реду, и изаберите да ли желите текућу измену и све остале, или само текућу измену с подацима о последњој измени.\n\nУ другом случају, можете користити и везу, на пример [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] за страницу [[{{MediaWiki:Mainpage}}]].",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|измена увезена|измене увезене|измена увезено}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|измена увезена|измене увезене|измена увезено}} из $2",
        "javascripttest": "Јаваскрипт тест",
-       "javascripttest-pagetext-noframework": "Ова страница је резервисана за извршавање јаваскрипт тестова.",
-       "javascripttest-pagetext-unknownframework": "Непознати радни оквир „$1“.",
        "javascripttest-pagetext-unknownaction": "Непозната радња „$1“.",
-       "javascripttest-pagetext-frameworks": "Изаберите један од следећих радних оквира: $1",
-       "javascripttest-pagetext-skins": "Изаберите с којом темом желите да покренете пробу:",
        "javascripttest-qunit-intro": "Погледајте [$1 документацију за тестирање] на mediawiki.org.",
-       "tooltip-pt-userpage": "Ваша корисничка страница",
+       "tooltip-pt-userpage": "{{GENDER:|Ваша}} корисничка страница",
        "tooltip-pt-anonuserpage": "Корисничка страница за ИП адресу с које уређујете",
-       "tooltip-pt-mytalk": "Ваша страница за разговор",
+       "tooltip-pt-mytalk": "{{GENDER:|Ваша}} страница за разговор",
        "tooltip-pt-anontalk": "Разговор о изменама с ове ИП адресе",
-       "tooltip-pt-preferences": "Ваша подешавања",
+       "tooltip-pt-preferences": "{{GENDER:|Ваша}} подешавања",
        "tooltip-pt-watchlist": "Списак страница које надгледате",
-       "tooltip-pt-mycontris": "Списак ваших доприноса",
+       "tooltip-pt-mycontris": "Списак {{GENDER:|ваших}} доприноса",
        "tooltip-pt-anoncontribs": "Списак измена направљених са ове IP адресе",
        "tooltip-pt-login": "Препоручујемо вам да се пријавите, иако то није обавезно.",
        "tooltip-pt-logout": "Одјавите се",
        "tooltip-t-recentchangeslinked": "Скорашње измене на страницама које су повезана с овом страницом",
        "tooltip-feed-rss": "RSS довод ове странице",
        "tooltip-feed-atom": "Атом довод ове странице",
-       "tooltip-t-contributions": "Ð\9fогледаÑ\98Ñ\82е Ñ\81пиÑ\81ак Ð´Ð¾Ð¿Ñ\80иноÑ\81а Ð¾Ð²Ð¾Ð³ ÐºÐ¾Ñ\80иÑ\81ника",
-       "tooltip-t-emailuser": "Пошаљите имејл овом кориснику",
+       "tooltip-t-contributions": "СпиÑ\81ак Ð´Ð¾Ð¿Ñ\80иноÑ\81а {{GENDER:$1|овог ÐºÐ¾Ñ\80иÑ\81ника|ове ÐºÐ¾Ñ\80иÑ\81ниÑ\86е}}",
+       "tooltip-t-emailuser": "Пошаљите имејл {{GENDER:$1|овом кориснику|овој корисници}}",
        "tooltip-t-info": "Више информација о овој страници",
        "tooltip-t-upload": "Пошаљите датотеке",
        "tooltip-t-specialpages": "Списак свих посебних страница",
        "variantname-gan": "gan",
        "variantname-sr-ec": "Ћирилица",
        "variantname-sr-el": "Latinica",
-       "variantname-sr": "sr",
+       "variantname-sr": "ћир/lat",
        "variantname-kk-kz": "kk-kz",
        "variantname-kk-tr": "kk-tr",
        "variantname-kk-cn": "kk-cn",
        "version-libraries-description": "Опис",
        "version-libraries-authors": "Аутори",
        "redirect": "Преусмерење на датотеку, корисника, страницу или измену",
-       "redirect-legend": "Преусмери на датотеку или страницу",
        "redirect-submit": "Иди",
        "redirect-lookup": "Тип вредности:",
        "redirect-value": "Вредност:",
        "logentry-protect-protect-cascade": "$1 је {{GENDER:$2|заштитио|заштитила}} $3 $4 [преносива заштита]",
        "logentry-protect-modify": "$1 је {{GENDER:$2|променио|променила}} степен заштите за $3 $4",
        "logentry-protect-modify-cascade": "$1 је {{GENDER:$2|променио|променила}} степен заштите за $3 $4 [преносива заштита]",
-       "logentry-rights-rights": "$1 је {{GENDER:$2|променио|променила}} чланство групе за $3 из $4 у $5",
+       "logentry-rights-rights": "$1 је {{GENDER:$2|променио|променила}} чланство групе за {{GENDER:$3|$3}} из $4 у $5",
        "logentry-rights-rights-legacy": "$1 је {{GENDER:$2|променио|променила}} чланство групе за $3",
        "logentry-rights-autopromote": "$1 је аутоматски {{GENDER:$2|унапређен|унапређена}} из $4 у $5",
        "logentry-upload-upload": "$1 је {{GENDER:$2|послао|послала}} $3",
        "mw-widgets-titleinput-description-new-page": "страница још увек не постоји",
        "mw-widgets-titleinput-description-redirect": "преусмерава на $1",
        "api-error-blacklisted": "Изаберите другачији, описан назив.",
-       "randomrootpage": "Случајна коренска страница"
+       "randomrootpage": "Случајна коренска страница",
+       "log-action-filter-block": "Тип блокирања:",
+       "log-action-filter-delete": "Тип брисања:",
+       "log-action-filter-patrol": "Тип патролирања:",
+       "log-action-filter-protect": "Тип закључавања:",
+       "log-action-filter-upload": "Тип отпремања:",
+       "log-action-filter-all": "све",
+       "log-action-filter-block-block": "блокирање",
+       "log-action-filter-block-reblock": "измена блокирања",
+       "log-action-filter-block-unblock": "деблокирање",
+       "log-action-filter-delete-delete": "брисање странице",
+       "log-action-filter-delete-restore": "враћање странице",
+       "log-action-filter-delete-event": "брисање уноса у дневницима",
+       "log-action-filter-delete-revision": "брисање измене",
+       "log-action-filter-patrol-patrol": "ручно",
+       "log-action-filter-patrol-autopatrol": "аутоматско",
+       "log-action-filter-protect-protect": "закључавање",
+       "log-action-filter-protect-modify": "измена закључавања",
+       "log-action-filter-protect-unprotect": "уклањање закључавања",
+       "log-action-filter-upload-upload": "ново",
+       "log-action-filter-upload-overwrite": "промена постојећег"
 }
index e95cfbb..7ac1b05 100644 (file)
        "newarticle": "(novi)",
        "newarticletext": "Došli ste na stranicu koja još ne postoji.\nDa biste je napravili, počnite da kucate u prozor ispod ovog teksta (pogledajte [$1 stranicu za pomoć]).\nAko ste ovde došli greškom, vratite se na prethodnu stranicu.",
        "anontalkpagetext": "---- Ovo je stranica za razgovor s anonimnim korisnikom koji još nema nalog ili ga ne koristi.\nZbog toga moramo da koristimo brojčanu IP adresu kako bismo ga prepoznali.\nTakvu adresu može deliti više korisnika.\nAko ste anonimni korisnik i mislite da su vam upućene primedbe, [[Special:UserLogin/signup|otvorite nalog]] ili se [[Special:UserLogin|prijavite]] da biste izbegli buduću zabunu s ostalim anonimnim korisnicima.",
-       "noarticletext": "Na ovoj stranici trenutno nema sadržaja.\nMožete [[Special:Search/{{PAGENAME}}|potražiti ovaj naslov]] na drugim stranicama,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pretražiti srodne izveštaje] ili [{{fullurl:{{FULLPAGENAME}}|action=edit}} urediti stranicu]</span>.",
+       "noarticletext": "Na ovoj stranici trenutno nema sadržaja.\nMožete [[Special:Search/{{PAGENAME}}|potražiti ovaj naslov]] na drugim stranicama,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pretražiti srodne izveštaje] ili [{{fullurl:{{FULLPAGENAME}}|action=edit}} napraviti ovu stranicu]</span>.",
        "noarticletext-nopermission": "Na ovoj stranici trenutno nema sadržaja.\nMožete [[Special:Search/{{PAGENAME}}|potražiti ovaj naslov]] na drugim stranicama ili <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pretražiti srodne dnevnike]</span>, ali nemate dozvolu da napravite ovu stranicu.",
        "missing-revision": "Ne mogu da pronađem izmenu br. $1 na stranici pod nazivom „{{FULLPAGENAME}}“.\n\nOvo se obično dešava kada pratite zastarelu vezu do stranice koja je obrisana.\nViše informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].",
        "userpage-userdoesnotexist": "Korisnički nalog „<nowiki>$1</nowiki>“ nije otvoren.\nRazmislite da li zaista želite da napravite/uredite ovu stranicu.",
        "recentchangeslinked-page": "Naziv stranice:",
        "recentchangeslinked-to": "Prikaži izmene stranica koje su povezane s datom stranicom",
        "recentchanges-page-added-to-category": "[[:$1]] je dodata u kategoriju",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] i još {{PLURAL:$2|jedna stranica|$2 stranice}} su dodate u kategoriju",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] i još [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedna stranica|$2 stranice}}]] su dodate u kategoriju",
        "recentchanges-page-removed-from-category": "[[:$1]] je uklonjena iz kategorije",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] i još {{PLURAL:$2|jedna stranica|$2 stranice}} su uklonjene iz kategorije",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] i još [[Special:WhatLinksHere/$1|{{PLURAL:$2|jedna stranica|$2 stranice}}]] su uklonjene iz kategorije",
        "autochange-username": "Medijaviki automatska izmena",
        "upload": "Pošalji datoteku",
        "uploadbtn": "Pošalji datoteku",
        "delete-toobig": "Ova stranica ima veliku istoriju, preko $1 {{PLURAL:$1|izmene|izmene|izmena}}.\nBrisanje takvih stranica je ograničeno da bi se sprečilo slučajno opterećenje servera.",
        "delete-warning-toobig": "Ova stranica ima veliku istoriju, preko $1 {{PLURAL:$1|izmene|izmene|izmena}}.\nNjeno brisanje može poremetiti bazu podataka, stoga postupajte s oprezom.",
        "deleteprotected": "Ne možete obrisati ovu stranicu zato što je zaštićena.",
-       "deleting-backlinks-warning": "'''Upozorenje:''' brišete stranicu koja je uključena u [[Special:WhatLinksHere/{{FULLPAGENAME}}|druge stranice]] ili druge stranice vode na nju.",
+       "deleting-backlinks-warning": "<strong>Upozorenje:</strong> brišete stranicu koja je uključena u [[Special:WhatLinksHere/{{FULLPAGENAME}}|druge stranice]] ili druge stranice vode na nju.",
        "rollback": "Vrati izmene",
        "rollbacklink": "vrati",
        "rollbacklinkcount": "vrati $1 {{PLURAL:$1|izmenu|izmene|izmena}}",
        "move-leave-redirect": "Ostavi preusmerenje",
        "protectedpagemovewarning": "'''Upozorenje:''' ova stranica je zaštićena, tako da samo korisnici s administratorskim ovlašćenjima mogu da je premeste.\nZa više informacija, poslednji zapis u dnevniku izmena je prikazan ispod:",
        "semiprotectedpagemovewarning": "'''Napomena:''' ova stranica je zaštićena, tako da samo registrovani korisnici mogu da je premeste.\nZa više informacija, poslednji zapis u dnevniku izmena je prikazan ispod:",
-       "move-over-sharedrepo": "== Datoteka postoji ==\n[[:$1]] se nalazi na deljenom skladištu. Ako premestite datoteku na ovaj naslov, to će zameniti deljenu datoteku.",
+       "move-over-sharedrepo": "[[:$1]] se nalazi na deljenom skladištu. Ako premestite datoteku na ovaj naslov, to će zameniti deljenu datoteku.",
        "file-exists-sharedrepo": "Navedeni naziv datoteke se već koristi u deljenom skladištu.\nIzaberite drugi naziv.",
        "export": "Izvoz stranica",
        "exporttext": "Možete izvesti tekst i istoriju izmena određene stranice ili grupe stranica u formatu XML.\nOvo onda može biti uvezeno u drugi viki koji koristi Medijaviki softver preko [[Special:Import|stranice za uvoz]].\n\nDa biste izvezli stranice, unesite nazive u okviru ispod, s jednim naslovom po redu, i izaberite da li želite tekuću izmenu i sve ostale, ili samo tekuću izmenu s podacima o poslednjoj izmeni.\n\nU drugom slučaju, možete koristiti i vezu, na primer [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] za stranicu [[{{MediaWiki:Mainpage}}]].",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|izmena uvezena|izmene uvezene|izmena uvezeno}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|izmena uvezena|izmene uvezene|izmena uvezeno}} iz $2",
        "javascripttest": "Javaskript test",
-       "javascripttest-pagetext-noframework": "Ova stranica je rezervisana za izvršavanje javaskript testova.",
-       "javascripttest-pagetext-unknownframework": "Nepoznati radni okvir „$1“.",
-       "javascripttest-pagetext-frameworks": "Izaberite jedan od sledećih radnih okvira: $1",
-       "javascripttest-pagetext-skins": "Izaberite s kojom temom želite da pokrenete probu:",
        "javascripttest-qunit-intro": "Pogledajte [$1 dokumentaciju za testiranje] na mediawiki.org.",
-       "tooltip-pt-userpage": "Vaša korisnička stranica",
+       "tooltip-pt-userpage": "{{GENDER:|Vaša}} korisnička stranica",
        "tooltip-pt-anonuserpage": "Korisnička stranica za IP adresu s koje uređujete",
-       "tooltip-pt-mytalk": "Vaša stranica za razgovor",
+       "tooltip-pt-mytalk": "{{GENDER:|Vaša}} stranica za razgovor",
        "tooltip-pt-anontalk": "Razgovor o izmenama s ove IP adrese",
-       "tooltip-pt-preferences": "Vaša podešavanja",
+       "tooltip-pt-preferences": "{{GENDER:|Vaša}} podešavanja",
        "tooltip-pt-watchlist": "Spisak stranica koje nadgledate",
-       "tooltip-pt-mycontris": "Spisak vaših doprinosa",
+       "tooltip-pt-mycontris": "Spisak {{GENDER:|vaših}} doprinosa",
        "tooltip-pt-anoncontribs": "Spisak izmena napravljenih sa ove IP adrese",
        "tooltip-pt-login": "Preporučujemo vam da se prijavite, iako to nije obavezno.",
        "tooltip-pt-logout": "Odjavite se",
        "tooltip-t-recentchangeslinked": "Skorašnje izmene na stranicama koje su povezana s ovom stranicom",
        "tooltip-feed-rss": "RSS dovod ove stranice",
        "tooltip-feed-atom": "Atom dovod ove stranice",
-       "tooltip-t-contributions": "Pogledajte spisak doprinosa ovog korisnika",
-       "tooltip-t-emailuser": "Pošaljite e-poruku ovom korisniku",
+       "tooltip-t-contributions": "Spisak doprinosa {{GENDER:$1|ovog korisnika|ove korisnice}}",
+       "tooltip-t-emailuser": "Pošaljite imejl {{GENDER:$1|ovom korisniku|ovoj korisnici}}",
        "tooltip-t-info": "Više informacija o ovoj stranici",
        "tooltip-t-upload": "Pošaljite datoteke",
        "tooltip-t-specialpages": "Spisak svih posebnih stranica",
        "variantname-gan": "gan",
        "variantname-sr-ec": "Ćirilica",
        "variantname-sr-el": "Latinica",
-       "variantname-sr": "sr",
+       "variantname-sr": "ћир/lat",
        "variantname-kk-kz": "kk-kz",
        "variantname-kk-tr": "kk-tr",
        "variantname-kk-cn": "kk-cn",
        "version-libraries-description": "Opis",
        "version-libraries-authors": "Autori",
        "redirect": "Preusmerenje na datoteku, korisnika, stranicu ili izmenu",
-       "redirect-legend": "Preusmeri na datoteku ili stranicu",
        "redirect-submit": "Idi",
        "redirect-lookup": "Tip vrednosti:",
        "redirect-value": "Vrednost:",
        "logentry-protect-protect-cascade": "$1 je {{GENDER:$2|zaštitio|zaštitila}} $3 $4 [prenosiva zaštita]",
        "logentry-protect-modify": "$1 je {{GENDER:$2|promenio|promenila}} stepen zaštite za $3 $4",
        "logentry-protect-modify-cascade": "$1 je {{GENDER:$2|promenio|promenila}} stepen zaštite za $3 $4 [prenosiva zaštita]",
-       "logentry-rights-rights": "$1 je {{GENDER:$2|promenio|promenila}} članstvo grupe za $3 iz $4 u $5",
+       "logentry-rights-rights": "$1 je {{GENDER:$2|promenio|promenila}} članstvo grupe za {{GENDER:$3|$3}} iz $4 u $5",
        "logentry-rights-rights-legacy": "$1 je {{GENDER:$2|promenio|promenila}} čalnstvo grupe za $3",
        "logentry-rights-autopromote": "$1 je automatski {{GENDER:$1|unapređen|unapređena}} iz $4 u $5",
        "logentry-upload-upload": "$1 je {{GENDER:$2|poslao|poslala}} $3",
index e856378..2c8ed35 100644 (file)
        "nocookieslogin": "{{SITENAME}} använder kakor för att logga in användare. Du har stängt av kakor i din webbläsare. Försök igen med stöd för kakor aktiverat.",
        "nocookiesfornew": "Användarkontot skapades inte, eftersom vi inte kunde bekräfta dess källa.\nSe till att du har aktiverat kakor, ladda om denna sida och försök igen.",
        "noname": "Du har angett ett ogiltigt användarnamn.",
-       "loginsuccesstitle": "Inloggningen lyckades",
+       "loginsuccesstitle": "Inloggad",
        "loginsuccess": "'''Du är nu inloggad på {{SITENAME}} som \"$1\".'''",
        "nosuchuser": "Det finns ingen användare med namnet \"$1\".\nAnvändarnamn är skiftlägeskänsliga.\nKontrollera din stavning, eller [[Special:UserLogin/signup|skapa ett nytt konto]].",
        "nosuchusershort": "Det finns ingen användare som heter \"$1\". Kontrollera att du stavat rätt.",
        "botpasswords-insert-failed": "Kunde inte lägga till botnamnet \"$1\". Har det redan lagts till?",
        "botpasswords-update-failed": "Kunde inte uppdatera botnamnet \"$1\". Har det raderats?",
        "botpasswords-created-title": "Botlösenord skapades",
-       "botpasswords-created-body": "Botlösenordet \"$1\" skapades.",
+       "botpasswords-created-body": "Botlösenordet för botnamnet \"$1\" till användaren \"$2\" skapades.",
        "botpasswords-updated-title": "Botlösenordet uppdaterades",
-       "botpasswords-updated-body": "Botlösenordet \"$1\" uppdaterades.",
+       "botpasswords-updated-body": "Botlösenordet för botnamnet \"$1\" till användaren \"$2\" uppdaterades.",
        "botpasswords-deleted-title": "Botlösenord raderades",
-       "botpasswords-deleted-body": "Botlösenordet \"$1\" raderades.",
+       "botpasswords-deleted-body": "Botlösenordet för botnamnet \"$1\" till användaren \"$2\" raderades.",
        "botpasswords-newpassword": "Det nya lösenordet att logga in för <strong>$1</strong> är <strong>$2</strong>. <em>Spara detta som framtida referens.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider är inte tillgänglig.",
        "botpasswords-restriction-failed": "Begränsningar av botlösenord tillåter inte denna inloggning.",
        "revdelete-unsuppress": "Ta bort begränsningar på återställda versioner",
        "revdelete-log": "Anledning:",
        "revdelete-submit": "Tillämpa på {{PLURAL:$1|vald version|valda versioner}}",
-       "revdelete-success": "'''Sidversionssynlighet har uppdaterats.'''",
+       "revdelete-success": "Sidversionssynlighet har uppdaterats.",
        "revdelete-failure": "'''Sidversionssynlighet kunde inte uppdateras:'''\n$1",
-       "logdelete-success": "'''Loggens synlighet har ställts in.'''",
+       "logdelete-success": "Loggens synlighet har ställts in.",
        "logdelete-failure": "'''Loggens synlighet kunde inte ställas in:'''\n$1",
        "revdel-restore": "ändra synlighet",
        "pagehist": "Sidhistorik",
        "recentchangeslinked-page": "Sidnamn:",
        "recentchangeslinked-to": "Visa ändringar på sidor med länkar till den givna sidan istället",
        "recentchanges-page-added-to-category": "[[:$1]] lades till i kategorin",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] och {{PLURAL:$2|en sida|$2 sidor}} lades till i kategorin",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] och [[Special:WhatLinksHere/$1|{{PLURAL:$2|en sida|$2 sidor}}]] lades till i kategorin",
        "recentchanges-page-removed-from-category": "[[:$1]] togs bort från kategorin",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] och {{PLURAL:$2|en sida|$2 sidor}} togs bort från kategorin",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] och [[Special:WhatLinksHere/$1|{{PLURAL:$2|en sida|$2 sidor}}]] togs bort från kategorin",
        "autochange-username": "Automatisk MediaWiki-ändring",
        "upload": "Ladda upp fil",
        "uploadbtn": "Ladda upp fil",
        "uploadstash-summary": "Denna sida ger tillgång till filer som är uppladdade (eller håller på att laddas upp) men som ännu inte är publicerade till wikin. Dessa filer är inte synliga för någon annan än den användare som laddade upp dem.",
        "uploadstash-clear": "Rensa temporärt lagrade filer",
        "uploadstash-nofiles": "Du har inga temporärt lagrade filer.",
-       "uploadstash-badtoken": "Utförandet av den åtgärden misslyckades, kanske för att din redigeringsrättigheter löpt ut. Försök igen.",
+       "uploadstash-badtoken": "Misslyckades att utföra åtgärden. Dina redigeringsrättigheter har kanske löpt ut. Försök igen.",
        "uploadstash-errclear": "Rensning av filerna misslyckades.",
        "uploadstash-refresh": "Uppdatera listan över filer",
+       "uploadstash-thumbnail": "visa miniatyr",
        "invalid-chunk-offset": "Ogiltig segmentsförskjutning",
        "img-auth-accessdenied": "Åtkomst nekad",
        "img-auth-nopathinfo": "PATH_INFO saknas.\nDin server är inte inställd för att ge denna information.\nDen kan vara CGI-baserad och stöder inte img_auth.\n[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization Se bildbehörighet.]",
        "changecontentmodel-title-label": "Sidtitel",
        "changecontentmodel-model-label": "Ny innehållsmodell",
        "changecontentmodel-reason-label": "Orsak:",
+       "changecontentmodel-submit": "Ändra",
        "changecontentmodel-success-title": "Innehållsmodellen ändrades",
        "changecontentmodel-success-text": "Innehållstypen för [[:$1]] har ändrats.",
        "changecontentmodel-cannot-convert": "Innehållet på [[:$1]] kan inte konverteras till typen $2.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|version|versioner}} importerades",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|version|versioner}} importerades från $2",
        "javascripttest": "JavaScript-testning",
-       "javascripttest-pagetext-noframework": "Denna sida är reserverat för att köra JavaScript-tester.",
-       "javascripttest-pagetext-unknownframework": "Okänd testmiljö \"$1\".",
        "javascripttest-pagetext-unknownaction": "Okänd handling \"$1\".",
-       "javascripttest-pagetext-frameworks": "Välj en av följande testmiljöer: $1",
-       "javascripttest-pagetext-skins": "Välj ett utseende att köra tester med:",
        "javascripttest-qunit-intro": "Se [$1 testningsdokumentationen] på mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Din användarsida}}",
        "tooltip-pt-anonuserpage": "Användarsida för ip-numret du redigerar från",
        "version-libraries-description": "Beskrivning",
        "version-libraries-authors": "Författare",
        "redirect": "Omdirigering efter filnamn, användar-ID, sida, versions-ID eller logg-ID",
-       "redirect-legend": "Omdirigera till en fil eller sida",
        "redirect-summary": "Den här specialsidan omdirigerar till en fil (efter filnamn), en sida (efter en versions eller sidas ID), en användarsida (efter användar-ID) eller en loggpost (efter logg-ID). Användning: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]] eller [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Kör",
        "redirect-lookup": "Slå upp:",
        "sessionprovider-generic": "$1-sessioner",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "cookiebaserade sessioner",
        "sessionprovider-nocookies": "Cookies kan vara inaktiverade. Se till att du har cookies aktiverat och försök igen.",
-       "randomrootpage": "Slumprotsida"
+       "randomrootpage": "Slumprotsida",
+       "log-action-filter-block": "Typ av blockering:",
+       "log-action-filter-delete": "Typ av radering:",
+       "log-action-filter-patrol": "Typ av patrullering:",
+       "log-action-filter-protect": "Typ av skydd:",
+       "log-action-filter-upload": "Typ av uppladdning:",
+       "log-action-filter-all": "Alla",
+       "log-action-filter-block-block": "Blockering",
+       "log-action-filter-block-reblock": "Blockeringsändring",
+       "log-action-filter-block-unblock": "Tog bort blockering",
+       "log-action-filter-delete-delete": "Radering av sida",
+       "log-action-filter-delete-restore": "Återställde sida",
+       "log-action-filter-delete-event": "Radering av logg",
+       "log-action-filter-delete-revision": "Radering av sidversion",
+       "log-action-filter-patrol-patrol": "Manuell patrullering",
+       "log-action-filter-patrol-autopatrol": "Automatisk patrullering",
+       "log-action-filter-protect-protect": "Skydd",
+       "log-action-filter-protect-modify": "Ändring av skydd",
+       "log-action-filter-protect-unprotect": "Tog bort skydd",
+       "log-action-filter-upload-upload": "Ny uppladdning",
+       "log-action-filter-upload-overwrite": "Återuppladdning"
 }
index 7374523..dfa514b 100644 (file)
@@ -45,7 +45,9 @@
                        "Anj.balaji",
                        "Dineshkumar Ponnusamy",
                        "Sharanrajindia",
-                       "Maathavan"
+                       "Maathavan",
+                       "தமிழ்க்குரிசில்",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "இணைப்புகளுக்கு அடிக்கோடிடு",
        "perfcachedts": "பின்வரும் தரவுகள் இடைமாற்றைக் கொண்டுள்ளன, தரவுகள் கடைசியாக  $1 இல் புதுபிக்கப்பட்டுள்ளன.அதிகபட்சமாக {{PLURAL:$4|ஒரு முடிவு|$4 முடிவுகள்}} இடைமாற்றில் இருக்கலாம்.",
        "querypage-no-updates": "இப்பக்கத்துக்கான இற்றைப்படுத்தல்கள் செயலிழக்கச் செய்யப்பட்டுள்ளன. இங்கே உள்ளத் தரவுகள் தற்சமயம் இற்றைப்படுத்தப்படமாட்டாது.",
        "viewsource": "மூலத்தைப் பார்",
-       "viewsource-title": "$1க்கான மூலத்தைப்  பார்",
+       "viewsource-title": "$1 என்பதற்கான மூலத்தைப் பார்",
        "actionthrottled": "செயற்பாடு கட்டுப்படுத்தப்பட்டது",
        "actionthrottledtext": "எரிதக் காப்பு நடவடிக்கையாகப் பயனொருவர் குறித்த சிறு கால இடைவெளியில் இச்செயற்பாட்டை அதிகளவில் செய்வது தடுக்கப்பட்டுள்ளது. நீர் அவ்வெல்லையைத் தாண்டிவிட்டீர். அருள் கூர்ந்து சில நிமிடங்களில் முயலவும்.",
        "protectedpagetext": "இப்பக்கம் தொகுக்கப்படுவதையோ அல்லது பிற செயல்களைத் தவிர்ப்பதற்காகவோ பூட்டப்பட்டுள்ளது.",
        "loginlanguagelabel": "மொழி: $1",
        "suspicious-userlogout": "உங்கள் விடுபதிகை கோரிக்கை மறுக்கப்பட்டது ஏனென்றால் அது அறுபட்ட உலாவி அல்லது மாற்று இடைக்கிடங்கியால் அனுப்பப்பட்டுள்ளது.",
        "createacct-another-realname-tip": "உண்மையான பெயர் கட்டாயமற்றது.\nநீங்கள் இதை கொடுத்தால் உங்கள் ஆக்கங்களுக்கான உரிமையளிப்புகளின் போது இது பயன்படும்.",
-       "pt-login": "பà¯\81à®\95à¯\81பதிà®\95ை",
+       "pt-login": "à®\89ளà¯\8dநà¯\81à®´ை",
        "pt-login-button": "புகுபதிகை",
        "pt-createaccount": "புதிய கணக்கை உருவாக்கவும்",
        "pt-userlogout": "விடுபதிகை",
        "sectioneditnotsupported-text": "இப்பக்கத்தில் உட்பிரிவை தொகுக்க தேவையான ஆதரவில்லை.",
        "permissionserrors": "அனுமதி தவறுகள்",
        "permissionserrorstext": "பின்வரும் {{PLURAL:$1|காரணத்துக்காக|காரணங்களுக்காக}} நீங்கள் அதைச் செய்ய முடியாது:",
-       "permissionserrorstext-withaction": "$2-்கு தங்களுக்கு அனுமதி இல்லை. அதற்கான {{PLURAL:$1|காரணம்|காரணங்கள்}}:",
+       "permissionserrorstext-withaction": "$2- இதற்கு தங்களுக்கு அனுமதி இல்லை. அதற்கான {{PLURAL:$1|காரணம்|காரணங்கள்}}:",
        "recreate-moveddeleted-warn": "'''எச்சரிக்கை: தாங்கள் ஏற்கனவே நீக்கப்பட்ட பக்கமொன்றை மீண்டும் தொடங்க விழைகிறீர்கள்.'''\n\nஇப்பக்கத்தைத் தொடர்ந்து தொகுப்பது சரியானதா என்று எண்ணிப்பார்க்கவும்.\n\nதங்களின் வசதிக்காக இப்பக்கத்தின் நீக்கல் மற்றும் நகர்த்தல் குறிப்புகள் கொடுக்கப்பட்டுள்ளது:",
        "moveddeleted-notice": "இது ஒரு நீக்கப்பட்ட பக்கமாகும்.\n\nதங்களின் வசதிக்காக இப்பக்கத்தின் நீக்கல் மற்றும் நகர்த்தல் குறிப்புகள் கொடுக்கப்பட்டுள்ளது.",
        "moveddeleted-notice-recent": "மன்னிக்கவும், இந்தப் பக்கம் அண்மையில் நீக்கப்பட்டுள்ளது (24 மணித்தியாலத்திற்குள்). இப்பக்கத்திற்கான நீக்கல் மற்றும் நகர்த்தல் பதிவு கீழே மேற்கோளுக்காக தரப்பட்டுள்ளது.",
        "postedit-confirmation-saved": "உங்களது தொகுப்பு சேமிக்கப்பட்டது.",
        "edit-already-exists": "புதிய பக்கமொன்றை உருவாக்க முடியாது.\nஇப்பக்கம் ஏற்கனவே உள்ளது.",
        "defaultmessagetext": "இயல்பிருப்பு தகவல் உரை",
-       "content-failed-to-parse": "à®\89ளà¯\8dளà®\9fà®\95à¯\8dà®\95à®®à¯\8d $2 à®µà®\95à¯\88 $1 à®\95்காக பாகுபடுத்தல் தோல்வி: $3",
+       "content-failed-to-parse": "à®\89ளà¯\8dளà®\9fà®\95à¯\8dà®\95à®®à¯\8d $2 à®µà®\95à¯\88 $1 à®\87à®±்காக பாகுபடுத்தல் தோல்வி: $3",
        "invalid-content-data": "செல்லாத உள்ளடக்கத் தரவு",
        "content-not-allowed-here": "\"$1\" உள்ளடக்கம் [[$2]] பக்கத்தில் அனுமதிக்கப்படவில்லை.",
        "editwarning-warning": "இந்த பக்கத்தை விட்டு செல்வது நீங்கள் ஏற்படுத்திய மாற்றங்களை இழக்க வழிவகுக்கும்.\nநீங்கள் புகுபதிந்திருந்தால், இந்த எச்சரிக்கையை உங்கள் விருப்பத்தேர்வில் உள்ள \"{{int:prefs-editing}}\" பகுதி மூலம் நீக்கலாம்.",
        "recentchanges-label-newpage": "இந்தத் தொகுப்பு ஒரு புதிய பக்கத்தை உருவாக்கியுள்ளது",
        "recentchanges-label-minor": "இது ஒரு சிறு தொகுப்பு",
        "recentchanges-label-bot": "இந்த தொகுப்பானது ஒரு தானியங்கியால் செய்யப்பட்டதாகும்",
-       "recentchanges-label-unpatrolled": "à®\87நà¯\8dத  à®¤à¯\8aà®\95à¯\81பà¯\8dபà¯\81  à®\87னà¯\8dனà¯\81à®®à¯\8d à®°à¯\8bநà¯\8dதிà®\9fபà¯\8dபà®\9fவில்லை",
+       "recentchanges-label-unpatrolled": "à®\87தà¯\8dதà¯\8aà®\95à¯\81பà¯\8dபà¯\81 à®\87னà¯\8dனà¯\81à®®à¯\8d à®\9aà¯\81à®±à¯\8dà®±à¯\81à®\95à¯\8dà®\95ாவலà¯\81à®\95à¯\8dà®\95à¯\81 à®\89ளà¯\8dளாà®\95வில்லை",
        "recentchanges-label-plusminus": "இத்தனை பைட்டுகளுக்கு பக்கத்தின் அளவு மாற்றப்பட்டுள்ளது",
        "recentchanges-legend-heading": "<strong>குறியீட்டு விளக்கம்:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|புதிய பக்கங்கள் பட்டியலையும்]] காணவும்)",
        "recentchangeslinked-page": "பக்கப் பெயர்:",
        "recentchangeslinked-to": "இதற்குப் பதிலாக இப்பக்கத்தினை இணைத்த பக்கங்களின் மாற்றங்களைக் காட்டவும்",
        "recentchanges-page-added-to-category": "[[:$1]] பகுப்பில் சேர்க்கப்பட்டது",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] மற்றும் {{PLURAL:$2|ஒரு பக்கம்|$2 பக்கங்கள்}} பகுப்பில் சேர்க்கப்பட்டது",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] மற்றும் [[Special:WhatLinksHere/$1|{{PLURAL:$2|ஒரு பக்கம்|$2 பக்கங்கள்}}]] பகுப்பில் சேர்க்கப்பட்டது",
        "recentchanges-page-removed-from-category": "[[:$1]] பகுப்பில் இருந்து நீக்கப்பட்டது",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] மற்றும் {{PLURAL:$2|ஒரு பக்கம்|$2 பக்கங்கள்}} பகுப்பிலிருந்து நீக்கப்பட்டது",
        "autochange-username": "மீடியாவிக்கி தானியக்க மாற்றம்",
        "listfiles-latestversion-yes": "ஆம்",
        "listfiles-latestversion-no": "இல்லை",
        "file-anchor-link": "கோப்பு",
-       "filehist": "à®\95à¯\8bபà¯\8dபà¯\81 வரலாறு",
+       "filehist": "à®\95à¯\8bபà¯\8dபினà¯\8d வரலாறு",
        "filehist-help": "குறித்த நேரத்தில் இருந்த படிமத்தைப் பார்க்க அந்நேரத்தின் மீது சொடுக்கவும்.",
        "filehist-deleteall": "சகலத்தையும் நீக்கு",
        "filehist-deleteone": "நீக்குக",
        "protect-summary-cascade": "படிநிலை",
        "protect-expiring": "$1 (UTC) மணிக்கு காலாவதியாகிறது",
        "protect-expiring-local": "காலாவதியாகும்$1",
-       "protect-expiry-indefinite": "காலவரையறையற்ற",
+       "protect-expiry-indefinite": "காலவரையறையற்ற",
        "protect-cascade": "இப்பக்கத்தில் இணைக்கப்பட்ட பக்கங்களைக் காப்புச் செய் (படிநிலைக் காப்பு)",
        "protect-cantedit": "இப்பக்கத்தின் காப்பு நிலையை நீங்கள் மாற்ற முடியாது. உங்களுக்கு காப்பு நிலையை தொகுப்பதற்கான அனுமதி கிடையாது.",
        "protect-othertime": "வேறு நேரம்:",
        "minimum-size": "குறைந்த அளவு",
        "maximum-size": "கூடிய அளவு:",
        "pagesize": "(பைட்டுகள்)",
-       "restriction-edit": "தொகு",
-       "restriction-move": "நà®\95à®°à¯\8dதà¯\8dதவà¯\81à®®்",
+       "restriction-edit": "தொகுத்தல்",
+       "restriction-move": "நà®\95à®°à¯\8dதà¯\8dதல்",
        "restriction-create": "உருவாக்கு",
        "restriction-upload": "பதிவேற்றம்",
        "restriction-level-sysop": "முழுமையாக காக்கப்பட்டது",
        "contributions-title": "$1 இற்கான பயனர் பங்களிப்புகள்",
        "mycontris": "பங்களிப்புக்கள்",
        "anoncontribs": "பங்களிப்புக்கள்",
-       "contribsub2": "{{GENDER:$3|$1}} à®\95்காக ($2)",
+       "contribsub2": "{{GENDER:$3|$1}} à®\87à®±்காக ($2)",
        "contributions-userdoesnotexist": "பயனர் கணக்கு \"$1\" ஆனது பதியப்படவில்லை.",
        "nocontribs": "இந்த நிபந்தனையுடன் ஒத்துப்போகும் வகையில் மாற்றங்களெதுவும் காணப்படவில்லை.",
        "uctop": "(தற்போதைய)",
        "ipblocklist-submit": "தேடுக",
        "ipblocklist-localblock": "உள் தடுப்பு",
        "ipblocklist-otherblocks": "மற்ற  {{PLURAL:$1|தடுப்பு|தடுப்புகள்}}",
-       "infiniteblock": "காலவரையறையற்ற",
+       "infiniteblock": "காலவரையறையற்ற",
        "expiringblock": "$1-தேதியில், $2-மணிக்கு இது காலாவதியாகிறது",
        "anononlyblock": "அடையாளம் காட்டாத பயனர் மட்டும்",
        "noautoblockblock": "தானியக்கமான தடை முடக்கப்பட்டுள்ளது",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|திருத்தம்|திருத்தங்கள்}} இறக்குமதி செய்யப்பட்டன",
        "import-logentry-interwiki-detail": "$2 இலிருந்து {{PLURAL:$1|திருத்தம்|திருத்தங்கள்}} இறக்குமதி செய்யப்பட்டன",
        "javascripttest": "சாவாநிரல் சோதனை நடக்கின்றது",
-       "javascripttest-pagetext-noframework": "இந்த பக்கம் JavaScript பரிசோதனை ஓட்டத்திற்காக ஒதுக்கப்பட்டுள்ளது",
-       "javascripttest-pagetext-unknownframework": "அறியப்படாத சோதனை பணிச்சட்டம் \"$1\".",
        "javascripttest-pagetext-unknownaction": "அறியப்படாத செயல் \"$1\".",
-       "javascripttest-pagetext-frameworks": "தயவு செய்து பின்வரும் சோதனை பணிச் சட்டங்களில் இருந்து ஒன்றைத் தேர்ந்தெடு: $1",
-       "javascripttest-pagetext-skins": "சோதனைகளை நடத்த முகப்புறை ஒன்றைத் தேர்வுசெய்:",
        "javascripttest-qunit-intro": "mediawiki.org இல் [$1 சோதனை கோப்புகளைப்] பார்க்க.",
        "tooltip-pt-userpage": "{{GENDER:|உங்கள் பயனர்}} பக்கம்",
        "tooltip-pt-anonuserpage": "நீங்கள் தொகுத்துக் கொண்டிருக்கும் ஐ.பி. முகவரிக்கான பயனர் பக்கம்",
        "pageinfo-category-subcats": "துணைபகுப்புகளின் எண்ணிக்கை",
        "pageinfo-category-files": "கோப்புகளின் எண்ணிக்கை",
        "markaspatrolleddiff": "ரோந்திட்டதாக குறி",
-       "markaspatrolledtext": "à®\87பà¯\8dபà®\95à¯\8dà®\95தà¯\8dதà¯\88 à®°à¯\8bநà¯\8dதிà®\9fà¯\8dà®\9fதாகக் குறி",
+       "markaspatrolledtext": "à®\87தனà¯\88 à®\9aà¯\81à®±à¯\8dà®±à¯\81à®\95à¯\8dà®\95ாவலà¯\8d à®\9aà¯\86யà¯\8dததாகக் குறி",
        "markaspatrolledtext-file": "இக்கோப்பு பதிப்பினை ரோந்திட்டதாக குறி",
        "markedaspatrolled": "ரோந்திட்டதாக குறிக்கப்பட்டது",
        "markedaspatrolledtext": "தெரிவு செய்யப்பட்டத் திருத்தம் [[:$1]]  பார்வையிட்டதாக குறிக்கப்பட்டுள்ளது.",
        "markedaspatrollederror-noautopatrol": "உமது மாற்றங்களை நீரே ரோந்திட்டதாக குறிக்க அனுமதி கிடையாது.",
        "markedaspatrollednotify": "$1 இல் மேற்கொள்ளப்பட்ட இம்மாற்றம் கண்காணிக்கப்பட்டதாய்க் குறிக்கப்பட்டது.",
        "markedaspatrollederrornotify": "சுற்றுக்காவல் தோல்வியடைந்ததாக குறிக்கப்பட்டது.",
-       "patrol-log-page": "à®°à¯\8bநà¯\8dதà¯\81ப் பதிகை",
+       "patrol-log-page": "à®\9aà¯\81à®±à¯\8dà®±à¯\81à®\95à¯\8dà®\95ாவல் பதிகை",
        "patrol-log-header": "இது ரோந்து செய்யப்பட்ட  பரிசீலனைகளுக்கான  குறிப்பேடு.",
        "log-show-hide-patrol": "$1 ரோந்து குறிப்பேடு",
        "log-show-hide-tag": "$1 அடையாள பதிவு",
        "version-libraries-description": "விளக்கம்",
        "version-libraries-authors": "ஆசிரியர்கள்",
        "redirect": "கோப்பு, பயனர், பக்கம் அல்லது திருத்த ID ஆன வழிமாற்று",
-       "redirect-legend": "கோப்பு அல்லது பக்கத்துக்கு வழிமாற்று",
        "redirect-submit": "செல்க",
        "redirect-lookup": "கவனிக்கவும்:",
        "redirect-value": "மதிப்பு:",
        "logentry-import-interwiki": "$1 $3-ஐ வேறு விக்கியிலிருந்து {{GENDER:$2|இறக்குமதி செய்தார்}}",
        "logentry-import-interwiki-details": "$1 $3-ஐ $5-இலிருந்து {{GENDER:$2|இறக்குமதி செய்தார்}} ($4 {{PLURAL:$4|மாற்றம்|மாற்றங்கள்}})",
        "logentry-merge-merge": "$1 $3-இனை $4-இனுள் {{GENDER:$2|இணைத்தார்}}",
-       "logentry-move-move": "$1 பக்கம் $3-ஐ $4க்கு {{GENDER:$2|நகர்த்தினார்}}",
+       "logentry-move-move": "$1 பக்கம் $3 என்பதை $4 என்பதற்கு {{GENDER:$2|நகர்த்தினார்}}",
        "logentry-move-move-noredirect": "$1, $3 பக்கத்தை $4 என்ற தலைப்புக்கு வழிமாற்று இன்றி நகர்த்தியுள்ளார்",
        "logentry-move-move_redir": "$1 பக்கம் $3 ஐ $4 க்கு முன்னிருந்த வழிமாற்றின் மேலாக நகர்த்தியுள்ளார்",
        "logentry-move-move_redir-noredirect": "$1 பக்கம் $3 ஐ $4 க்கு முன்னிருந்த வழிமாற்றின் மேலாக, இன்னொரு வழிமாற்றின்றி நகர்த்தியுள்ளார்",
        "logentry-patrol-patrol": "பக்கம் $3 இன் திருத்தம் $4 ஐ  $1 பார்வையிட்டுக் குறிக்கப்பட்டது. .",
-       "logentry-patrol-patrol-auto": "தானாக பக்கம் $3-ன் பரிசீலனை $4 ஆனது ரோந்து செய்யப்பட்டது என $1 குறியிடப்பட்டது.",
+       "logentry-patrol-patrol-auto": "தானாக பக்கம் $3 இன் பரிசீலனை $4 என்பது சுற்றுக்காவல் செய்யப்பட்டது என $1 பயனரால் குறியிடப்பட்டது.",
        "logentry-newusers-newusers": "பயனர் கணக்கு $1 {{GENDER:$2|உருவாக்கப்பட்டது}}",
        "logentry-newusers-create": "$1 புதிய பயனர் கணக்கு உருவாக்கப்பட்டுள்ளது.",
        "logentry-newusers-create2": "$3 பயனர் கணக்கினை $1 {{GENDER:$2|உருவாக்கினார்}}",
        "logentry-newusers-autocreate": "பயனர் கணக்கு $1 தானாக உருவாக்கப்பட்டது",
        "logentry-protect-move_prot": "$1 காப்பு அமைப்பை $4-இலிருந்து $3-இற்கு {{GENDER:$2|நகர்த்தினார்}}",
        "logentry-protect-unprotect": "$1 $3-இலிருந்து காப்பை {{GENDER:$2|நீக்கினார்}}",
-       "logentry-protect-protect": "$1 $3-இனை $4-இற்கு {{GENDER:$2|காப்பச் செய்தார்}}",
-       "logentry-protect-protect-cascade": "$1 $3-இனை $4-இற்கு {{GENDER:$2|காப்பச் செய்தார்}} [விழுத்தொடர்]",
+       "logentry-protect-protect": "$1 $3 என்பதனை $4 என்பதற்கு {{GENDER:$2|காப்பச் செய்தார்}}",
+       "logentry-protect-protect-cascade": "$1 $3 என்பதனை $4 என்பதற்கு {{GENDER:$2|காப்பச் செய்தார்}} [விழுத்தொடர்]",
        "logentry-protect-modify": "$1 $3-க்கான காப்பு நிலையை $4 நேரத்திற்கு {{GENDER:$2|மாற்றினார்}}",
        "logentry-protect-modify-cascade": "$1 $3-க்கான காப்பு நிலையை $4 நேரத்திற்கு {{GENDER:$2|மாற்றினார்}} [விழுத்தொடர்]",
        "logentry-rights-rights": "$1 $3-இற்கான குழு அங்கத்துவத்தை $4-இலிருந்து $5-இற்கு {{GENDER:$2|மாற்றினார்}}",
        "sessionprovider-generic": "$1 பகுதி",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "குக்கீயை அடிபடையாக்கக் கொண்ட பகுதிகள்",
        "sessionprovider-nocookies": "குக்கீசு செயலற்று இருக்கலாம். உங்களது குக்கீசு செயலில் உள்ளது என உறுதிப்படுத்திவிட்டு மீண்டும் முயல்க.",
-       "randomrootpage": "தற்போக்கு வேர்ப் பக்கம்"
+       "randomrootpage": "தற்போக்கு வேர்ப் பக்கம்",
+       "log-action-filter-protect": "பாதுகாப்பு வகை"
 }
index 5c3ad1c..8f4ce43 100644 (file)
        "rcshowhidemine": "నా మార్పులను $1",
        "rcshowhidemine-show": "చూపించు",
        "rcshowhidemine-hide": "దాచు",
+       "rcshowhidecategorization": "పేజి  వర్గీకరణ $1",
        "rcshowhidecategorization-show": "చూపించు",
        "rcshowhidecategorization-hide": "దాచు",
        "rclinks": "గత  $2 రోజుల లోని చివరి $1 మార్పులను చూపించు <br />$3",
        "watchlist-submit": "చూపించు",
        "wlshowtime": "చూపించాల్సిన కాలం:",
        "wlshowhideminor": "చిన్న మార్పులు",
+       "wlshowhidebots": "బాట్లు",
        "wlshowhideliu": "నమోదైన వాడుకరులు",
        "wlshowhideanons": "అజ్ఞాత వాడుకరులు",
        "wlshowhidemine": "నా మార్పులు",
+       "wlshowhidecategorization": "పేజీ వర్గీకరణ",
        "watchlist-options": "వీక్షణ జాబితా ఎంపికలు",
        "watching": "గమనిస్తున్నారు...",
        "unwatching": "గమనించడం లేదు...",
index 44ff623..5a6ea0f 100644 (file)
        "categoryviewer-pagedlinks": "($1) ($2)",
        "about": "Patungkol",
        "article": "Pahina ng nilalaman",
-       "newwindow": "(magbubukas sa bagong bintana)",
+       "newwindow": "(magbubukas sa bagong window)",
        "cancel": "Kanselahin",
        "moredotdotdot": "Damihan pa...",
        "morenotlisted": "Hindi kumpleto ang talang ito.",
        "search": "Paghahanap",
        "searchbutton": "Maghanap",
        "go": "Gawin",
-       "searcharticle": "Gawin",
+       "searcharticle": "Pumunta",
        "history": "Kasaysayan ng pahina",
        "history_short": "Kasaysayan",
        "updatedmarker": "isinapanahon mula noong huli kong pagdalaw",
        "printableversion": "Bersiyong maililimbag",
-       "permalink": "Palagiang kawing",
+       "permalink": "Palagiang link",
        "print": "Ilimbag",
        "view": "Tingnan",
        "view-foreign": "Tingnan sa $1",
        "categorypage": "Tingnan ang pahina ng kategorya",
        "viewtalkpage": "Tingnan ang usapan",
        "otherlanguages": "Sa ibang wika",
-       "redirectedfrom": "(Ikinarga mula sa $1)",
+       "redirectedfrom": "(Nakaturo mula sa $1)",
        "redirectpagesub": "Pahina ng pagkarga",
        "redirectto": "Papuntahin sa:",
        "lastmodifiedat": "Huling binago ang pahinang ito noong $2, noong $1.",
        "nstab-media": "Pahina ng midya",
        "nstab-special": "Natatanging pahina",
        "nstab-project": "Pahina ng proyekto",
-       "nstab-image": "Talaksan",
+       "nstab-image": "File",
        "nstab-mediawiki": "Mensahe",
        "nstab-template": "Padron",
        "nstab-help": "Pahina ng tulong",
        "italic_tip": "Nakahilig na panitik",
        "link_sample": "Pamagat ng kawing",
        "link_tip": "Panloob na kawing",
-       "extlink_sample": "http://www.example.com na kawing ng pamagat",
-       "extlink_tip": "Panlabas na kawing (tandaan ang unlaping http://)",
-       "headline_sample": "Paulong teksto",
-       "headline_tip": "Paulong antas 2",
+       "extlink_sample": "http://www.example.com na link ng pamagat",
+       "extlink_tip": "Panlabas na link (tandaan ang unlaping http://)",
+       "headline_sample": "Teksto ng ulong pambungad",
+       "headline_tip": "Antas 2 na ulong pambungad",
        "nowiki_sample": "Isingit ang hindi nakapormat na teksto dito",
        "nowiki_tip": "Balewalain ang pormat na pangwiki",
        "image_sample": "Halimbawa.jpg",
-       "image_tip": "Nakabaong talaksan",
+       "image_tip": "File na naka-embed",
        "media_sample": "Halimbawa.ogg",
-       "media_tip": "Kawing sa talaksan",
+       "media_tip": "Link ng file",
        "sig_tip": "Lagda mo na may tatak ng oras",
        "hr_tip": "Pahalagang na guhit (gamitin nang madalang)",
        "summary": "Buod:",
        "watchthis": "Bantayan ang pahinang ito",
        "savearticle": "Itala ang pahina",
        "preview": "Paunang tingin",
-       "showpreview": "Ipakita ang paunang tingin",
+       "showpreview": "Paunang tingin",
        "showdiff": "Ipakita ang mga pagbabago",
-       "anoneditwarning": "'''Babala:''' Hindi ka nakalagda.\nMatatala ang iyong direksiyong IP sa kasaysayan ng pagbabago ng pahinang ito.",
+       "anoneditwarning": "<stromg>Babala:</strong> Hindi ka nakalagda.\nMakikita ng publiko ang iyong IP address kung gagawa ka ng mga pagbabago. Kung <strong>[$1 mag-login]</strong> ka o <strong>[$2 lumikha ng account]</strong>, maiuugnay ang iyong mga pagbabago sa iyong account, kasama ang ibang pakinabang.",
        "anonpreviewwarning": "''Hindi ka nakalagda.  Itatala sa inyong pagtatala ang inyong direksiyong IP sa kasaysayan ng pagbabago ng pahinang ito.''",
        "missingsummary": "'''Paalala:''' Hindi ka nagbigay ng buod ng pagbabago.\nKapag pinindot mo uli ang Sagip, masasagip ang pagbabago mo na wala nito.",
        "missingcommenttext": "Magbigay ng isang kumento/puna sa ibaba.",
        "prefs-searchoptions": "Paghahanap",
        "prefs-namespaces": "Mga espasyo ng pangalan",
        "default": "Likas na pagtatakda",
-       "prefs-files": "Mga talaksan",
+       "prefs-files": "Mga file",
        "prefs-custom-css": "Pasadyang CSS",
        "prefs-custom-js": "Pasadyang JS",
        "prefs-common-css-js": "Naibahaging CSS/JS para sa lahat ng pabalat:",
        "right-move": "Ilipat ang mga pahina",
        "right-move-subpages": "Ilipat ang mga pahina kasama ang pahinang nasa ilalim nito",
        "right-move-rootuserpages": "Ilipat ang pinagugatang mga pahina ng tagagamit",
-       "right-movefile": "Ilipat ang mga talaksan",
+       "right-movefile": "Ilipat ang mga file",
        "right-suppressredirect": "Hindi nilikha sa isang pagkarga mula sa lumang pangalan kapag naglipat ng isang pahina",
-       "right-upload": "Magkarga ng mga talaksan",
+       "right-upload": "Mag-upload ng mga file",
        "right-reupload": "Patungan ang mayroon nang mga talaksan",
        "right-reupload-own": "Patungan ang talaksang kinarga ng sarili",
        "right-reupload-shared": "Patungan ang mga talaksan sa binabahaging repositoryo midya sa lokal",
        "recentchanges-label-minor": "Isa itong munting pagbabago",
        "recentchanges-label-bot": "Gawa ng isang bot ang pagbabagong ito",
        "recentchanges-label-unpatrolled": "Hindi pa napapatrulyahan ang pagbabagong ito",
+       "recentchanges-label-plusminus": "Nagbago ang laki ng pahina sa ganitong bilang ng mga byte",
        "recentchanges-legend-heading": "<strong>Gabay:</strong>",
-       "recentchanges-legend-newpage": "$1 - bagong pahina",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (tingnan din [[Special:NewPages|ang talaan ng mga bagong pahina]])",
        "rcnotefrom": "Nasa ibaba ang mga pagbabago mula pa noong '''$2''' (ipinapakita ang magpahanggang sa '''$1''').",
        "rclistfrom": "Ipakita ang bagong mga pagbabago simula sa $3 $2",
        "rcshowhideminor": "$1 ang mga maliliit na pagbabago",
        "recentchangeslinked-feed": "Kaugnay na mga pagbabago",
        "recentchangeslinked-toolbox": "Kaugnay na mga pagbabago",
        "recentchangeslinked-title": "Mga pagbabagong may kaugnayan sa \"$1\"",
-       "recentchangeslinked-summary": "Nililista ng natatanging pahina na ito ang huling mga pagbabago na nakaugnay. Naka '''matapang na teksto''' ang iyong mga binabantayan.",
+       "recentchangeslinked-summary": "Ito ang tala ng mga pagbabagong ginawa kamakailan sa mga pahinang naka-link mula sa isang tinukoy na pahina (o sa mga kasapi ng isang tinukoy na kategorya). <strong>Makapal na teksto</strong> ang mga pahinang [[Special:Watchlist|iyong mga binabantayan]].",
        "recentchangeslinked-page": "Pangalan ng pahina:",
        "recentchangeslinked-to": "Ipakita ang mga pagbabago sa mga pahinang nakaugnay sa isang binigay na pahina sa halip",
-       "upload": "Magkarga ng talaksan",
-       "uploadbtn": "Magkarga ng talaksan",
+       "upload": "Mag-upload ng file",
+       "uploadbtn": "Mag-upload ng file",
        "reuploaddesc": "Kanselahin/Iurong ang pagkarga at magbalik sa pormularyo ng pagkakarga",
        "upload-tryagain": "Ipasa ang binagong paglalarawan ng talaksan",
        "uploadnologin": "Hindi nakalagda",
        "upload-prohibited": "Ipinagbabawal na mga uri ng talaksan: $1.",
        "uploadlogpage": "Tala ng pagkarga",
        "uploadlogpagetext": "Nasa ibaba ang tala ng pinakahuling mga karga ng talaksan.",
-       "filename": "Pangalan ng talaksan",
+       "filename": "Pangalan ng file",
        "filedesc": "Buod",
        "fileuploadsummary": "Buod:",
        "filereuploadsummary": "Mga pagbabago sa talaksan:",
        "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": "Batayang talaksan",
-       "sourcefilename": "Pangalan ng panggagalingang talaksan:",
+       "upload-source": "Batayang file",
+       "sourcefilename": "Pangalan ng panggagalingang file:",
        "sourceurl": "Batayang URL:",
-       "destfilename": "Pangalan ng patutunguhang talaksan:",
+       "destfilename": "Pangalan ng patutunguhang file:",
        "upload-maxfilesize": "Pinakamataas na sukat ng talaksan: $1",
-       "upload-description": "Paglalarawan ng talaksan",
+       "upload-description": "Paglalarawan ng file",
        "upload-options": "Ikargang pataas ang mga pagpipilian",
        "watchthisupload": "Bantayan ang talaksang ito",
        "filewasdeleted": "Isang talaksan na may ganitong pangalan ay naikarga dati at nabura. Kailangan mong tingnan ang $1 bago magpatuloy sa pagkarga nito muli.",
        "upload_source_file": " (isang talaksan sa iyong kompyuter)",
        "listfiles-summary": "Ipinapakita ng natatanging pahinang ito ang lahat ng naikargang mga talaksan.\nKapag sinala ng tagagamit, tanging mga talaksan lang kung saan nagkarga ang tagagamit na iyan ng pinaka kamakailang bersiyon ng talaksan ang ipinapakita.",
        "listfiles_search_for": "Hanapin ang pangalan ng midya:",
-       "imgfile": "talaksan",
-       "listfiles": "Talaan ng talaksan",
+       "imgfile": "file",
+       "listfiles": "Talaan ng file",
        "listfiles_thumb": "Kagyat",
        "listfiles_date": "Petsa",
        "listfiles_name": "Pangalan",
        "listfiles_count": "Mga bersiyon",
        "listfiles-latestversion-yes": "Oo",
        "listfiles-latestversion-no": "Hindi",
-       "file-anchor-link": "Talaksan",
-       "filehist": "Kasaysayan ng talaksan",
+       "file-anchor-link": "File",
+       "filehist": "Kasaysayan ng file",
        "filehist-help": "Pindutin ang isang petsa/oras para makita ang anyo ng talaksan noong panahong iyon.",
        "filehist-deleteall": "burahin lahat",
        "filehist-deleteone": "burahin",
        "filehist-revert": "ibalik",
        "filehist-current": "kasalukuyan",
        "filehist-datetime": "Petsa/Oras",
-       "filehist-thumb": "Kagyat (''thumbnail'')",
+       "filehist-thumb": "Thumbnail",
        "filehist-thumbtext": "Kagyat (''thumbnail'') para sa bersyon mula noong $1",
        "filehist-nothumb": "Walang kagyat (''thumbnail'')",
        "filehist-user": "Tagagamit",
        "filehist-dimensions": "Mga sukat",
        "filehist-filesize": "Sukat ng talaksan",
        "filehist-comment": "Komento",
-       "imagelinks": "Paggamit ng talaksan",
+       "imagelinks": "Paggamit ng file",
        "linkstoimage": "Nakakawing ang sumusunod na {{PLURAL:$1|pahina|$1 pahina}} sa talaksang ito:",
        "linkstoimage-more": "Mahigit sa $1 {{PLURAL:$1|pahina|mga pahina}} ang nakakawing sa talaksang ito.\nIpinapakita sa sumusunod na talaan ang {{PLURAL:$1|unang pahina lamang|unang $1 mga pahina lamang}} na nakakawing sa talaksang ito.\nMayroong makukuhang [[Special:WhatLinksHere/$2|buong talaan]].",
        "nolinkstoimage": "Walang pahinang nakakawing sa talaksang ito.",
        "filedelete-reason-dropdown": "*Karaniwang mga dahilan ng pagbubura\n** Paglabag sa karapatang-ari\n** Nagkadalawang talaksan",
        "filedelete-edit-reasonlist": "Baguhin ang mga dahilan ng pagbura",
        "filedelete-maintenance": "Pansamantalang hindi pinagana ang pagbura at pagpapnumbalik ng mga talaksan habang nagpapanatili ng kaayusan.",
-       "filedelete-maintenance-title": "Hindi mabura ang talaksan",
+       "filedelete-maintenance-title": "Hindi mabura ang file",
        "mimesearch": "Maghanap ng MIME",
        "mimesearch-summary": "Pinapagana ng pahinang ito ang pagsasala ng mga talaksan para sa kanyang uri ng MIME. Pagpapasok: uringnilalaman/mababangkabahaginguri, hal. <code>image/jpeg</code>.",
        "mimetype": "Uri ng MIME:",
        "wantedcategories": "Kinakailangang mga kategorya",
        "wantedpages": "Kinakailangang mga pahina",
        "wantedpages-badtitle": "Hindi tanggap na pamagat sa loob ng pangkat ng kinalabasan: $1",
-       "wantedfiles": "Ninanais na mga talaksan",
+       "wantedfiles": "Ninanais na mga file",
        "wantedfiletext-cat": "Ang sumusunod na mga talaksan ay ginagamit ngunit hindi naman umiiral. Ang mga talaksang nagmumula sa mga repositoryong dayuhan ay maaariing nakalista kahit na umiiral. Ang anumang ganyang mga kamalian sa pagiging positibo ay <del>aalisin</del>. Bilang karagdagan, ang mga pahinang may nakabaon na mga talaksang hindi umiiral ay nakatala sa [[:$1]]",
        "wantedfiletext-nocat": "Ginagamit ang sumusunod na mga talaksan ngunit hindi naman umiiral. Ang mga talaksan mula sa mga repositoryong dayuhan ay maaaring nakalista kahit na umiiral. Ang ganyang mga kamalian sa pagiging positibo ay <del>aalisin</del>.",
        "wantedtemplates": "Ninanais na mga suleras",
        "allpagesto": "Ipakita ang mga pahinang nagtatapos sa:",
        "allarticles": "Lahat ng mga pahina",
        "allinnamespace": "Lahat ng mga pahina ($1 espasyo ng pangalan)",
-       "allpagessubmit": "Gawin",
+       "allpagessubmit": "Ipadala",
        "allpagesprefix": "Ipakita ang mga pahinang may unlaping:",
        "allpagesbadtitle": "Ang binagay na pamagat ng pahina ay hindi tinatanggap o may unlapi na tumuturo sa ibang wika o wiki.  Maaaring naglalaman ito ng isa o higit pa na mga karakter na hindi ginagamit bilang pamagat.",
        "allpages-bad-ns": "Wala sa {{SITENAME}} ang espasyo ng pangalang \"$1\".",
        "delete-toobig": "May isang malaking kasaysayan ng pagbabago ang pahinang ito, mahigit sa $1 {{PLURAL:$1|pagbabago|mga pagbabago}}.\nIpanagbabawal ang pagbura ng ganyang mga pahina upang maiwasan ang hindi sinasadyang pagantala/paggambala sa {{SITENAME}}.",
        "delete-warning-toobig": "May malaking kasaysayan ng pagbabago ang pahinang ito, mahigit sa $1 {{PLURAL:$1|pagbabago|mga pagbabago}}.\nMaaaring makagambala/makaabala sa pagpapatakbo sa kalipunan ng dato ng {{SITENAME}};\nmagpatuloy na may pagiingat.",
        "rollback": "Mga pagbabagong may kaugnayan sa pagpapagulong na pabalik sa (mas) dati",
-       "rollbacklink": "pagulunging pabalik sa (mas) dati",
+       "rollbacklink": "pagulunging pabalik sa dati",
        "rollbacklinkcount": "pagulunging pabalik ang $1 {{PLURAL:$1|pagbabago|mga pagbabago}}",
        "rollbacklinkcount-morethan": "pagulunging pabalik ang mahigit sa $1 {{PLURAL:$1|pagbabago|mga pagbabago}}",
        "rollbackfailed": "Nabigo ang pagpapagulong na pabalik sa (mas) dati",
        "contributions": "Mga ambag ng {{GENDER:$1|tagagamit}}",
        "contributions-title": "Mga ambag ng tagagamit na si $1",
        "mycontris": "Mga ambag",
+       "anoncontribs": "Mga inambag",
        "contribsub2": "Para kay $1 ($2)",
        "nocontribs": "Walang pagbabagong nakita sa binigay na kondisyon.",
        "uctop": "(kasalukuyan)",
        "nolinkshere-ns": "Walang pahinang nakakawing sa '''[[:$1]]''' mula sa loob ng napiling espasyo ng pangalan.",
        "isredirect": "pahinang panturo/panuto",
        "istemplate": "pagsasali",
-       "isimage": "kawing sa talaksan",
+       "isimage": "link ng file",
        "whatlinkshere-prev": "{{PLURAL:$1|nakaraang|nakaraang $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|susunod|susunod na $1}}",
        "whatlinkshere-links": "← mga kawing",
        "export-addcat": "Magdagdag",
        "export-addnstext": "Magdagdag ng mga pahina mula sa espasyo ng pangalan:",
        "export-addns": "Idagdag",
-       "export-download": "Itala bilang talaksan",
+       "export-download": "Itala bilang file",
        "export-templates": "Kabilang ang mga suleras",
        "export-pagelinks": "Isama ang nakakawing na mga pahina magpahanggang sa isang lalim na:",
        "allmessages": "Mga mensaheng pansistema",
        "allmessages-filter-submit": "Gawin",
        "allmessages-filter-translate": "Isalin",
        "thumbnail-more": "Palakihin",
-       "filemissing": "Nawawala ang talaksan",
+       "filemissing": "Nawawala ang file",
        "thumbnail_error": "May kamalian sa paglikha ng kagyat (''thumbnail''): $1",
        "djvu_page_error": "Wala sa nasasakupan ang pahinang DjVu",
        "djvu_no_xml": "Hindi makuha ang XML para sa talaksang DjVu",
        "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",
-       "import-upload-filename": "Pangalan ng talaksan:",
+       "import-upload-filename": "Pangalan ng file:",
        "import-comment": "Komento:",
        "importtext": "Pakiluwas ang talaksan magmula sa pinagmulang wiki na ginagamit ang [[Special:Export|kasangkapang pangluwas]].  \nSagipin mo ito sa iyong kompyuter at papaitaas na ikarga ito rito.",
        "importstart": "Inaangkat na ang mga pahina...",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|pagbabago|mga pagbabago}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|pagbabago|mga pagbabago}} mula sa $2",
        "javascripttest": "Pagsubok sa JavaScript",
-       "javascripttest-pagetext-noframework": "Nakalaan ang pahinang ito para sa pagpapatakbo ng mga pagsubok ng JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Hindi napag-aalamang balangkas ng pagsubok na \"$1\".",
-       "javascripttest-pagetext-frameworks": "Mangyaring pumili ng isa sa sumusunod na mga  balangkas na pangsubok: $1",
-       "javascripttest-pagetext-skins": "Pumili ng isang pabalat na patatakbuhan ng mga pagsubok:",
        "javascripttest-qunit-intro": "Tingnan ang [$1 dokumentasyon ng pagsubok] sa mediawiki.org.",
        "tooltip-pt-userpage": "Ang iyong pahina ng tagagamit",
        "tooltip-pt-anonuserpage": "Ang pahina ng tagagamit para sa IP na iyong binabago bilang",
        "tooltip-pt-preferences": "Mga nais ko",
        "tooltip-pt-watchlist": "Ang talaan ng mga pagbabago sa mga pahinang binabantayan mo",
        "tooltip-pt-mycontris": "Talaan ng mga ambag mo",
+       "tooltip-pt-anoncontribs": "Mga tala ng binago ng IP address na ito",
        "tooltip-pt-login": "Hinihikayat kang lumagda; gayunpaman, hindi ito kinakailangan.",
        "tooltip-pt-logout": "Umalis sa pagkaka-login",
        "tooltip-pt-createaccount": "Hinihikayat kang lumikha ng kuwenta at lumigda; gayunpaman, hindi ito kinakailangan",
        "tooltip-feed-atom": "Sindikasyong Atom para sa pahinang ito",
        "tooltip-t-contributions": "Tunghayan ang tala ng mga ambag ng tagagamit na ito",
        "tooltip-t-emailuser": "Magpadala ng isang e-liham sa tagagamit na ito",
-       "tooltip-t-upload": "Magkarga ng mga talaksan",
+       "tooltip-t-upload": "Mag-upload ng mga file",
        "tooltip-t-specialpages": "Tala ng lahat ng mga natatanging pahina",
        "tooltip-t-print": "Bersiyong maililimbag ng pahinang ito",
-       "tooltip-t-permalink": "Palagiang kawing sa bersyong ito ng pahina",
+       "tooltip-t-permalink": "Palagiang link sa bersyong ito ng pahina",
        "tooltip-ca-nstab-main": "Tingnan ang pahina ng nilalaman",
        "tooltip-ca-nstab-user": "Tingnan ang pahina ng tagagamit",
        "tooltip-ca-nstab-media": "Tingnan ang pahina ng midya",
        "spam_reverting": "Ibinabalik sa huling bersyon na 'di-naglalaman ng mga kawing sa $1",
        "spam_blanking": "Lahat ng mga pagbabago ay naglalaman ng mga kawing sa $1, pagpapatlang",
        "spam_deleting": "Lahat ng mga pagbabago ay naglalaman ng mga kawing sa $1, binubura",
-       "simpleantispam-label": "Pagsusuring panlaban sa \"manlulusob\" (''spam'').\n'''HUWAG''' itong lagyan ng laman!",
+       "simpleantispam-label": "Pagsusuring laban sa spam.\n<stromg>HUWAG</strong> itong lagyan ng laman!",
        "pageinfo-title": "Kabatiran para sa \"$1\"",
        "pageinfo-not-current": "Maaari lamang ipakita ang impormasyon para sa kasalukuyang rebisyon.",
        "pageinfo-header-basic": "Saligang kabatiran",
        "file-nohires": "Walang makuhang mas mataas na resolusyon (kalinawan).",
        "svg-long-desc": "Talaksang SVG, nasa mga bilang na $1 × $2 mga piksel, sukat ng talaksan: $3",
        "svg-long-desc-animated": "Animadong talaksang SVG, nasa mga bilang na $1 × $2 mga piksel, sukat ng talaksan: $3",
-       "show-big-image": "Orihinal na talaksan",
+       "show-big-image": "Orihinal na file",
        "show-big-image-preview": "Sukat ng paunang-tingin na ito: $1.",
        "show-big-image-other": "Ibang {{PLURAL:$2|resolusyon|mga resolusyon}}: $1.",
        "show-big-image-size": "$1 x $2 mga piksel",
        "exif-subjectlocation": "Lokasyon ng paksa",
        "exif-exposureindex": "Pang-antas o indeks ng pagkakalantad",
        "exif-sensingmethod": "Paraang pandama",
-       "exif-filesource": "Pinagmulang talaksan",
+       "exif-filesource": "Pinagmulang file",
        "exif-scenetype": "Uri ng tagpuan",
        "exif-customrendered": "Pagpoproseso ng pinasadyang larawan",
        "exif-exposuremode": "Modalidad ng paglalantad",
        "fileduplicatesearch": "Maghanap ng kaparehong mga talaksan",
        "fileduplicatesearch-summary": "Maghanap ng mga kaparehong mga talaksan sa baba ng kanyang halaga ng ''hash''.",
        "fileduplicatesearch-legend": "Maghanap ng mga kapareho",
-       "fileduplicatesearch-filename": "Pangalan ng talaksan:",
+       "fileduplicatesearch-filename": "Pangalan ng file:",
        "fileduplicatesearch-submit": "Hanapin",
        "fileduplicatesearch-info": "$1 × $2 pixel<br />Laki ng talaksan: $3<br />Uri ng MIME: $4",
        "fileduplicatesearch-result-1": "Walang katulad ang talaksan na \"$1\".",
        "tags": "Tanggap na mga tatak ng pagbabago",
        "tag-filter": "Pansala ng [[Special:Tags|tatak]]:",
        "tag-filter-submit": "Pansala",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Tatak|Mga tatak}}]]: $2)",
        "tags-title": "Mga tatak",
        "tags-intro": "Itinatala ng pahinang ito ang mga tatak na maaaring ipantatak ng sopwer sa isang pagbabago, at ang kanilang kahulugan.",
        "tags-tag": "Tatakan ang pangalan",
index f214131..1b7236a 100644 (file)
@@ -83,7 +83,8 @@
                        "Matma Rex",
                        "HakanIST",
                        "Imabadplayer",
-                       "İnternion"
+                       "İnternion",
+                       "Hbseren"
                ]
        },
        "tog-underline": "Bağlantıların altını çiz:",
        "blocklist-tempblocks": "Geçici engellemeleri gizle",
        "blocklist-addressblocks": "Tek IP engellemelerini gizle",
        "blocklist-rangeblocks": "Dizi bloklarını gizle",
-       "blocklist-timestamp": "Tarih damgası",
+       "blocklist-timestamp": "Tarih",
        "blocklist-target": "Hedef",
        "blocklist-expiry": "Bitiş tarihi",
-       "blocklist-by": "Engeli koyan hizmetli",
+       "blocklist-by": "Engeli veren hizmetli",
        "blocklist-params": "Engel parametreleri",
        "blocklist-reason": "Gerekçe",
        "ipblocklist-submit": "Ara",
        "noautoblockblock": "otomatik engelleme devre dışı bırakıldı",
        "createaccountblock": "hesap açımı engellendi",
        "emailblock": "e-posta engellendi",
-       "blocklist-nousertalk": "kendi tartışma sayfasını değiştiremez",
+       "blocklist-nousertalk": "kendi mesaj sayfasını değiştiremez",
        "ipblocklist-empty": "Engelleme listesi boş.",
        "ipblocklist-no-results": "İstenen IP adresi ya da kullanıcı adı engellenmedi.",
        "blocklink": "engelle",
        "block-log-flags-nocreate": "hesap yaratımı engellendi",
        "block-log-flags-noautoblock": "Otomatik engelleme iptal edildi",
        "block-log-flags-noemail": "e-posta engellendi",
-       "block-log-flags-nousertalk": "kendi tartışma sayfasını değiştiremez",
+       "block-log-flags-nousertalk": "kendi mesaj sayfasını değiştiremez",
        "block-log-flags-angry-autoblock": "gelişmiş oto-engelleme devrede",
        "block-log-flags-hiddenname": "kullanıcı adı gizli",
        "range_block_disabled": "Hizmetliler için aralık engellemesi oluşturma yeteneği devre dışı.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|revizyon|revizyon}} içe aktarıldı",
        "import-logentry-interwiki-detail": "$2 sayfasından $1 {{PLURAL:$1|revizyon|revizyon}} içe aktarıldı",
        "javascripttest": "JavaScript denemesi",
-       "javascripttest-pagetext-noframework": "Bu sayfa JavaScript testleri çalıştırmak için ayrılmıştır.",
-       "javascripttest-pagetext-unknownframework": "Bilinmeyen test çerçevesi \"$1\".",
        "javascripttest-pagetext-unknownaction": "Bilinmeyen eylem \"$1\".",
-       "javascripttest-pagetext-frameworks": "Lütfen aşağıdaki test çerçevelerinden birini seçin: $1",
-       "javascripttest-pagetext-skins": "Testleri koşmak için bir tema seçin:",
        "javascripttest-qunit-intro": "mediawiki.org üzerinden [$1 deneme belgelerine] bakınız.",
        "tooltip-pt-userpage": "{{GENDER:|Kullanıcı}} sayfanız",
        "tooltip-pt-anonuserpage": "IP adresine ait bir kullanıcı sayfasını düzenliyorsunuz",
        "version-libraries-description": "Açıklama",
        "version-libraries-authors": "Yazarlar",
        "redirect": "Dosya, kullanıcı, sayfa ya da revizyon kimliği ile yönlendirme",
-       "redirect-legend": "Bir dosya veya sayfaya yönlendirme",
        "redirect-summary": "Bu özel sayfa sizi bir dosya (dosya adı verilen), bir sayfa (bir revizyon ya da sayfa ID'si verilen) veya bir kullanıcı sayfasının (sayısal kullanıcı kimliği verilen) adresine yönlendirir. Kullanım: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], ya da  [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Git",
        "redirect-lookup": "Ara:",
        "revdelete-unrestricted": "hizmetliler için kaldırılmış kısıtlamalar",
        "logentry-block-block": "$1 {{GENDER:$2|engelledi}} {{GENDER:$4|$3}} engelleme süresi: $5 $6",
        "logentry-block-unblock": "$1 kullanıcısının {{GENDER:$2|engeli kaldırıldı}} {{GENDER:$4|$3}}",
-       "logentry-block-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} engelleme süresi $5 $6",
+       "logentry-block-reblock": "$1, {{GENDER:$4|$3}} kullanıcısının engellenme süresini $5 $6 olarak {{GENDER:$2|değiştirdi}}",
        "logentry-suppress-block": "{{GENDER:$4|$3}} $1 tarafından {{GENDER:$2|engellendi}} Zamanaşımı: $5 $6",
        "logentry-suppress-reblock": "$1 {{GENDER:$2|changed}} block settings for {{GENDER:$4|$3}} engelleme süresi $5 $6",
        "logentry-import-upload": "$1 dosya yükleme ile {{GENDER:$2|içe aktardı}}: $3",
        "special-characters-group-ipa": "UFA",
        "special-characters-group-symbols": "Simgeler",
        "special-characters-group-greek": "Yunan",
+       "special-characters-group-greekextended": "Genişletilmiş Yunanca",
        "special-characters-group-cyrillic": "Kiril",
        "special-characters-group-arabic": "Arap",
        "special-characters-group-arabicextended": "Genişletilmiş Arapça",
        "mw-widgets-titleinput-description-redirect": "$1'e yönlendirildi",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "çerez tabanlı oturumlar",
        "sessionprovider-nocookies": "Çerezler devre dışı olabilir. Çerkezlerin aktif olduğuna emin olun ve yeniden başlatin.",
-       "randomrootpage": "Rastgele kök sayfası"
+       "randomrootpage": "Rastgele kök sayfası",
+       "log-action-filter-block": "Blok türü:",
+       "log-action-filter-delete": "Silme türü:",
+       "log-action-filter-patrol": "Devriye türü:",
+       "log-action-filter-protect": "Koruma tipi:",
+       "log-action-filter-upload": "Yükleme türü:",
+       "log-action-filter-all": "Tümü",
+       "log-action-filter-block-block": "Blok",
+       "log-action-filter-block-reblock": "Blok değiştirme",
+       "log-action-filter-block-unblock": "Engeli kaldır",
+       "log-action-filter-delete-delete": "Sayfa silme",
+       "log-action-filter-delete-restore": "Sayfa silmeyi geri al",
+       "log-action-filter-delete-event": "Günlük silme",
+       "log-action-filter-delete-revision": "Gözden geçirmenin silinmesi",
+       "log-action-filter-patrol-patrol": "Manuel devriye",
+       "log-action-filter-patrol-autopatrol": "Otomatik devriye",
+       "log-action-filter-protect-protect": "Koruma",
+       "log-action-filter-protect-modify": "Koruma değişikliği",
+       "log-action-filter-protect-unprotect": "Korunmayan",
+       "log-action-filter-upload-upload": "Yeni yükleme",
+       "log-action-filter-upload-overwrite": "Yeniden yükle"
 }
index cd81bf5..98e7356 100644 (file)
        "createaccount-title": "{{SITENAME}}: теркәлү",
        "createaccount-text": "Кемдер, электрон почта адресыгызны күрсәтеп, {{SITENAME}} ($4) проектында «$3» серсүзе белән «$2» исемле хисап язмасы теркәде. Сез керергә һәм серсүзегезне үзгәртергә тиеш.\n\nХисап язмасы төзү хата булса, бу хатны онытыгыз.",
        "login-throttled": "Сез артык күп тапкыр керергә тырыштыгыз.\nЗинһар, яңадан кабатлаганчы, $1 көтүегез сорала.",
-       "login-abort-generic": "Системага уңышсыз керү очрагы",
+       "login-abort-generic": "Системага керү килеп чыкмады",
        "loginlanguagelabel": "Тел: $1",
        "suspicious-userlogout": "Сезнең эшчәнлекне бетерү соравыгыз кире кагылды, чөнки ул ялгыш браузер яисә кэшлаучы прокси аша җибәрелергэ мөмкин.",
        "pt-login": "Керү",
        "newpassword": "Яңа серсүз:",
        "retypenew": "Яңа серсүзне кабатлагыз:",
        "resetpass_submit": "Серсүз куеп керү",
-       "changepassword-success": "Серсүзегез уңышлы үзгәртелде!",
+       "changepassword-success": "Серсүзегез үзгәртелде!",
        "botpasswords": "Ботларның серсүзләре",
        "botpasswords-label-appid": "Бот исеме:",
        "botpasswords-label-create": "Төзү",
        "resetpass-no-info": "Бу битне карау өчен сез системага үз хисап язмагыз ярдәмендә керергә тиеш.",
        "resetpass-submit-loggedin": "Серсүзне үзгәртү",
        "resetpass-submit-cancel": "Кире кагу",
-       "resetpass-wrong-oldpass": "ЯлгÑ\8bÑ\88 Ñ\81еÑ\80Ñ\81үз.\nСез серсүзегезне үзгәрткән яисә яңа вакытлы серсүз сораткан булырга мөмкинсез.",
+       "resetpass-wrong-oldpass": "Ð¥Ó\99зеÑ\80ге Ñ\8fиÑ\81Ó\99 Ð²Ð°ÐºÑ\8bÑ\82лÑ\8b Ñ\81еÑ\80Ñ\81үз Ð´Ó©Ñ\80еÑ\81 Ñ\82үгел.\nСез серсүзегезне үзгәрткән яисә яңа вакытлы серсүз сораткан булырга мөмкинсез.",
        "resetpass-temp-password": "Вакытлы серсүз:",
        "passwordreset": "Серсүзне бетерү",
        "passwordreset-disabled": "Бу викида серсүз бетереп булмый",
        "continue-editing": "Үзгәртүне дәвам итү",
        "previewconflict": "Әлеге алдан карау битендә сакланачак текстның ничек күренәчәге күрсәтелә.",
        "session_fail_preview": "Кызганычка каршы сессия барышы югалы, шуңа  күрә без сезнең төзәтмәләрнегезне кабул итә алмадык.\n\nБәлки сез хисап язмагыздан чыккансыздыр. <strong>Зинһар, керүегез турында инаныгыз һәм тагын бер тапкыр кабатлап карагыз.</strong>\nӘгәрдә бу ысул ярдәм итмәсәс, системадан [[Special:UserLogout|чыгыгыз]] һәм яңадан керегез. Шулай ук сезгә браузерыгызның  cookies файлларын кабул итүне тикшерүне карап чыгуны тәкъдим итәбез.",
-       "session_fail_preview_html": "'''Кызганычка, сезнең сессия турында мәгълүматлар югалды. Нәтиҗәдә сервер үзгәртүләрегезне кабул итә алмый.'''\n\n''{{SITENAME}} чиста HTML кулланырга рөхсәт итә, ә бу үз чиратында JavaScript-атакалар оештыру өчен кулланылырга мөмкин. Шул сәбәпле сезнең өчен алдан карау мөмкинлеге ябык.''\n\n'''Әгәр сез үзгәртүне яхшы ният белән башкарасыз икән, тагын бер тапкыр кабатлап карагыз. Хата кабатланса, сайттан [[Special:UserLogout|чыгыгыз]] һәм яңадан керегез.'''",
+       "session_fail_preview_html": "<strong>Кызганычка каршы сервер сезнең төзәтмәләрне сессия югалу аркасында кабул итә алмады.</strong>\n\n<em>{{SITENAME}} чиста HTML кулланырга рөхсәт итә, ә бу үз чиратында JavaScript-хөҗүмнәр оештыру өчен кулланылырга мөмкин. Шул сәбәпле сезнең өчен алдан карау мөмкинлеге ябык.</em>\n\n<strong>Әгәр сез үзгәртүне яхшы ният белән башкарасыз икән, тагын бер тапкыр кабатлап карагыз. Хата кабатланса, сайттан [[Special:UserLogout|чыгыгыз]] һәм яңадан керегез.</strong>",
        "token_suffix_mismatch": "'''Сезнең үзгәртү кабул ителмәде.'''\nСәбәбе: браузерыгыз үзгәртү өлкәсендәге пунктуацияне дөрес күрсәтми, нәтиҗәдә текст бозылырга мөмкин.\nМондый хаталар аноним web-проксилар кулланганда килеп чыгарга мөмкин.",
        "edit_form_incomplete": "'''Төзәтү кырларының кайбер өлешләре серверга барып ирешмәде. Сезнең үзгәртүләр бозылмаганмы - игътибар белән тикшерегез һәм яңадан җибәреп карагыз.'''",
        "editing": "«$1» битен үзгәртү",
        "revdelete-suppress": "Мәгълүматлар идарәчеләрдән дә яшерелсен",
        "revdelete-log": "Сәбәп:",
        "revdelete-submit": "{{PLURAL:$1|1=сайланылган юрамага|сайланылган юрамаларга}} кулланырга",
-       "revdelete-success": "'''Версиянең күренүчәнлеге уңышлы рәвештә үзгәртелде'''",
+       "revdelete-success": "Юраманың күренүчәнлеге яңартылды.",
        "revdelete-failure": "'''Версиянең күренүчәнлеге үзгәртелә алмый:'''\n$1",
        "logdelete-success": "Вакыйганың күренүчәнлеге үзгәртелде.",
        "logdelete-failure": "'''Көндәлекнең күренүчәнлеге  куелмады:'''\n$1",
        "recentchanges-label-bot": "Бу үзгәртү бот белән эшләнгән",
        "recentchanges-label-unpatrolled": "Үзгәртүне әлегә тикшермәгәннәр",
        "recentchanges-label-plusminus": "Битнең зурлыгы шуның кадәрле байтка үзгәрде",
-       "recentchanges-legend-heading": "<strong>Аңлатма:&nbsp;</strong>",
+       "recentchanges-legend-heading": "<strong>Аңлатма:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (шулай ук [[Special:NewPages|яңа битләр исемлеген]] карагыз)",
        "recentchanges-submit": "Күрсәт",
        "rcnotefrom": "Астарак <strong>$3, $4</strong> өчен {{PLURAL:$5|үзгәртүләр күрсәтелгән}} (<strong>$1</strong> артык түгел).",
        "importnopages": "Импортлау өчен битләр юк.",
        "importlogpage": "Кертү көндәлеге",
        "javascripttest": "JavaScript тикшерү",
-       "javascripttest-pagetext-noframework": "Әлеге бит JavaScript тестларын ачу өчен ясалган.",
        "tooltip-pt-userpage": "{{GENDER:|Кулланучы}} битегез",
        "tooltip-pt-mytalk": "Бәхәс {{GENDER:|битегез}}",
        "tooltip-pt-preferences": "{{GENDER:|Көйләнмәләрегез}}",
        "creditspage": "Рәхмәтләр",
        "spamprotectiontitle": "Спам фильтры",
        "simpleantispam-label": "Анти-спам тикшерә.\nМоны <strong>ТУТЫРМАГЫЗ!</strong>",
+       "pageinfo-title": "«$1» буенча мәгълүмат",
        "pageinfo-header-basic": "Төп мәгълүмат",
        "pageinfo-header-edits": "Үзгәртүләр тарихы",
        "pageinfo-header-restrictions": "Битне яклау",
        "years": "{{PLURAL:$1|$1 ел}}",
        "ago": "$1 элек",
        "just-now": "яңа гына",
-       "hours-ago": "$1 cәгать элек",
-       "minutes-ago": "$1 минут элек",
+       "hours-ago": "$1 {{PLURAL:$1|cәгать}} элек",
+       "minutes-ago": "$1 {{PLURAL:$1|минут}} элек",
        "seconds-ago": "$1 {{PLURAL:$1|секунд}} элек",
        "monday-at": "дүшәмбе $1",
        "tuesday-at": "сишәмбе $1",
index e126367..78d3e9b 100644 (file)
@@ -64,7 +64,8 @@
                        "Translatemyname",
                        "Dars",
                        "Mix Gerder",
-                       "E.belykh"
+                       "E.belykh",
+                       "Visem"
                ]
        },
        "tog-underline": "Підкреслювання посилань:",
@@ -87,7 +88,7 @@
        "tog-previewontop": "Показувати попередній перегляд перед вікном редагування, а не після",
        "tog-previewonfirst": "Показувати попередній перегляд під час першого редагування",
        "tog-enotifwatchlistpages": "Повідомляти електронною поштою про зміну сторінки або файлу з мого списку спостереження",
-       "tog-enotifusertalkpages": "Ð\9fовÑ\96домлÑ\8fÑ\82и ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ð¿Ð¾Ñ\88Ñ\82оÑ\8e Ð¿Ñ\80о Ð·Ð¼Ñ\96ни Ð¼Ð¾Ñ\94Ñ\97 Ñ\81Ñ\82оÑ\80Ñ\96нки обговорення",
+       "tog-enotifusertalkpages": "Ð\9fовÑ\96домлÑ\8fÑ\82и ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ð¿Ð¾Ñ\88Ñ\82оÑ\8e Ð¿Ñ\80о Ð·Ð¼Ñ\96ни Ð½Ð° Ð¼Ð¾Ñ\97й Ñ\81Ñ\82оÑ\80Ñ\96нÑ\86Ñ\96 обговорення",
        "tog-enotifminoredits": "Надсилати мені електронного листа навіть при незначних редагуваннях сторінок та файлів",
        "tog-enotifrevealaddr": "Показувати мою поштову адресу в повідомленнях",
        "tog-shownumberswatching": "Показувати число користувачів, які додали сторінку до свого списку спостереження",
        "october-date": "$1 жовтня",
        "november-date": "$1 листопада",
        "december-date": "$1 грудня",
-       "period-am": "AM",
-       "period-pm": "PM",
+       "period-am": "ранку",
+       "period-pm": "пополудні",
        "pagecategories": "{{PLURAL:$1|1=Категорія|Категорії}}",
        "category_header": "Сторінки в категорії «$1»",
        "subcategories": "Підкатегорії",
        "category-empty": "''Ця категорія зараз порожня.''",
        "hidden-categories": "{{PLURAL:$1|1=Прихована категорія|Приховані категорії}}",
        "hidden-category-category": "Приховані категорії",
-       "category-subcat-count": "{{PLURAL:$2|ЦÑ\8f ÐºÐ°Ñ\82егоÑ\80Ñ\96Ñ\8f Ð¼Ð°Ñ\94 Ñ\82Ñ\96лÑ\8cки Ñ\82акÑ\83 Ð¿Ñ\96дкаÑ\82егоÑ\80Ñ\96Ñ\8e.|Ð\9fоказано $1 {{PLURAL:$1|пÑ\96дкаÑ\82егоÑ\80Ñ\96Ñ\8e Ð·|пÑ\96дкаÑ\82егоÑ\80Ñ\96Ñ\97 Ð·|пÑ\96дкаÑ\82егоÑ\80Ñ\96й Ñ\96з}} $2.}}",
+       "category-subcat-count": "{{PLURAL:$2|Ð\9fоказано $1 {{PLURAL:$1|пÑ\96дкаÑ\82егоÑ\80Ñ\96Ñ\8e Ð·|пÑ\96дкаÑ\82егоÑ\80Ñ\96Ñ\97 Ð·|пÑ\96дкаÑ\82егоÑ\80Ñ\96й Ñ\96з}} $2.|1=ЦÑ\8f ÐºÐ°Ñ\82егоÑ\80Ñ\96Ñ\8f Ð¼Ð°Ñ\94 Ñ\82Ñ\96лÑ\8cки Ñ\82акÑ\83 Ð¿Ñ\96дкаÑ\82егоÑ\80Ñ\96Ñ\8e.}}",
        "category-subcat-count-limited": "У цій категорії {{PLURAL:$1|$1 підкатегорія|$1 підкатегорії|$1 підкатегорій}}.",
        "category-article-count": "Показано $1 {{PLURAL:$1|сторінку|сторінки|сторінок}} цієї категорії (із $2).",
        "category-article-count-limited": "У цій категорії {{PLURAL:$1|$1 сторінка|$1 сторінки|$1 сторінок}}.",
        "noemail": "Для користувача \"$1\" не вказано адреси електронної пошти.",
        "noemailcreate": "Вам треба вказати правильну адресу електронної пошти",
        "passwordsent": "Новий пароль був надісланий на адресу електронної пошти, зазначену для \"$1\".\nБудь ласка, ввійдіть до системи після отримання пароля.",
-       "blocked-mailpassword": "РедагÑ\83ваннÑ\8f Ð· Ð²Ð°Ñ\88оÑ\97 IP-адÑ\80еÑ\81и Ð·Ð°Ð±Ð¾Ñ\80онено, Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð° Ñ\82акож Ñ\84Ñ\83нкÑ\86Ñ\96Ñ\8f Ð²Ñ\96дновленнÑ\8f Ð¿Ð°Ñ\80олÑ\8f, Ñ\89об Ð·Ð°Ð¿Ð¾Ð±Ñ\96гÑ\82и Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ\8fм.",
+       "blocked-mailpassword": "РедагÑ\83ваннÑ\8f Ð· Ð\92аÑ\88оÑ\97 IP-адÑ\80еÑ\81и Ð·Ð°Ð±Ð¾Ñ\80онено. Ð©Ð¾Ð± Ð·Ð°Ð¿Ð¾Ð±Ñ\96гÑ\82и Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ\8fм, Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð° Ñ\82акож Ñ\84Ñ\83нкÑ\86Ñ\96Ñ\8f Ð²Ñ\96дновленнÑ\8f Ð¿Ð°Ñ\80олÑ\8f Ð· Ñ\86Ñ\96Ñ\94Ñ\97 IP-адÑ\80еÑ\81и.",
        "eauthentsent": "На вказану адресу електронної пошти відправлено лист підтвердження.\nЩоб отримувати надалі будь-які повідомлення, необхідно підтвердити, що обліковий запис належить справді Вам, за процедурою, описаною в листі.",
        "throttled-mailpassword": "Листа для оновлення пароля вже було надіслано електронною поштою протягом {{PLURAL:$1|1=останньої години|останніх $1 годин}}.\nДля попередження зловживань дозволено надсилати тільки одного листа оновлення пароля за {{PLURAL:$1|годину|$1 години|$1 годин}}.",
        "mailerror": "Помилка надсилання пошти: $1",
        "botpasswords-insert-failed": "Не вдалось додати бота з іменем «$1». Можливо, він вже був доданий?",
        "botpasswords-update-failed": "Не вдалось оновити бота з іменем «$1». Можливо, він був видалений?",
        "botpasswords-created-title": "Пароль бота створено",
-       "botpasswords-created-body": "Пароль бота «$1» було створено.",
+       "botpasswords-created-body": "Пароль бота з ім'ям «$1» користувача «$2» було створено.",
        "botpasswords-updated-title": "Пароль бота оновлено",
-       "botpasswords-updated-body": "Пароль бота «$1» було оновлено.",
+       "botpasswords-updated-body": "Пароль бота з ім'ям «$1» користувача «$2» було оновлено.",
        "botpasswords-deleted-title": "Пароль бота видалено",
-       "botpasswords-deleted-body": "Пароль бота «$1» було видалено",
+       "botpasswords-deleted-body": "Пароль бота з ім'ям «$1» користувача «$2» було видалено",
        "botpasswords-newpassword": "Новий пароль для входу під <strong>$1</strong> — <strong>$2</strong>. <em>Запишіть його для подальшого використання.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider не доступний.",
        "botpasswords-restriction-failed": "Вхід не було здійснено через обмеження для паролю бота.",
        "prefs-watchlist": "Список спостереження",
        "prefs-editwatchlist": "Редагування списку спостереження",
        "prefs-editwatchlist-label": "Редагування елементів Вашого списку спостереження:",
-       "prefs-editwatchlist-edit": "Ð\9fеÑ\80еглÑ\8fд Ñ\96 Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ\8f Ð½Ð°Ð·Ð² Ð· Ð²ашого списку спостереження",
+       "prefs-editwatchlist-edit": "Ð\9fеÑ\80еглÑ\8fд Ñ\96 Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ\8f Ð½Ð°Ð·Ð² Ð· Ð\92ашого списку спостереження",
        "prefs-editwatchlist-raw": "Редагувати список спостереження як текст",
        "prefs-editwatchlist-clear": "Очистити список спостереження",
        "prefs-watchlist-days": "Кількість днів, що відображаються у списку спостережень:",
        "recentchangeslinked-page": "Назва сторінки:",
        "recentchangeslinked-to": "Показати зміни на сторінках, пов'язаних з даною",
        "recentchanges-page-added-to-category": "[[:$1]] Додано до категорії",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] та ще {{PLURAL:$2|$2 сторінку|$2 сторінки|$2 сторінок|1=одну сторінку}} було додано до категорії",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] та ще [[Special:WhatLinksHere/$1|{{PLURAL:$2|$2 сторінку|$2 сторінки|$2 сторінок|1=одну сторінку}}]] було додано до категорії",
        "recentchanges-page-removed-from-category": "[[:$1]] було вилучено з категорії",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] та ще {{PLURAL:$2|$2 сторінку|$2 сторінки|$2 сторінок|1=одну сторінку}} було вилучено з категорії",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] та ще [[Special:WhatLinksHere/$1|{{PLURAL:$2|$2 сторінку|$2 сторінки|$2 сторінок|1=одну сторінку}}]] було вилучено з категорії",
        "autochange-username": "Автоматичні редагування MediaWiki",
        "upload": "Завантажити файл",
        "uploadbtn": "Завантажити файл",
        "uploadstash-badtoken": "Не вдалося виконати вказану дію. Можливо, вичерпаний термін дії сесії редагування. Будь ласка, спробуйте ще раз.",
        "uploadstash-errclear": "Очищення файлів зазнало невдачі.",
        "uploadstash-refresh": "Оновити список файлів",
+       "uploadstash-thumbnail": "перегляд мініатюри",
        "invalid-chunk-offset": "Неприпустимий зсув фрагмента",
        "img-auth-accessdenied": "Відмовлено в доступі",
        "img-auth-nopathinfo": "Відсутній PATH_INFO.\nВаш сервер не налаштовано для передачі цих даних.\nМожливо, він працює на основі CGI та не підтримує img_auth.\nПерегляньте [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization Відкриття доступу до зображень]",
        "changecontentmodel-title-label": "Назва сторінки",
        "changecontentmodel-model-label": "Нова модель вмісту",
        "changecontentmodel-reason-label": "Причина:",
+       "changecontentmodel-submit": "Змінити",
        "changecontentmodel-success-title": "Модель вмісту було змінено",
        "changecontentmodel-success-text": "Тип вмісту сторінки [[:$1]] було змінено.",
        "changecontentmodel-cannot-convert": "Вміст сторінки [[:$1]] не можна перетворити на вміст типу $2.",
        "ipb-unblock": "Розблокувати користувача або IP-адресу",
        "ipb-blocklist": "Показати чинні блокування",
        "ipb-blocklist-contribs": "Внесок {{GENDER:$1|$1}}",
+       "ipb-blocklist-duration-left": "Залишилось $1",
        "unblockip": "Розблокувати IP-адресу",
        "unblockiptext": "Використовуйте подану нижче форму, щоб відновити можливість збереження з раніше заблокованої IP-адреси.",
        "ipusubmit": "Зняти це блокування",
        "import-logentry-upload-detail": "Імпортовано $1 {{PLURAL:$1|версія|версії|версій}}",
        "import-logentry-interwiki-detail": "Імпортовано $1 {{PLURAL:$1|версія|версії|версій}} з $2",
        "javascripttest": "Тестування JavaScript",
-       "javascripttest-pagetext-noframework": "Ця сторінка призначений для тестування JavaScript.",
-       "javascripttest-pagetext-unknownframework": "Невідоме середовище тестування \" $1 \".",
        "javascripttest-pagetext-unknownaction": "невідома дія \"$1\".",
-       "javascripttest-pagetext-frameworks": "Будь ласка, оберіть одне з наступних середовищ тестування: $1",
-       "javascripttest-pagetext-skins": "Виберіть оформлення сторінки запуску тесту:",
        "javascripttest-qunit-intro": "Переглянути [ $1  тестування документації] на mediawiki.org.",
        "tooltip-pt-userpage": "{{GENDER:|Ваша}} сторінка користувача",
        "tooltip-pt-anonuserpage": "Сторінка користувача для вашої IP-адреси",
        "version-libraries-description": "Опис",
        "version-libraries-authors": "Автори",
        "redirect": "Перенаправлення за файлом, користувачем, сторінкою, версією або ID журналу",
-       "redirect-legend": "Перенаправити на файл чи сторінку",
        "redirect-summary": "Ця спеціальна сторінка перенаправляє на файл (за поданою назвою файлу), сторінку (за поданим ID версії або сторінки), сторінку користувача (за поданим числовим ID користувача) або запис журлану (за поданим ID журналу). Використання: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]],[[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]] або [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Перейти",
        "redirect-lookup": "Шукати:",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|захистив|захистила}} $3 $4 [каскадно]",
        "logentry-protect-modify": "$1 {{GENDER:$2|змінив|змінила}} налаштування захисту $3 $4",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|змінив|змінила}} налаштування захисту $3 $4 [каскадно]",
-       "logentry-rights-rights": "$1 {{GENDER:$2|змінив|змінила}} членство в групах для $3 із $4 на $5",
+       "logentry-rights-rights": "$1 {{GENDER:$2|змінив|змінила}} членство в групах для {{GENDER:$3|$3}} із $4 на $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|змінив|змінила}} членство в групах для $3",
        "logentry-rights-autopromote": "$1 було автоматично переведено із $4 в $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|завантажив|завантажила}} $3",
        "api-error-unknownerror": "Невідома помилка: \"$1\".",
        "api-error-uploaddisabled": "Завантаження вимкнуто у цій вікі.",
        "api-error-verification-error": "Цей файл можливо пошкоджено, або він має неправильне розширення.",
+       "api-error-was-deleted": "Файл із цією назвою раніше було завантажено і згодом вилучено.",
        "duration-seconds": "$1 {{PLURAL:$1|секунда|секунди|секунд}}",
        "duration-minutes": "$1 {{PLURAL:$1|хвилина|хвилини|хвилин}}",
        "duration-hours": "$1 {{PLURAL:$1|година|години|годин}}",
        "special-characters-group-ipa": "МФА (IPA)",
        "special-characters-group-symbols": "Символи",
        "special-characters-group-greek": "Грецькі",
+       "special-characters-group-greekextended": "Розширена грецька",
        "special-characters-group-cyrillic": "Кирилиця",
        "special-characters-group-arabic": "Арабські",
        "special-characters-group-arabicextended": "Арабська розширена",
        "sessionprovider-generic": "сесій $1",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "сесій на основі кук",
        "sessionprovider-nocookies": "Куки можуть бути відключені. Переконайтеся, що у Вас включені cookies і почніть знову.",
-       "randomrootpage": "Випадкова коренева сторінка"
+       "randomrootpage": "Випадкова коренева сторінка",
+       "log-action-filter-block": "Тип блокування:",
+       "log-action-filter-delete": "Тип вилучення:",
+       "log-action-filter-patrol": "Тип патрулювання:",
+       "log-action-filter-protect": "Тип захисту:",
+       "log-action-filter-upload": "Тип завантаження:",
+       "log-action-filter-all": "Усі",
+       "log-action-filter-block-block": "Блокування",
+       "log-action-filter-block-reblock": "Зміна блокування",
+       "log-action-filter-block-unblock": "Розблокування",
+       "log-action-filter-delete-delete": "Видалення сторінки",
+       "log-action-filter-delete-restore": "Відновлення сторінки",
+       "log-action-filter-delete-event": "Вилучення журналу",
+       "log-action-filter-delete-revision": "Вилучення версії",
+       "log-action-filter-patrol-patrol": "Ручне патрулювання",
+       "log-action-filter-patrol-autopatrol": "Автоматичне патрулювання",
+       "log-action-filter-protect-protect": "Захист",
+       "log-action-filter-protect-modify": "Зміна захисту",
+       "log-action-filter-protect-unprotect": "Зняття захисту",
+       "log-action-filter-upload-upload": "Нове завантаження",
+       "log-action-filter-upload-overwrite": "Повторне завантаження"
 }
index 2a3c48f..eca9197 100644 (file)
@@ -11,7 +11,8 @@
                        "Xexdof",
                        "Arystanbek",
                        "6ahodir",
-                       "Таржимон"
+                       "Таржимон",
+                       "Ximik1991"
                ]
        },
        "tog-underline": "Havolalarning tagiga chizish:",
        "mytalk": "Munozara",
        "anontalk": "Ushbu IP-manzil munozarasi",
        "navigation": "Saytda harakatlanish",
-       "and": "&#32;va",
+       "and": "&nbsp;va",
        "qbfind": "Topish",
        "qbbrowse": "Koʻrib chiqish",
        "qbedit": "Tahrirlash",
index c840b1b..4ce72b4 100644 (file)
        "powersearch-togglelabel": "Kodvda:",
        "powersearch-toggleall": "Kaik",
        "powersearch-togglenone": "Ei ole nimidä",
+       "powersearch-remember": "Panda valičend muštho tulebiden ecmižiden täht",
        "search-external": "Irdecind",
        "searchdisabled": "{{SITENAME}} ecind om saubatud.\nTö voit nügüd' ectä Google'n turbiš.\nOtkat sil'mnägubale üks-se, miše {{SITENAME}}-saitan sädäimišt voib olda vanhtunuden.",
        "preferences": "Järgendused",
        "recentchanges-label-bot": "Necen redakcijan tegi bot",
        "recentchanges-label-unpatrolled": "Necidä redakcijad ei völ patruliruinugoi",
        "recentchanges-label-plusminus": "Suruden toižetamine baitoiš",
+       "recentchanges-legend-heading": "<strong>Legend:</strong>",
        "recentchanges-legend-newpage": "$1 - uz' lehtpol'",
        "rcnotefrom": "Alemba oma anttud toižetused '''$2'''-späi ( '''$1'''-hesai).",
        "rclistfrom": "Ozutada uded toižetused dataspäi $3 $2 augotaden",
index 3ac8d05..dc92a01 100644 (file)
        "viewhelppage": "Xem trang trợ giúp",
        "categorypage": "Xem trang thể loại",
        "viewtalkpage": "Xem trang thảo luận",
-       "otherlanguages": "Trong các ngôn ngữ khác",
+       "otherlanguages": "Trong ngôn ngữ khác",
        "redirectedfrom": "(đổi hướng từ $1)",
        "redirectpagesub": "Trang đổi hướng",
        "redirectto": "Đổi hướng đến:",
        "nocookieslogin": "{{SITENAME}} sử dụng cookie để đăng nhập thành viên. Bạn đã tắt cookie. Xin hãy kích hoạt rồi thử lại.",
        "nocookiesfornew": "Không thể mở tài khoản vì không thể xác nhận nguồn yêu cầu nó.\nHãy chắc chắn bạn đã bật lên cookie, làm mới trang này, và thử lại.",
        "noname": "Chưa nhập tên.",
-       "loginsuccesstitle": "Đăng nhập thành công",
+       "loginsuccesstitle": "Đã đăng nhập",
        "loginsuccess": "'''Bạn đã đăng nhập vào {{SITENAME}} với tên “$1”.'''",
        "nosuchuser": "Không có thành viên nào có tên “$1”.\nTên người dùng có phân biệt chữ hoa chữ thường.\nHãy kiểm tra lại chính tả, hoặc [[Special:UserLogin/signup|mở tài khoản mới]].",
        "nosuchusershort": "Không có thành viên nào có tên “$1”. Xin hãy kiểm tra lại chính tả.",
        "createaccount-title": "Tài khoản mới tại {{SITENAME}}",
        "createaccount-text": "Ai đó đã tạo một tài khoản với tên $2 tại {{SITENAME}} ($4). Mật khẩu của “$2” là “$3”. Bạn nên đăng nhập và đổi mật khẩu ngay bây giờ.\n\nXin hãy bỏ qua thông điệp này nếu tài khoản này không phải do bạn tạo ra.",
        "login-throttled": "Bạn đã hết quyền thử mật khẩu tài khoản này vì bạn đã nhập sai quá nhiều. Xin hãy đợi $1 rồi hãy thử lại.",
-       "login-abort-generic": "Thất bại khi đăng nhập",
+       "login-abort-generic": "Đăng nhập của bạn không thành công – bị hủy bỏ",
        "login-migrated-generic": "Tài khoản của bạn đã được hợp nhất, và tên đăng nhập của bạn không còn tồn tại trên wiki này.",
        "loginlanguagelabel": "Ngôn ngữ: $1",
        "suspicious-userlogout": "Đã bỏ qua yêu cầu đăng xuất bạn, hình như được gửi từ trình duyệt hoặc máy proxy nhớ đệm hư.",
        "newpassword": "Mật khẩu mới:",
        "retypenew": "Gõ lại:",
        "resetpass_submit": "Chọn mật khẩu và đăng nhập",
-       "changepassword-success": "Đã đổi mật khẩu thành công!",
+       "changepassword-success": "Mật khẩu của bạn đã được thay đổi.",
        "changepassword-throttled": "Bạn đã thử đăng nhập gần đây nhiều lần quá. Xin chờ $1 trước khi bạn thử lần nữa.",
        "botpasswords": "Mật khẩu Bot",
+       "botpasswords-summary": "<em>Mật khẩu bot</em> cho phép truy cập một tài khoản người dùng qua API mà không sử dụng thông tin chứng nhận chính của tài khoản. Các quyền người dùng có thể bị hạn chế khi đăng nhập dùng mật khẩu bot.\n\nNếu bạn không hiểu tại sao cần sử dụng mật khẩu bot, có lẽ bạn không nên sử dụng nó. Không ai bao giờ có lý do chính đáng để yêu cầu bạn tạo ra một mật khẩu bot và cung cấp nó cho họ.",
        "botpasswords-disabled": "Mật khẩu Bot bị vô hiệu hoá.",
        "botpasswords-no-central-id": "Để sử dụng mật khẩu bot, bạn phải đăng nhập vào một tài khoản tập trung.",
        "botpasswords-existing": "Mật khẩu bot hiện tại",
        "botpasswords-label-delete": "Xoá",
        "botpasswords-label-resetpassword": "Đặt lại mật khẩu",
        "botpasswords-label-grants": "Các quyền có liên quan:",
+       "botpasswords-help-grants": "Các lượt cấp phép cho phép truy cập các quyền người dùng mà một tài khoản đã có sẵn. Xem thêm thông tin trong [[Special:ListGrants|bảng cấp phép]].",
        "botpasswords-label-restrictions": "Hạn chế sử dụng:",
        "botpasswords-label-grants-column": "Cấp quyền",
        "botpasswords-bad-appid": "Bot có tên \"$1\" không hợp lệ.",
        "botpasswords-insert-failed": "Không thể thêm tên bot \"$1\". Nó đã được thêm vào chưa?",
        "botpasswords-update-failed": "Thất bại khi cập nhật bot có tên \"$1\". Có phải nó đã bị xóa?",
        "botpasswords-created-title": "Mật khẩu bot đã được tạo",
-       "botpasswords-created-body": "Mật khẩu bot \"$1\" đã được tạo thành công.",
+       "botpasswords-created-body": "Đã tạo mật khẩu cho bot “$1” của người dùng “$2”.",
        "botpasswords-updated-title": "Mật khẩu Bot đã được cập nhật",
-       "botpasswords-updated-body": "Mật khẩu bot \"$1\" đã được cập nhật thành công.",
+       "botpasswords-updated-body": "Đã cập nhật mật khẩu cho bot “$1” của người dùng “$2”.",
        "botpasswords-deleted-title": "Bot mật khẩu đã bị xóa",
-       "botpasswords-deleted-body": "Mật khẩu bot \"$1\" đã bị xóa.",
+       "botpasswords-deleted-body": "Đã xóa mật khẩu cho bot “$1” của người dùng “$2”.",
+       "botpasswords-newpassword": "Mật khẩu mới để đăng nhập như <strong>$1</strong> là <strong>$2</strong>. <em>Xin hãy ghi lại mật khẩu này để mai mốt tham khảo.</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider không có sẵn.",
        "botpasswords-restriction-failed": "Mật khẩu bot giới hạn ngăn chặn đăng nhập này.",
        "botpasswords-invalid-name": "Tên người dùng đã chỉ định không chứa dấu tách mật khẩu bot (\"$1\").",
        "resetpass-no-info": "Bạn phải đăng nhập mới có thể truy cập trực tiếp trang này.",
        "resetpass-submit-loggedin": "Thay đổi mật khẩu",
        "resetpass-submit-cancel": "Hủy bỏ",
-       "resetpass-wrong-oldpass": "Mật khẩu tạm hoặc mật khẩu hiện thời không hợp lệ.\nCó thể bạn đã thay đổi thành công mật khẩu của mình hoặc đã yêu cầu cung cấp một mật khẩu tạm mới.",
+       "resetpass-wrong-oldpass": "Mật khẩu tạm hoặc mật khẩu hiện thời không hợp lệ.\nCó thể bạn đã thay đổi mật khẩu của mình hoặc đã yêu cầu cung cấp một mật khẩu tạm mới.",
        "resetpass-recycled": "Xin vui lòng chọn một mật khẩu khác với mật khẩu hiện tại.",
        "resetpass-temp-emailed": "Bạn đã đăng nhập bằng mật khẩu tạm gửi qua thư điện tử. Để hoàn tất việc đăng nhập, bạn phải tạo lại mật khẩu mới tại đây:",
        "resetpass-temp-password": "Mật khẩu tạm:",
        "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:",
        "revdelete-submit": "Áp dụng vào {{PLURAL:$1|phiên bản|các phiên bản}} được chọn",
-       "revdelete-success": "'''Đã cập nhật thành công độ khả kiến của phiên bản.'''",
+       "revdelete-success": "Phiên bản Hiển thị đã cập nhật.",
        "revdelete-failure": "'''Không thể cập nhật khả năng hiển thị của phiên bản:'''\n$1",
-       "logdelete-success": "'''Khả năng nhìn thấy của sự kiện đã được thiết lập thành công.'''",
+       "logdelete-success": "Đã thiết lập khả năng nhìn thấy của nhật trình.",
        "logdelete-failure": "'''Không thể thiết lập khả năng hiện thị của nhật trình:'''\n$1",
        "revdel-restore": "đổi mức khả kiến",
        "pagehist": "Lịch sử trang",
        "mergehistory-empty": "Không thể trộn được sửa đổi nào.",
        "mergehistory-done": "$3 phiên bản của $1 đã được trộn vào [[:$2]].",
        "mergehistory-fail": "Không thể thực hiện được việc trộn lịch sử sửa đổi, vui lòng chọn lại trang cũng như thông số ngày giờ.",
+       "mergehistory-fail-bad-timestamp": "Dấu thời gian không hợp lệ.",
        "mergehistory-fail-invalid-source": "Trang nguồn không hợp lệ.",
        "mergehistory-fail-invalid-dest": "Trang đích không hợp lệ.",
+       "mergehistory-fail-no-change": "Kết hợp lịch sử đã không hợp nhất bất kỳ sửa đổi nào. Xin vui lòng kiểm tra lại trang và các thông số thời gian.",
        "mergehistory-fail-permission": "Không đủ quyền để hợp nhất lịch sử.",
        "mergehistory-fail-self-merge": "Trang nguồn và đích là giống nhau.",
+       "mergehistory-fail-timestamps-overlap": "Các phiên bản nguồn trùng với nhau hoặc dẫn sau các phiên bản đích.",
        "mergehistory-fail-toobig": "Không thể trộn lịch sử vì phải di chuyển $1 phiên bản và vượt quá giới hạn cho phép.",
        "mergehistory-no-source": "Trang nguồn $1 không tồn tại.",
        "mergehistory-no-destination": "Trang đích $1 không tồn tại.",
        "recentchangeslinked-page": "Tên trang:",
        "recentchangeslinked-to": "Hiện thay đổi tại những trang có liên kết đến trang này thay thế",
        "recentchanges-page-added-to-category": "[[:$1]] được xếp vào thể loại",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] và {{PLURAL:$2|một trang|$2 trang}} nữa được xếp vào thể loại",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] và [[Special:WhatLinksHere/$1|{{PLURAL:$2|một trang|$2 trang}} nữa]] được xếp vào thể loại",
        "recentchanges-page-removed-from-category": "[[:$1]] được gỡ khỏi thể loại",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] và {{PLURAL:$2|một trang|$2 trang}} nữa được gỡ khỏi thể loại",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] và [[Special:WhatLinksHere/$1|{{PLURAL:$2|một trang|$2 trang}} nữa]] được gỡ khỏi thể loại",
        "autochange-username": "MediaWiki thay đổi tự động",
        "upload": "Tải tập tin lên",
        "uploadbtn": "Tải tập tin lên",
        "uploaded-script-svg": "Tìm thấy phần tử “$1” có khả năng chạy kịch bản trong tập tin SVG được tải lên.",
        "uploaded-hostile-svg": "Tìm thấy CSS nguy hiểm trong phần tử style của tập tin SVG được tải lên.",
        "uploaded-event-handler-on-svg": "Không cho phép đặt thuộc tính xử lý sự kiện <code>$1=\"$2\"</code> trong tập tin SVG.",
-       "uploaded-href-unsafe-target-svg": "Tìm thấy href đến đích data: URI không an toàn <code>&lt;$1 $2=\"$3\"&gt;</code> trong tập tin SVG được tải lên.",
+       "uploaded-href-attribute-svg": "Các đặc tính href trong tập tin SVG chỉ được phép dẫn đến các trang http:// hoặc https://, nhưng gặp phải <code>&lt;$1 $2=\"$3\"&gt;</code>.",
+       "uploaded-href-unsafe-target-svg": "Tìm thấy href đến đích URI data: không an toàn <code>&lt;$1 $2=\"$3\"&gt;</code> trong tập tin SVG được tải lên.",
        "uploaded-animate-svg": "Tìm thấy thẻ “animate” có thể thay đổi href qua thuộc tính “from” <code>&lt;$1 $2=\"$3\"&gt;</code> trong tập tin SVG được tải lên.",
        "uploaded-setting-event-handler-svg": "Đã ngăn cản việc đặt thuộc tính xử lý sự kiện khi tìm thấy <code>&lt;$1 $2=\"$3\"&gt;</code> trong tập tin SVG được tải lên.",
        "uploaded-setting-href-svg": "Cấm sử dụng thẻ “set” để thêm thuộc tính “href” vào phần tử mẹ.",
        "upload-too-many-redirects": "URL có quá nhiều đổi hướng",
        "upload-http-error": "Xảy ra lỗi HTTP: $1",
        "upload-copy-upload-invalid-domain": "Không có sẵn các bản sao tải lên tại tên miền này.",
+       "upload-foreign-cant-upload": "Wiki này không được thiết lập để tải tập tin lên kho tập tin chung bên ngoài được chỉ định.",
        "upload-dialog-title": "Tải tập tin lên",
        "upload-dialog-button-cancel": "Hủy bỏ",
        "upload-dialog-button-done": "Xong",
        "upload-dialog-button-upload": "Tải lên",
        "upload-form-label-infoform-title": "Chi tiết",
        "upload-form-label-infoform-name": "Tên",
+       "upload-form-label-infoform-name-tooltip": "Một tiêu đề mô tả duy nhất cho tập tin, mà sẽ được dùng để làm một tên file. Bạn có thể sử dụng ngôn ngữ đơn giản với các dấu cách. Không bao gồm phần mở rộng của file.",
        "upload-form-label-infoform-description": "Miêu tả",
+       "upload-form-label-infoform-description-tooltip": "Miêu tả một cách ngắn gọn mỗi điều đáng kể về tác phẩm này.\nNếu là hình chụp, hãy nói đến những vật thể chính, cũng như tình hình, sự kiện, hay địa điểm của hình chụp.",
        "upload-form-label-usage-title": "Sử dụng",
        "upload-form-label-usage-filename": "Tên tập tin",
        "foreign-structured-upload-form-label-own-work": "Đây là tác phẩm của chính tôi",
        "uploadstash-badtoken": "Tác vụ bị thất bại, có lẽ vì thông tin đăng nhập của bạn đã hết hạn. Hãy thử lại.",
        "uploadstash-errclear": "Việc dọn sạch các tập tin bị thất bại.",
        "uploadstash-refresh": "Làm mới danh sách tập tin",
+       "uploadstash-thumbnail": "xem hình thu nhỏ",
        "invalid-chunk-offset": "Khúc lệch (chunk offset) không hợp lệ",
        "img-auth-accessdenied": "Không cho phép truy cập",
        "img-auth-nopathinfo": "Thiếu PATH_INFO.\nMáy chủ của bạn không được thiết lập để truyền thông tin này.\nCó thể do nó dựa trên CGI và không hỗ trợ img_auth.\nXem [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization hướng dẫn điều khiển truy cập hình ảnh].",
        "apisandbox-fullscreen": "Mở rộng bảng điều khiển",
        "apisandbox-fullscreen-tooltip": "Mở rộng bảng sandbox để điền vào cửa sổ trình duyệt.",
        "apisandbox-unfullscreen": "Hiển thị trang",
+       "apisandbox-unfullscreen-tooltip": "Thu nhỏ bảng điều khiển sandbox, do đó các linh kiện chuyển hướng MediaWiki sẽ được kích hoạt.",
        "apisandbox-submit": "Yêu cầu",
        "apisandbox-reset": "Tẩy trống",
        "apisandbox-retry": "Thử lại",
        "apisandbox-loading": "Đang tải thông tin cho mô-đun API \"$1\"...",
+       "apisandbox-load-error": "Một lỗi xuất hiện khi tải thông tin cho mô-đun API \"$1\": $2",
        "apisandbox-no-parameters": "Mô-đun API này không có thông số.",
        "apisandbox-helpurls": "Các đường dẫn trợ giúp",
        "apisandbox-examples": "Các ví dụ",
        "apisandbox-dynamic-parameters-add-label": "Thêm tham số:",
        "apisandbox-dynamic-parameters-add-placeholder": "Tên tham số",
        "apisandbox-dynamic-error-exists": "Một tham số có tên \"$1\" đã tồn tại.",
+       "apisandbox-deprecated-parameters": "Tham số bị phản đối",
        "apisandbox-fetch-token": "Tự động điền token này",
        "apisandbox-submit-invalid-fields-title": "Một số field là không hợp lệ",
+       "apisandbox-submit-invalid-fields-message": "Xin vui lòng sửa các miền được đánh dấu và thử lại.",
        "apisandbox-results": "Kết quả",
        "apisandbox-sending-request": "Đang gửi yêu cầu API...",
        "apisandbox-loading-results": "Nhận kết quả API...",
        "apisandbox-results-error": "Một lỗi xuất hiện khi tải các đáp ứng truy vấn API: $1.",
        "apisandbox-request-url-label": "URL của yêu cầu:",
-       "apisandbox-request-time": "Thời gian yêu cầu: {{PLURAL:$1|$1 ms}}",
+       "apisandbox-request-time": "Thời gian yêu cầu: $1 ms",
+       "apisandbox-results-fixtoken": "Sửa lại dấu hiệu và gửi lại",
+       "apisandbox-results-fixtoken-fail": "Thất bại khi lấy dấu hiệu “$1”.",
        "apisandbox-alert-page": "Các miền trên Trang này là không hợp lệ.",
+       "apisandbox-alert-field": "Giá trị của miền này là không hợp lệ.",
        "booksources": "Nguồn sách",
        "booksources-search-legend": "Tìm kiếm nguồn sách",
        "booksources-search": "Tìm kiếm",
        "listgrouprights-namespaceprotection-header": "Hạn chế không gian tên",
        "listgrouprights-namespaceprotection-namespace": "Không gian tên",
        "listgrouprights-namespaceprotection-restrictedto": "Quyền cho phép người dùng sửa đổi",
+       "listgrants": "Cấp phép",
+       "listgrants-summary": "Danh sách sau có các lượt cấp phép và thông tin về quyền truy cập quyền người dùng. Những người dùng có thể cho phép các ứng dụng sử dụng tài khoản của họ, các quyền được hạn chế tùy theo người dùng cấp phép cho ứng dụng. Một ứng dụng hoạt động nhân danh người dùng thực sự chỉ có thể sử dụng các quyền mà người dùng thật có.\nCó thể có [[{{MediaWiki:Listgrouprights-helppage}}|thêm thông tin]] về các quyền nói riêng.",
        "listgrants-grant": "Cấp phép",
        "listgrants-rights": "Quyền lợi",
        "trackingcategories": "Thể loại phần mềm",
        "changecontentmodel-title-label": "Tên trang",
        "changecontentmodel-model-label": "Kiểu nội dung mới",
        "changecontentmodel-reason-label": "Lý do:",
+       "changecontentmodel-submit": "Thay đổi",
        "changecontentmodel-success-title": "Kiểu nội dung đã thay đổi",
        "changecontentmodel-success-text": "Kiểu nội dung của [[:$1]] đã được thay đổi.",
        "changecontentmodel-cannot-convert": "Không thể chuyển đổi nội dung [[:$1]] thành nội dung dưới dạng $2.",
        "changecontentmodel-nodirectediting": "Kiểu nội dung $1 không hỗ trợ sửa đổi trực tiếp",
        "log-name-contentmodel": "Nhật trình thay đổi kiểu nội dung",
        "log-description-contentmodel": "Sự kiện có liên quan đến kiểu nội dung của trang.",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2}}đã tạo trang $3 với mô hình nội dung không mặc định “$5”",
        "logentry-contentmodel-change": "$1 {{GENDER:$2}}đã thay đổi kiểu nội dung của trang $3 từ “$4” thành “$5”",
        "logentry-contentmodel-change-revertlink": "lùi lại",
        "logentry-contentmodel-change-revert": "lùi lại",
        "import-nonewrevisions": "Không nhập phiên bản nào (tất cả các phiên bản đều đã có sẵn hoặc bị bỏ qua do lỗi).",
        "xml-error-string": "$1 tại dòng $2, cột $3 (byte $4): $5",
        "import-upload": "Tải lên dữ liệu XML",
-       "import-token-mismatch": "Mất dữ liệu phiên làm việc. Xin hãy thử lại lần nữa.",
+       "import-token-mismatch": "Mất dữ liệu phiên làm việc.\n\nCó thể bạn đã được đăng xuất. <strong>Xin hãy xác nhận rằng bạn vẫn được đăng nhập và thử lại.</strong>\nNếu vẫn không được, hãy thử [[Special:UserLogout|đăng xuất]] rồi đăng nhập lại, và kiểm tra rằng trình duyệt của bạn cho phép các cookie của trang Web này.",
        "import-invalid-interwiki": "Không thể nhập trang từ wiki được chỉ định.",
        "import-error-edit": "Trang “$1” không được nhập tại vì bạn không được phép sửa đổi nó.",
        "import-error-create": "Trang “$1” không được nhập tại vì bạn không được phép tạo ra nó.",
        "tooltip-feed-rss": "Nguồn cấp RSS của trang này",
        "tooltip-feed-atom": "Nguồn cấp Atom của trang này",
        "tooltip-t-contributions": "Danh sách đóng góp của {{GENDER:$1|người này}}",
-       "tooltip-t-emailuser": "Gửi thư cho người này",
+       "tooltip-t-emailuser": "Gửi thư cho {{GENDER:$1|người dùng này}}",
        "tooltip-t-info": "Thêm chi tiết về trang này",
        "tooltip-t-upload": "Tải hình ảnh hoặc tập tin lên",
        "tooltip-t-specialpages": "Danh sách các trang đặc biệt",
        "lastmodifiedatby": "Trang này được $3 cập nhật lần cuối lúc $2 $1.",
        "othercontribs": "Dựa trên công trình của $1.",
        "others": "những người khác",
-       "siteusers": "{{PLURAL:$2|Thành viên|Các thành viên}} $1 của {{SITENAME}}",
+       "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|người dùng}}|users}} $1",
        "anonusers": "{{PLURAL:$2|người dùng|những người dùng}} vô danh $1 tại {{SITENAME}}",
        "creditspage": "Trang ghi nhận đóng góp",
        "nocredits": "Không có thông tin ghi nhận đóng góp cho trang này.",
        "pageinfo-category-files": "Số tập tin",
        "markaspatrolleddiff": "Đánh dấu tuần tra",
        "markaspatrolledtext": "Đánh dấu tuần tra trang này",
+       "markaspatrolledtext-file": "Đánh dấu phiên bản fiel này là đã kiểm tra",
        "markedaspatrolled": "Đã đánh dấu tuần tra",
        "markedaspatrolledtext": "Phiên bản được chọn của [[:$1]] đã được đánh dấu tuần tra.",
        "rcpatroldisabled": "“Thay đổi gần đây” của các trang tuần tra không bật",
        "newimages-legend": "Bộ lọc",
        "newimages-label": "Tên tập tin (hoặc một phần tên):",
        "newimages-showbots": "Xem các tập tin do bot tải lên",
+       "newimages-hidepatrolled": "Ẩn tập tin tải lên đã tuần tra",
        "noimages": "Chưa có hình.",
        "ilsubmit": "Tìm kiếm",
        "bydate": "theo ngày",
        "exif-compression-34712": "JPEG 2000",
        "exif-copyrighted-true": "Dưới bản quyền",
        "exif-copyrighted-false": "Cờ bản quyền không được đặt",
+       "exif-photometricinterpretation-0": "Trắng đen (trắng là 0)",
        "exif-photometricinterpretation-1": "Trắng đen (đen là 0)",
        "exif-photometricinterpretation-2": "RGB",
+       "exif-photometricinterpretation-3": "Bảng màu",
+       "exif-photometricinterpretation-4": "Mặt nạ trong suốt",
+       "exif-photometricinterpretation-5": "Riêng rẽ (có lẽ CMYK)",
+       "exif-photometricinterpretation-9": "CIE L*a*b* (mã hóa Hiệp hội Màu sắc Quốc tế)",
+       "exif-photometricinterpretation-10": "CIE L*a*b* (mã hóa Liên minh Viễn thông Quốc tế)",
+       "exif-photometricinterpretation-32803": "Dãy bộ lọc màu sắc",
+       "exif-photometricinterpretation-34892": "Thô tuyến",
        "exif-unknowndate": "Không biết ngày",
        "exif-orientation-1": "Thường",
        "exif-orientation-2": "Lộn ngược theo phương ngang",
        "exif-orientation-8": "Quay 90° bên phải",
        "exif-planarconfiguration-1": "định dạng thấp",
        "exif-planarconfiguration-2": "định dạng phẳng",
+       "exif-xyresolution-i": "$1 điểm/inch",
+       "exif-xyresolution-c": "$1 điểm/cm",
        "exif-colorspace-65535": "Chưa hiệu chỉnh",
        "exif-componentsconfiguration-0": "không tồn tại",
        "exif-exposureprogram-0": "Không chỉ định",
        "scarytranscludefailed-httpstatus": "[Truy xuất bản mẫu $1 bị thất bại: HTTP $2]",
        "scarytranscludetoolong": "[Địa chỉ URL quá dài]",
        "deletedwhileediting": "'''Cảnh báo''': Trang này đã bị xóa sau khi bắt đầu sửa đổi!",
-       "confirmrecreate": "Thành viên [[User:$1|$1]] ([[User talk:$1|thảo luận]]) đã xóa trang này sau khi bạn bắt đầu sửa đổi trang với lý do:\n: ''$2''\nXin hãy xác nhận bạn thực sự muốn tạo lại trang này.",
+       "confirmrecreate": "Thành viên [[User:$1|$1]] ([[User talk:$1|thảo luận]]) đã xóa trang này sau khi bạn bắt đầu sửa đổi trang với lý do:\n: <em>$2</em>\nXin hãy xác nhận bạn thực sự muốn tạo lại trang này.",
        "confirmrecreate-noreason": "Người dùng [[User:$1|$1]] ([[User talk:$1|talk]]) xóa trang này sau khi bạn bắt đầu sửa đổi nó. Bạn có chắc chắn muốn tạo lại trang này không?",
        "recreate": "Tạo ra lại",
+       "unit-pixel": "điểm ảnh",
        "confirm_purge_button": "Làm tươi",
        "confirm-purge-top": "Làm sạch vùng nhớ đệm của trang này?",
        "confirm-purge-bottom": "Làm mới một trang sẽ giúp xóa bộ đệm và buộc hiển thị phiên bản gần nhất.",
        "version-libraries-authors": "Tác giả",
        "redirect": "Đổi hướng đến tập tin, người dùng, trang, hoặc ID đăng nhập",
        "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 hoặc số trang đượ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}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], hoặc [[{{#Special:Redirect}}/user/101]].",
+       "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 hoặc số trang được cho vào), trang cá nhân (theo số thành viên), hoặc mục nhật trình (theo số mục nhật trình). Cách sử dụng: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], hoặc [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Đi",
        "redirect-lookup": "Tra cứu:",
        "redirect-value": "Giá trị:",
        "redirect-page": "Số trang",
        "redirect-revision": "Số phiên bản trang",
        "redirect-file": "Tên tập tin",
+       "redirect-logid": "Số mục nhật trình",
        "redirect-not-exists": "Không tìm thấy giá trị",
        "fileduplicatesearch": "Tìm kiếm các tập tin trùng lắp",
        "fileduplicatesearch-summary": "Tìm kiếm các bản sao y hệt với tập tin khác, theo giá trị băm của nó.",
        "tags-delete-not-allowed": "Thẻ được định nghĩa bởi một mở rộng không thể bị xóa trừ khi mở rộng đặc biệt cho phép điều đó xảy ra.",
        "tags-delete-not-found": "Thẻ “$1” không tồn tại.",
        "tags-delete-too-many-uses": "Thẻ “$1” được áp dụng cho hơn $2 phiên bản, có nghĩa là nó không thể bị xóa.",
-       "tags-delete-warnings-after-delete": "Thẻ “$1” bị xóa thành công, nhưng gặp {{PLURAL:$2|cảnh báo|các cảnh báo}} sau:",
+       "tags-delete-warnings-after-delete": "Thẻ “$1” đã được xóa thành công, nhưng gặp phải {{PLURAL:$2|cảnh báo|các cảnh báo}} sau:",
        "tags-activate-title": "Kích hoạt thẻ",
        "tags-activate-question": "Bạn sắp sửa kích hoạt thẻ “$1”.",
        "tags-activate-reason": "Lý do:",
        "expand_templates_generate_xml": "Xem cây phân tích XML",
        "expand_templates_generate_rawhtml": "Hiển thị HTML thô",
        "expand_templates_preview": "Xem trước",
-       "expand_templates_preview_fail_html": "<em>{{SITENAME}} cho phép mã nguồn HTML thô và dữ liệu phiên bị mất, nên bản xem trước bị ẩn để tránh tấn công JavaScript.</em>\n\n<strong>Nếu bạn thực sự muốn xem trước mã nguồn này, xin hãy thử lại nữa.</strong>\nNếu vẫn không được, hãy thử [[Special:UserLogout|đăng xuất]] rồi đăng nhập lại.",
+       "expand_templates_preview_fail_html": "<em>{{SITENAME}} cho phép mã nguồn HTML thô và dữ liệu phiên bị mất, nên bản xem trước bị ẩn để tránh tấn công JavaScript.</em>\n\n<strong>Nếu bạn thực sự muốn xem trước mã nguồn này, xin hãy thử lại nữa.</strong>\nNếu vẫn không được, hãy thử [[Special:UserLogout|đăng xuất]] rồi đăng nhập lại, và kiểm tra rằng trình duyệt của bạn cho phép các cookie của trang Web này.",
        "expand_templates_preview_fail_html_anon": "<em>{{SITENAME}} cho phép mã nguồn HTML thô và dữ liệu phiên bị mất, nên bản xem trước bị ẩn để tránh tấn công JavaScript.</em>\n\n<strong>Nếu bạn thực sự muốn xem trước mã nguồn này, xin hãy thử lại nữa.</strong>\nNếu vẫn không được, hãy [[Special:UserLogin|đăng nhập]] và thử lại lần nữa.",
+       "expand_templates_input_missing": "Bạn phải cung cấp văn bản nhập.",
        "pagelanguage": "Thay đổi ngôn ngữ của trang",
        "pagelang-name": "Trang",
        "pagelang-language": "Ngôn ngữ",
        "mediastatistics": "Thống kê phương tiện",
        "mediastatistics-summary": "Thống kê về các kiểu tập tin đã tải lên. Bảng này chỉ liệt kê phiên bản mới nhất của các tập tin. Các phiên bản cũ hoặc các phiên bản bị xóa được bỏ qua.",
        "mediastatistics-nbytes": "$1 byte ($2; $3%)",
-       "mediastatistics-bytespertype": "Tổng kích thước tập tin của phần này: $1 byte.",
-       "mediastatistics-allbytes": "Tổng kích thước của tất cả các tập tin: $1 byte.",
+       "mediastatistics-bytespertype": "Tổng kích thước tập tin của phần này: $1 byte ($2; $3%).",
+       "mediastatistics-allbytes": "Tổng kích thước của tất cả các tập tin: $1 byte ($2).",
        "mediastatistics-table-mimetype": "Kiểu MIME",
        "mediastatistics-table-extensions": "Phần mở rộng có thể",
        "mediastatistics-table-count": "Số tập tin",
        "mw-widgets-titleinput-description-redirect": "đổi hướng đến $1",
        "api-error-blacklisted": "Xin vui lòng chọn một tên khác miêu tả đầy đủ.",
        "sessionmanager-tie": "Không thể kết hợp nhiều yêu cầu xác thực loại: $1.",
+       "sessionprovider-generic": "phiên $1",
+       "sessionprovider-mediawiki-session-cookiesessionprovider": "phiên dựa trên cookie",
        "sessionprovider-nocookies": "Cookie có thể bị vô hiệu hóa. Đảm bảo bạn đã bật cookie và bắt đầu một lần nữa.",
        "randomrootpage": "Trang gốc ngẫu nhiên"
 }
index 20ee5aa..898a3df 100644 (file)
@@ -14,6 +14,7 @@
        "tog-hideminor": "Èn nén mostrer les dierins candjmints mineurs",
        "tog-hidepatrolled": "Èn nén mostrer les candjmints ddja patrouyîs",
        "tog-newpageshidepatrolled": "Èn nén mostrer el djivêye des novelès pådjes les cenes dedja patrouyeyes",
+       "tog-hidecategorization": "Èn nén mostrer les categorijhaedjes des pådjes",
        "tog-extendwatchlist": "Ragrandi l' djivêye po mostrer tos les candjmints, nén seulmint les dierins",
        "tog-usenewrc": "Relére par pådje dins les dierins candjmints et l' djivêye des shuvous (i fåt JavaScript)",
        "tog-numberheadings": "Limerotaedje otomatike des tites",
@@ -34,7 +35,7 @@
        "tog-shownumberswatching": "Mostrer l' nombe d' uzeus ki shuvèt l' pådje",
        "tog-oldsig": "Siné pol moumint:",
        "tog-fancysig": "Sinateure avou do tecse wiki (sins loyén otomatike)",
-       "tog-uselivepreview": "Eployî l' prévoeyaedje abeye (JavaScript) (Esperimintå)",
+       "tog-uselivepreview": "Eployî l' préveyaedje abeye",
        "tog-forceeditsummary": "M' advierti cwand dji lai vude on rascourti",
        "tog-watchlisthideown": "Èn nén mostrer les candjmints da minne",
        "tog-watchlisthidebots": "Èn nén mostrer les candjmints des robots",
@@ -45,6 +46,7 @@
        "tog-ccmeonemails": "M' evoyî ene copeye des emiles ki dj' evoye ås ôtes",
        "tog-diffonly": "Èn nén håyner l' contnou del pådje pa dzo l' pådje des diferinces",
        "tog-showhiddencats": "Mostrer les categoreyes mucheyes",
+       "tog-norollbackdiff": "Èn nén håyner les diferinces après on disfijhaedje",
        "tog-useeditwarning": "M' advierti cwand dji cwite ene pådje k' a des candjmints nén schapés",
        "underline-always": "Tofer",
        "underline-never": "Måy",
        "oct": "oct",
        "nov": "nôv",
        "dec": "dec",
+       "january-date": "$1 di djanvî",
+       "february-date": "$1 di fevrî",
+       "march-date": "$1 di måss",
+       "april-date": "$1 d' avri",
+       "may-date": "$1 di may",
+       "june-date": "$1 di djun",
+       "july-date": "$1 di djulete",
+       "august-date": "$1 d' awousse",
+       "september-date": "$1 di setimbe",
+       "october-date": "$1 d' octôbe",
+       "november-date": "$1 di nôvimbe",
+       "december-date": "$1 di decimbe",
        "pagecategories": "{{PLURAL:$1|Categoreye|Categoreyes}}",
        "category_header": "Årtikes el categoreye «$1»",
        "subcategories": "Dizo-categoreyes",
        "newwindow": "(drovant en on novea purnea)",
        "cancel": "Rinoncî",
        "moredotdotdot": "Co dpus...",
-       "mypage": "Mi pådje",
+       "mypage": "Pådje",
        "mytalk": "Mi copinaedje",
-       "anontalk": "Pådje di copene po ciste adresse IP",
+       "anontalk": "Copinaedje",
        "navigation": "Naiviaedje",
        "and": "&#32;eyet",
        "qbfind": "Trover",
        "actions": "Accions",
        "namespaces": "Espåces di lomaedje",
        "variants": "Variantes",
+       "navigation-heading": "Menu d' naiviaedje",
        "errorpagetitle": "Aroke",
        "returnto": "Rivni al pådje «$1».",
        "tagline": "Èn årtike di {{SITENAME}}.",
        "permalink": "Hårdêye viè cisse modêye ci",
        "print": "Imprimer",
        "view": "Vey",
+       "view-foreign": "Vey so $1",
        "edit": "Candjî",
        "create": "Ahiver",
        "editthispage": "Candjî l' pådje",
        "articlepage": "Vey l' årtike",
        "talk": "Copene",
        "views": "Vuwes",
-       "toolbox": "Boesse ås usteyes",
+       "toolbox": "Usteyes",
        "userpage": "Vey li pådje di l' uzeu",
        "projectpage": "Vey li pådje do pordjet",
        "imagepage": "Vey li pådje do fitchî",
        "pool-errorunknown": "Aroke nén cnoxhowe",
        "aboutsite": "Åd fwait di {{SITENAME}}",
        "aboutpage": "Project:Åd fwait",
-       "copyright": "Li contnou est dizo l' $1.",
+       "copyright": "Li contnou est dzo l' licince $1 a moens k' ça soeye dit ôtrumint.",
        "copyrightpage": "{{ns:project}}:Abondroets",
        "currentevents": "Actouwålités",
        "currentevents-url": "Project:Actouwålités",
        "edithelp": "Aidance",
+       "helppage-top-gethelp": "Aidance",
        "mainpage": "Mwaisse pådje",
        "mainpage-description": "Mwaisse pådje",
        "portal": "Inte di nozôtes",
        "portal-url": "Project:Inte di nozôtes",
        "badaccess": "Åk n' a nén stî avou les permissions",
+       "badaccess-groups": "L' accion ki vos avoz dmandé est limitêye ås uzeus {{PLURAL:$2|do groupe|des groupes}}: $1.",
        "versionrequired": "I vs fåt l' modêye $1 di MediaWiki",
        "versionrequiredtext": "I vs fåt l' modêye $1 di MediaWiki po-z eployî cisse pådje ci. Loukîz [[Special:Version|al pådje des modêyes]]",
        "ok": "'l est bon",
        "retrievedfrom": "Prin del pådje «$1»",
        "youhavenewmessages": "Vos avoz des $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Vos avoz}} $1 {{PLURAL:$3|d' èn ôte uzeu|di $3 ôtes uzeus}} ($2).",
+       "youhavenewmessagesmanyusers": "Vous avoz $1 di bråmint d' uzeus ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|on novea messaedje|999=noveas messaedjes}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|dierin candjmint|999=dierins candjmints}}",
        "youhavenewmessagesmulti": "Vos avoz des noveas messaedjes so $1",
        "editsection": "candjî",
        "editold": "candjî",
        "hidetoc": "catchî",
        "collapsible-collapse": "erôler",
        "collapsible-expand": "diswalper",
+       "confirmable-confirm": "Estoz vs {{GENDER:$1|seur|seure}}?",
+       "confirmable-yes": "Oyi",
+       "confirmable-no": "Neni",
        "thisisdeleted": "Vey ou rapexhî $1?",
        "viewdeleted": "Vey $1?",
        "restorelink": "{{PLURAL:$1|on candjmint disfacé|$1 candjmints disfacés}}",
        "nstab-template": "Modele",
        "nstab-help": "Aidance",
        "nstab-category": "Categoreye",
+       "mainpage-nstab": "Mwaisse pådje",
        "nosuchaction": "Nole sifwaite accion",
        "nosuchactiontext": "L' accion specifieye pal hårdêye n' est nén ricnoxhowe på wiki.\nMotoit ki vos avoz må scrît l' hårdêye ou shuvou on cron loyén.\nÇa pôreut eto esse on bug do programe eployî pa {{SITENAME}}.",
        "nosuchspecialpage": "Nole sifwaite pådje",
        "nospecialpagetext": "Vos avoz dmandé ene pådje sipeciåle nén valide, po ene djivêye des pådjes sipeciåles valides, loukîz a [[Special:SpecialPages]].",
        "error": "Aroke",
        "databaseerror": "Åk n' a nén stî avou l' båze di dnêyes",
+       "databaseerror-error": "Aroke: $1",
        "laggedslavemode": "Asteme: I s' pout ki l' pådje n' åye nén co les dierins candjmints.",
        "readonly": "Li båze di dnêyes est aclawêye",
        "missing-article": "Li båze di dnêyes n' a nén trové l' tecse d' ene pådje k' åreut dvou esse trovêye, lomêye «$1» $2.\n\nÇoula arive cwand on shût on loyén po ene diferince k' est houte ou viè l' istwere d' ene pådej disfacêye.\n\nSi c' est nén çoula, motoit k' vos avoz trové on bug dins l' programe.\nAdon dijhoz l' a on [[Special:ListUsers/sysop|manaedjeu]], sins rovyî d' mete li hårdêye (URL) ki mostere l' aroke.",
        "cannotdelete": "Dji n' sai disfacer l' pådje ou l' fitchî «$1».\nÇa s' pôreut k' ene ôte sakî l' a ddja disfacé.",
        "cannotdelete-title": "Dji n' sai disfacer l' pådje «$1»",
        "badtitle": "Måva tite",
-       "badtitletext": "Li tite del pådje dimandêye n' esteut nén valide, il estet vude, oudonbén c' esteut on cron loyén eterlingaedje ou eterwiki. Ça s' pout k' il åye onk ou sacwants caracteres ki n' polèt nén esse eployîs dins les tites.",
+       "badtitletext": "Li tite del pådje dimandêye n' esteut nén valide, il esteut vude, oudonbén c' esteut on cron loyén eterlingaedje ou eterwiki.\nÇa s' pout k' il åye onk ou sacwants caracteres ki n' polèt nén esse eployîs dins les tites.",
+       "title-invalid-too-long": "Li tite di pådje dimandé est pår trop longou. Ça n' pout nén aveur pus di $1 {{PLURAL:$1|octet|octets}} e l' ecôdaedje UTF-8.",
        "perfcached": "Les dnêyes ki shuvèt c' est ene copeye e muchete, et ça s' pout ki ça n' soeye nén ttafwaitmint a djoû. Li muchete a-st on macsimom {{PLURAL:$1|d' on rzultat|di $1 rizultats}}.",
        "perfcachedts": "Les dnêyes ki shuvèt c' est ene copeye e muchete, ey elle ont stî metowes a djoû pol dierin côp li $1. Li muchete a-st on macsimom {{PLURAL:$4|d' on rzultat|di $4 rizultats}}.",
        "viewsource": "Vey côde sourdant",
        "viewsource-title": "Côde sourdant di «$1»",
        "viewsourcetext": "Loukîz li contnou d' l’ årtike, et s’ li rcopyî si vos vloz, por vos bouter dsu foû des fyis:",
        "protectedinterface": "Cisse pådje ci dene on tecse d' eterface pol programe, eyet elle a stî protedjeye po s' waeranti siconte des abus.",
-       "editinginterface": "'''Asteme:''' Vos estoz ki candje ene pådje eployeye po fé l' tecse po l' eterface do programe.\nLes candjmints ki vso frîz vont candjî l' rivnance di l' eterface po ds ôtes uzeus.\nPo des ratournaedjes, loukîz purade a [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net], li pordjet di locålijhaedje da MediaWiki.",
+       "editinginterface": "<stron>Asteme:</strong> Vos estoz ki candje ene pådje eployeye po fé l' tecse po l' eterface do programe.\nLes candjmints ki vos frîz vont candjî l' rivnance di l' eterface po ls ôtes uzeus do wiki.",
        "cascadeprotected": "Cisse pådje ci a stî protedjeye siconte des candjmints, pask' ele est eploye ådvins {{PLURAL:$1|del pådje shuvante k' est protedjeye|des pådjes shuvantes ki sont protedjeyes}} avou l' tchuze «e cascåde» en alaedje:\n$2",
-       "logouttext": "'''Vos vs avoz dislodjî.'''\n\nVos ploz continouwer a naivyî so {{SITENAME}} anonimmint, oudonbén <span class='plainlinks'>[$1 vos relodjî]</span>, dizo l' minme uzeu ou dizo èn uzeu diferin.\nNotez ki des pådjes k' i gn a si pôrént continowuer a vey come si vos estîz elodjî, disk' a tant ki vos vudrîz l' muchete di vosse betchteu waibe.",
+       "logouttext": "<strong>Vos vs avoz dislodjî.</strong>\n\nNotez ki des pådjes k' i gn a si pôrént continouwer a vey come si vos estîz elodjî, disk' a tant ki vos vudrîz l' muchete di vosse betchteu waibe.",
+       "welcomeuser": "Bénvnowe, $1!",
        "yourname": "Vosse no d' elodjaedje:",
+       "userlogin-yourname": "No d' uzeu",
        "yourpassword": "Vosse sicret",
+       "userlogin-yourpassword": "Sicret",
        "yourpasswordagain": "Ritapez vosse sicret",
        "remembermypassword": "Rimimbrer m' sicret inte les sessions (nén dpus ki po $1 {{PLURAL:$1|djoû|djoûs}})",
        "yourdomainname": "Vosse dominne",
        "logout": "Si dislodjî",
        "userlogout": "Si dislodjî",
        "notloggedin": "Nén elodjî",
+       "userlogin-joinproject": "S' edjîstrer so {{SITENAME}}",
        "nologin": "Vos n' avoz nén d' conte so ç' wiki ci? $1.",
        "nologinlink": "Ahivez on conte da vosse",
        "createaccount": "Ahiver on novea conte",
        "gotaccount": "Vos avoz ddja on conte so ç' wiki ci? '''$1'''.",
        "gotaccountlink": "Elodjîz vs",
        "userlogin-resetlink": "Avoz rovyî les pondants et djondants po s' elodjî?",
-       "createaccountmail": "pa emile",
+       "createaccountmail": "Eployî on scret timporaire a l' astcheyance eyet l' evoyî so l' emile diné",
+       "createacct-realname": "Vraiy no (opcionel)",
        "createaccountreason": "Råjhon:",
+       "createacct-reason": "Råjhon",
        "createacct-another-submit": "Ahiver èn ôte conte",
+       "createacct-benefit-body1": "{{PLURAL:$1|candjmint|candjmints}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|pådje|pådjes}}",
        "badretype": "Vos avoz dné deus screts diferins.",
        "userexists": "Li no d' uzeu ki vs avoz tchoezi est ddja eployî.\nTchoezixhoz è èn ôte s' i vs plait.",
        "loginerror": "Aroke d' elodjaedje",
        "nosuchuser": "I g na nou uzeu dizo l' no «$1».\nNotez k' les nos d' uzeu fjhèt l' diferince etur pitites et grandès letes.\nVerifyîz çou k' vos avoz tapé, oudonbén [[Special:UserLogin/signup|ahivez on novea conte]].",
        "nosuchusershort": "I g na nou uzeu dizo l' no «$1». Verifyîz çou k' vos avoz tapé.",
        "nouserspecified": "Vos dvoz dner on no d' elodjaedje.",
+       "login-userblocked": "{{GENDER:$1|Cist uzeu est bloké|Ciste uzeuse est blokêye}}. L' elodjaedje n' est nén possibe.",
        "wrongpassword": "Li scret ki vs avoz dné est måva. Rissayîz s' i vs plait.",
        "wrongpasswordempty": "Vos avoz dné on vude sicret. Rissayîz s' i vs plait.",
        "passwordtooshort": "Li scret doet esse di pol moens {{PLURAL:$1|1 caractere|$1 caracteres}}.",
-       "mailmypassword": "M' emiler on novea scret",
+       "passwordtoolong": "Les screts n' polèt nén aveur pus di {{PLURAL:$1|1 caractere|$1 caracteres}}.",
+       "mailmypassword": "Rifé l' sicret",
        "passwordremindertitle": "Novea scret timporaire po {{SITENAME}}",
        "passwordremindertext": "Ene sakî (probåblumint vos-minme, avou l' adresse IP $1) a dmandé \non novea scret po {{SITENAME}} ($4).\nOn scret timporare po l' uzeu «$2» a stî fwait, c' est «$3».\nSi c' est vos k' a fwait l' dimande, vos vs divoz elodjî eyet tchoezi on novea scret.\nLi scret timporaire ni srè pus valide après {{PLURAL:$5|on djoû|$5 djoûs}}.\n\nSi c' est ene ôte sakî k' a fwait l' dimande, ou si vos vs avoz rtrové l' vî scret eyet \nnel pus vleur candjî, vos ploz djusse ignorer ci messaedje ci eyet continouwer avou l' vî scret.",
        "noemail": "I n' a pont d' adresse emile di cnoxhowe po l' uzeu «$1».",
        "emailconfirmlink": "Acertinaedje di voste adresse emile",
        "invalidemailaddress": "L' adresse emile ni pout nén esse acceptêye la k' i shonnreut k' ele soeye dins ene cogne nén valide.\nTapez ene adresse emile sicrîte comifåt oudobén vudîz l' tchamp, s' i vs plait.",
        "accountcreated": "Conte ahivé",
-       "accountcreatedtext": "Li conte d' uzeu «$1» a stî ahivé.",
+       "accountcreatedtext": "Li conte d' uzeu «[[{{ns:User}}:$1|$1]]» ([[{{ns:User talk}}:$1|copene]]) a stî ahivé.",
        "loginlanguagelabel": "Lingaedje: $1",
        "pt-login": "S' elodjî",
        "pt-login-button": "S' elodjî",
        "pt-createaccount": "Ahiver on novea conte",
        "pt-userlogout": "\nSi dislodjî",
        "changepassword": "Candjî l' sicret",
-       "resetpass_announce": "Vos vs avoz elodjî avou on scret timporaire ki vos a stî emilé.\nPor vos fini l' elodjaedje, vos dvoz defini on novea scret:",
+       "resetpass_announce": "Por vos fini l' elodjaedje, vos dvoz defini on novea scret.",
        "resetpass_header": "Candjî l' sicret do conte",
        "oldpassword": "Vî scret:",
        "newpassword": "Noû scret:",
        "retypenew": "Ritapez l' noû scret:",
        "resetpass_submit": "Defini on scret et s' elodjî",
-       "changepassword-success": "Vosse sicret a stî candjî comifåt!\nAsteure l' elodjaedje...",
+       "changepassword-success": "Vosse sicret a stî candjî comifåt!",
+       "botpasswords-label-update": "Mete a djoû",
+       "botpasswords-label-delete": "Disfacer",
        "resetpass_forbidden": "Les screts n' polèt nén esse candjîs",
        "resetpass-no-info": "Vos dvoz esse elodjî po pleur aveur accès a cisse pådje ci.",
        "resetpass-submit-loggedin": "Candjî l' sicret",
        "passwordreset-capture-help": "Si vos clitchîz cisse boesse ci, l' emile (eyet li scret timporaire) vos srè håyné e minme tins k' il est emilé.",
        "passwordreset-email": "Adresse emile:",
        "passwordreset-emailtitle": "Detays do contre so {{SITENAME}}",
-       "changeemail": "Candjî l' emile",
-       "changeemail-header": "Candjî l' adresse emile do conte",
+       "changeemail": "Candjî ou disfacer l' adresse emile",
+       "changeemail-header": "Completez cisse pådje ci po candjî l' adresse emile do conte.\nSi vos vloz disfacer totes les adresses aloyeyes, leyîz l' tchamp vude å moumint d' evoyî.",
        "changeemail-no-info": "Vos dvoz esse elodjî po pleur aveur accès a cisse pådje ci.",
        "changeemail-oldemail": "Adresse emile pol moumint:",
        "changeemail-newemail": "Novele adresse emile:",
        "sig_tip": "Li sinateure da vosse, avou l' date et l' eure",
        "hr_tip": "Roye di coûtchî (a n' nén eployî d' trop)",
        "summary": "Rascourti:",
-       "subject": "Sudjet/tiestire:",
+       "subject": "Sudjet:",
        "minoredit": "Ci n' est k' ene tchitcheye",
        "watchthis": "Shuve cist årtike",
        "savearticle": "Schaper l' pådje",
        "preview": "Vey divant",
        "showpreview": "Vey divant",
        "showdiff": "Vey les candjmints",
-       "anoneditwarning": "'''Asteme:''' Vos n' estoz nén elodjî.\nVoste adresse IP serè rashiowe dins l' istwere di cisse pådje ci.",
+       "anoneditwarning": "<strong>Asteme:</strong> Vos n' estoz nén elodjî.\nVoste adresse IP serè rashiowe dins l' istwere di cisse pådje ci eyet veyowe publicmint.\nSi vos vs <strong>[$1 elodjîz]</strong> ou <strong>[$2 ahivez on conte]</strong>, les candjmints da vosse seront-st atribouwés a vosse no d' uzeu, et co ds ôtes advintaedjes.",
        "anonpreviewwarning": "''Vos n' estoz nén elodjî. Si vos schapez c' est voste adresse IP ki serè wårdêye dins l' istwere des candjmints.''",
        "missingsummary": "'''Asteme:''' Vos n' avoz nén dné on tecse di rascourti po vosse candjmint. Si vos rclitchîz sol boton «Schaper», li candjmint da vosse serè schapé sins nou tecse di rascourti po l' istwere del pådje.",
        "missingcommenttext": "Tapez on comintaire chal pa dzo s' i vs plait.",
        "accmailtitle": "Li scret a stî evoyî.",
        "accmailtext": "On scret costrût a l' astcheyance po [[User talk:$1|$1]] a stî evoyî a $2.\n\nLi scret po ci novea conte ci pout esse candjî sol pådje di ''[[Special:ChangePassword|candjmint di scret]]'' après l' elodjaedje.",
        "newarticle": "(Novea)",
-       "newarticletext": "Vos avoz clitchî so on loyén viè ene pådje ki n' egzistêye nén co.\nMins '''vos''' l' poloz askepyî! Po çoula, vos n' avoz k' a cmincî a taper vosse tecse dins l' boesse di tecse chal pa dzo (alez vey li [$1 pådje d' aidance] po pus d' infôrmåcion).\nSi vos n' voloz nén scrire cisse pådje chal, clitchîz simplumint sol boton '''En erî''' di vosse betchteu waibe po rivni al pådje di dvant.",
-       "anontalkpagetext": "---- ''Çouchal, c' est li pådje di copene po èn uzeu anonime ki n' a nén (co) fwait on conte por lu s' elodjî, ou ki n' l' eploye nén.\nÇa fwait k' on doet eployî si adresse IP limerike po l' idintifyî.\nCome ene sifwaite adresse IP pout esse eployeye pa pus d' èn uzeu, i s' pout ki vos voeyoz chal des rmarkes et des messaedjes ki n' sont nén por vos.\nLoukîz s' i vs plait po [[Special:UserLogin/signup|fé on novea conte]] ou [[Special:UserLogin|s' elodjî]] po n' pus aveur d' ecramiaedje avou des ôtes uzeus anonimes.''",
+       "newarticletext": "Vos avoz clitchî so on loyén viè ene pådje ki n' egzistêye nén co.\nMins '''vos''' l' poloz askepyî! Po çoula, vos n' avoz k' a cmincî a taper vosse tecse dins l' boesse di tecse cial pa dzo (alez vey li [$1 pådje d' aidance] po pus d' infôrmåcion).\nSi vos estoz droci par accidint, clitchîz simplumint sol boton <strong>En erî</strong> di vosse betchteu waibe po rivni al pådje di dvant.",
+       "anontalkpagetext": "---- ''Çouchal, c' est li pådje di copene po èn uzeu anonime ki n' a nén (co) fwait on conte por lu s' elodjî, ou ki n' l' eploye nén.\nÇa fwait k' on doet eployî si adresse IP limerike po l' idintifyî.\nCome ene sifwaite adresse IP pout esse eployeye pa pus d' èn uzeu, i s' pout ki vos veyoz chal des rmarkes et des messaedjes ki n' sont nén por vos.\nLoukîz s' i vs plait po [[Special:UserLogin/signup|fé on novea conte]] ou [[Special:UserLogin|s' elodjî]] po n' pus aveur d' ecramiaedje avou des ôtes uzeus anonimes.''",
        "noarticletext": "I gn a pol moumint nou tecse e cisse pådje chal.\nVos ploz [[Special:Search/{{PAGENAME}}|cweri après l' tite di cisse pådje ci]] dins des ôtès pådjes,\noudonbén <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cweri dins les djournås],\nou co [{{fullurl:{{FULLPAGENAME}}|action=edit}} ahiver l' pådje]</span>.",
-       "noarticletext-nopermission": "I gn a pol moumint nou tecse e cisse pådje chal.\nVos ploz [[Special:Search/{{PAGENAME}}|cweri après l' tite di cisse pådje ci]] dins des ôtès pådjes,\noudonbén <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cweri dins les djournås]</span>.",
+       "noarticletext-nopermission": "I gn a pol moumint nou tecse e cisse pådje chal.\nVos ploz [[Special:Search/{{PAGENAME}}|cweri après l' tite di cisse pådje ci]] dins des ôtès pådjes,\noudonbén <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cweri dins les djournås]</span>, mins vos n' avoz nén l' livea d' permission pol poleur ahiver.",
        "blocked-notice-logextract": "{{GENDER:$1|Cist uzeu est bloké|Ciste uzeuse est blokêye}} pol moumint.\nLi dierinne intrêye e djournå des blocaedjes est dnêye chal pa dzo po infôrmåcion:",
        "clearyourcache": "'''Note:''' après aveur schapé l' pådje, vos l' divoz rafrister, po pleur vey les candjmints dins vosse betchteu waibe.\n* '''Firefox / Safari:''' tchôkîz so ''Shift'' tot clitchant so ''Rafrister'', ou co fjhoz ''Ctrl-F5'' ou ''Ctrl-R'' (''⌘-R'' so on Mac)\n* '''Google Chrome:''' tchôkîz so ''Ctrl-Shift-R'' (''⌘-Shift-R'' on a Mac)\n* '''Internet Explorer:''' tchôkîz so ''Ctrl'' tot clitchant so ''Rafrister'', ou co fjhoz ''Ctrl-F5''\n* '''Konqueror:''' clitchîz so ''Rafrister'' ou tchôkîz so ''F5''\n* '''Opera:''' vudîz l' muchete dins ''Usteyes → Preferinces''.",
        "usercssyoucanpreview": "'''Racsegne:''' eployîz l' boton «{{int:showpreview}}» po sayî vosse novea CSS divant del schaper.",
        "editingold": "'''ASTEME: Vos estoz ki candje ene viye modêye del pådje.\nSi vos l' schapez, tos les candjmints k' ont stî fwaits\ndispoy adon si vont piede.'''",
        "yourdiff": "Diferinces",
        "copyrightwarning": "Notez ki tos les contribouwaedjes fwaits po {{SITENAME}} dvèt esse dizo l' licince $2 (loukîz $1 po pus di racsegnes).\nSi vos n' voloz nén ki vosse tecse poye esse candjî eyet spårdou pa tot l' minme kî, adon nel evoyîz nén chal.<br />\nVos nos acertinez eto ki vos avoz scrît l' tecse vos-minme, oudonbén l' avoz copyî d' on sourdant libe (dominne publik ou on sourdant pareymint libe).\n'''N' EVOYÎZ NÉN DES TECSES DIZO ABONDROETS SINS PERMISSION!'''",
-       "copyrightwarning2": "Notez ki tos les contribouwaedjes fwaits po {{SITENAME}} polèt esse esse candjîs ou disfacés pa des ôtes contribouweus.\nSi vos n' voloz nén scrire des årtikes ki polèt esse candjîs pa des ôtes, adon nels evoyîz nén chal.<br />\nVos nos acertinez eto ki vos avoz scrît l' tecse vos-minme, oudonbén l' avoz copyî d' on sourdant libe (voeyoz $1 po pus di racsegnes).\n'''N' EVOYÎZ NÉN DES TECSES DIZO ABONDROETS SINS PERMISSION!'''",
+       "copyrightwarning2": "Notez ki tos les contribouwaedjes fwaits po {{SITENAME}} polèt esse esse candjîs ou disfacés pa des ôtes contribouweus.\nSi vos n' voloz nén scrire des årtikes ki polèt esse candjîs pa des ôtes, adon nels evoyîz nén chal.<br />\nVos nos acertinez eto ki vos avoz scrît l' tecse vos-minme, oudonbén l' avoz copyî d' on sourdant libe (veyoz $1 po pus di racsegnes).\n'''N' EVOYÎZ NÉN DES TECSES DIZO ABONDROETS SINS PERMISSION!'''",
        "longpageerror": "'''AROKE: Li tecse ki vos avoz evoyî fwait di pus d' $1 kilo-octet{{PLURAL:$1||s}}, çou k' est pus ki l' macsimom di $2 kilo-octet{{PLURAL:$2||s}}.'''\nC' est nén possible del schaper sol sierveu.",
        "readonlywarning": "'''ASTEME: On-z overe sol båze di dnêyes pol moumint, ey elle a stî metowe e mode seulmint-lére.\nDo côp, vos n' såroz schaper vos candjmints asteure.'''\nMotoit vos dvrîz copyî et aclaper l' tecse dins on fitchî da vosse pol poleur rimete pus tård.\n\nLi manaedjeu k' a-st eclawé l' båze di dnêyes a dné cist esplicaedje ci: $1",
        "protectedpagewarning": "'''ASTEME: Cisse pådje chal a stî protedjeye, seulmint les uzeus avou èn accès di manaedjeu el polèt candjî.'''\nLi dierinne intrêye ezès djournås est håynêye chal pa dzo po referince:",
        "currentrev": "Modêye d' asteure",
        "currentrev-asof": "Dierinne modêye å $1",
        "revisionasof": "Modêye do $1",
-       "revision-info": "Modêye do $1 pa $2",
+       "revision-info": "Modêye do $1 pa $2$7",
        "previousrevision": "←Modêye di dvant",
        "nextrevision": "Modêye shuvante→",
        "currentrevisionlink": "Modêye d' asteure",
        "rev-deleted-text-permission": "Cisse modêye ci del pådje a stî '''disfacêye'''.\nVos ploz vey les ca et les ma sol [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} djournå des disfaçaedjes].",
        "rev-deleted-text-view": "Cisse modêye ci del pådje a stî '''disfacêye'''.\nVos l' poloz co vey; i gn a des detays sol [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} djournå des disfaçaedjes].",
        "rev-delundel": "mostrer/catchî",
+       "rev-showdeleted": "mostrer",
        "revisiondelete": "Disfacer/rapexhî des modêyes",
        "revdelete-show-file-submit": "Oyi",
        "logdelete-selected": "{{PLURAL:$1|Evenmint tchoezi|Evenmints tchoezis}} ezès djournås:",
-       "revdelete-legend": "Defini des restriccions sol voeyaedje",
+       "revdelete-legend": "Defini des restriccions sol veyaedje",
        "revdelete-hide-text": "Catchî l' tecse del modêye",
        "revdelete-hide-comment": "Catchî l' comintaire di candjmint",
        "revdelete-hide-user": "Catchî l' no d' uzeu/adresse IP do candjeu",
        "shown-title": "Mostrer $1 rizultat{{PLURAL:$1||s}} par pådje",
        "viewprevnext": "Vey ($1 {{int:pipe-separator}} $2) ($3).",
        "searchmenu-exists": "'''Gn a ddja ene pådje lomêye « [[:$1]] » so ç' wiki ci'''",
-       "searchmenu-new": "'''Ahiver l' pådje \"[[:$1]]\" so ç' wiki ci!'''",
+       "searchmenu-new": "<strong>Ahiver l' pådje \"[[:$1]]\" so ç' wiki ci!</strong>\n{{PLURAL:$2|0=|Loukîz eto l' pådje trovêye pa vosse cweraedje.|Loukîz eto li rzultat di vosse cweraedje.}}",
        "searchprofile-articles": "Pådjes di contnou",
        "searchprofile-images": "Multimedia",
        "searchprofile-everything": "Tote li waibe",
        "powersearch-togglelabel": "Tchoezi:",
        "powersearch-toggleall": "Totafwait",
        "powersearch-togglenone": "Disclitchî tot",
+       "powersearch-remember": "Rimimbrer l' tchuze po ls ôtes cweraedjes",
        "search-external": "Difoûtrin cweraedje",
        "searchdisabled": "Mande escuzes! Li cweraedje å dvins des årtikes a stî dismetou pol moumint, cåze ki l' sierveu est fortcherdjî. Tot ratindant, vos ploz eployî Google po fé les rcweraedjes so {{SITENAME}}, mins çoula pout esse ene miete vî.",
        "preferences": "Preferinces",
        "prefs-watchlist-days": "Nombe di djoûs a mostrer dins l' djivêye:",
        "prefs-watchlist-days-max": "Macsimom $1 djoû{{PLURAL:$1||s}}",
        "prefs-watchlist-edits": "Nombe di candjmints a mostrer dins l' djivêye:",
+       "prefs-watchlist-edits-max": "Nombe macsimom: 1000",
        "prefs-misc": "Totes sôres",
        "prefs-resetpass": "Candjî l' sicret",
        "prefs-changeemail": "Candjî l' emile",
        "rows": "Royes",
        "columns": "Colones",
        "searchresultshead": "Håynaedje des rzultats di cweraedje",
+       "stub-threshold": "Limite pol formataedje des loyéns djermons ($1):",
+       "stub-threshold-sample-link": "egzimpe",
+       "stub-threshold-disabled": "Dismetou",
        "recentchangesdays": "Nombe di djoûs po les dierins candjmints:",
        "recentchangesdays-max": "Macsimom $1 djoû{{PLURAL:$1||s}}",
        "recentchangescount": "Prémetou nombe di candjmintstites a håyner:",
+       "prefs-help-recentchangescount": "Çouchal inclût les dierins candjmints, l' istwere, eyet les djournås.",
        "savedprefs": "Vos preferinces ont stî schapêyes.",
        "timezonelegend": "Coisse d' eureye:",
        "localtime": "L' eure locåle",
        "right-deletedtext": "Vey les tecses disfacés eyet les candjmints etur disfacêyès modêyes",
        "right-browsearchive": "Loukî après les disfacêyès pådjes",
        "right-undelete": "Rapexhî ene pådje k' a stî disfacêye",
-       "right-suppressrevision": "Verifyî et rapexhî les modêyes catcheyes åzès manaedjeus",
+       "right-suppressrevision": "Vey, catchî et discatchî des dnés candjmints po tot l' minme kén uzeu",
        "right-suppressionlog": "Vey les djournås privés",
        "right-block": "Espaitchî d' ôtes uzeus di scrire",
        "right-blockemail": "Espaitchî èn uzeu d' evoyî des emiles",
        "right-ipblock-exempt": "Passer houte des blocaedjes pa adresse IP, pa fortchete d' adresses ou des blocaedjes otomatikes",
        "right-unblockself": "Si disbloker lu-minme",
        "right-protect": "Candjî les liveas d' protedjaedje eyet candjî les pådjes protedjeyes",
+       "right-rollback": "Disfijhaedje abeye des candjmints do dierin uzeu a-z aveur candjî ene pådje",
        "newuserlogpage": "Djournå des noveas uzeus",
        "newuserlogpagetext": "Chal pa dzo c' est ene djivêye des uzeus novelmint eredjîstrés.",
        "rightslog": "Djournå des droets des uzeus",
        "recentchanges-label-minor": "Ci n' est k' on ptit candjmint",
        "recentchanges-label-bot": "Ci candjmint la a stî fwait pa on robot",
        "recentchanges-label-unpatrolled": "Ci candjmint la n' a nén co stî patrouyî",
+       "recentchanges-label-plusminus": "Li grandeur del pådje a candjî d' ostant d' octets",
+       "recentchanges-legend-heading": "<strong>Ledjinde:</strong>",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vey eto l' [[Special:NewPages|djivêye des nouvès pådjes]])",
+       "recentchanges-submit": "Vey",
        "rcnotefrom": "Chal pa dzo les candjmints dispoy li '''$2''' (disk' a '''$1''' di mostrés).",
        "rclistfrom": "Mostrer les candjmints k' i gn a yeu a pårti do $3 $2",
        "rcshowhideminor": "$1 candjmints mineurs",
+       "rcshowhideminor-show": "Mostrer",
+       "rcshowhideminor-hide": "Catchî",
        "rcshowhidebots": "$1 robots",
-       "rcshowhideliu": "$1 uzeus eredjîstrés",
+       "rcshowhidebots-show": "Mostrer",
+       "rcshowhidebots-hide": "Catchî",
+       "rcshowhideliu": "$1 uzeus edjîstrés",
+       "rcshowhideliu-hide": "Catchî",
        "rcshowhideanons": "$1 uzeus anonimes",
+       "rcshowhideanons-show": "Mostrer",
+       "rcshowhideanons-hide": "Catchî",
        "rcshowhidepatr": "$1 candjmints rwaitîs",
+       "rcshowhidepatr-show": "Mostrer",
+       "rcshowhidepatr-hide": "Catchî",
        "rcshowhidemine": "$1 candjmints da minne",
+       "rcshowhidemine-show": "Mostrer",
+       "rcshowhidemine-hide": "Catchî",
+       "rcshowhidecategorization": "$1 li categorijhaedjes des pådjes",
+       "rcshowhidecategorization-show": "Mostrer",
+       "rcshowhidecategorization-hide": "Catchî",
        "rclinks": "Mostrer les $1 dierins candjmints des dierins $2 djoûs.<br />$3",
        "diff": "dif.",
        "hist": "ist.",
        "rc_categories_any": "Totes",
        "rc-change-size-new": "$1 {{PLURAL:$1|octet|octets}} après l' candjmint",
        "newsectionsummary": "/* $1 */ novele seccion",
-       "rc-enhanced-expand": "Mostrer les detays (i fåt JavaScript)",
+       "rc-enhanced-expand": "Mostrer les detays",
        "rc-enhanced-hide": "Catchî les detays",
        "recentchangeslinked": "Candjmints aloyîs",
        "recentchangeslinked-feed": "Candjmints aloyîs",
        "shared-repo-from": "vént d' $1",
        "shared-repo": "on depot pårtaedjî",
        "filerevert": "Rimete come divant $1",
+       "filerevert-legend": "Rapexhî l' fitchî",
+       "filerevert-intro": "Vos estoz k' alez rapexhî l' fitchî <strong>[[Media:$1|$1]]</strong> al [$4 modêye do $3, a $2].",
        "filerevert-comment": "Råjhon:",
+       "filerevert-defaultcomment": "Rimetou al modêye do $2, a $1 ($3)",
        "filerevert-submit": "Disfé",
+       "filerevert-success": "<strong>[[Media:$1|$1]]</strong> a stî rmetou al [$4 modêye do $3, a $2].",
        "filedelete": "Disfacer $1",
        "filedelete-legend": "Disfacer fitchî",
        "filedelete-comment": "Råjhon:",
        "mostimages": "Imådjes les pus loyeyes",
        "mostrevisions": "Årtikes avou l' pus di candjmints",
        "prefixindex": "Indecse pa betchete",
+       "prefixindex-submit": "Mostrer",
        "shortpages": "Coûtès pådjes",
        "longpages": "Longowès pådjes",
        "deadendpages": "Pådjes sins nou loyén wiki",
        "protectedpages": "Pådjes protedjeyes",
        "protectedpages-indef": "Seulmint les protedjaedje disk' a todi",
        "protectedpages-cascade": "Seulmint les protedjaedjes e cascåde",
+       "protectedpages-noredirect": "Catchî les redjiblaedjes",
        "protectedpagesempty": "I gn a pol moumint nole pådje sifwaitmint protedjeye.",
        "protectedtitles": "Tites protedjîs",
        "protectedtitlesempty": "I gn a pol moumint nou tite sifwaitmint protedjî.",
        "usereditcount": "$1 candjmint{{PLURAL:$1||s}}",
        "usercreated": "{{GENDER:$3|Edjîstré|Edjîstrêye}} li $1 a $2",
        "newpages": "Novelès pådjes",
+       "newpages-submit": "Mostrer",
        "newpages-username": "No d' elodjaedje:",
        "ancientpages": "Viyès pådjes",
        "move": "Displaecî",
        "pager-older-n": "{{PLURAL:$1|$1 pus vî|$1 pus vîs}}",
        "booksources": "Sourdants po les lives",
        "booksources-search-legend": "Cweri des sourdants po des lives",
+       "booksources-search": "Cweri",
        "specialloguserlabel": "Fwait pa:",
        "speciallogtitlelabel": "Såme (tite ou uzeu):",
        "log": "Djournås",
+       "logeventslist-submit": "Mostrer",
        "all-logs-page": "Tos les djournås publiks",
        "alllogstext": "Håynaedje etercroejhlé di tos les djournås disponibes so {{SITENAME}}.<br />\nVos ploz defini l' håynaedje tot tchoezixhant ene sôre di djournå, on no d' uzeu, ou l' tite d' ene pådje (po ces deus dierins l' sitinme fwait l' diferince inte les grandes et les ptitès letes).",
        "logempty": "Rén n' corespond dins l' djournå.",
        "allpagessubmit": "I va",
        "allpagesprefix": "Håyner les pådjes avou l' betchete:",
        "allpagesbadtitle": "Li tite di pådje diné n' est nén valide oudonbén il a-st ene betchete di loyén eterlingaedje ou eterwiki. Ça s' pout k' il åye onk ou d' pus d' caracteres ki n' si polèt nén eployî dins les tites.",
+       "allpages-hide-redirects": "Catchî les redjiblaedjes",
        "categories": "Categoreyes",
+       "categories-submit": "Mostrer",
        "categoriespagetext": "{{PLURAL:$1|Li categoreye shuvante est eployeye|Les categoreyes shuvantes sont-st eployeyes}} pa des pådjes ou des fitchîs.\n[[Special:UnusedCategories|Les categoreyes nén eployeyes]] èn sont nén håynêyes chal.\nLoukîz eto [[Special:WantedCategories|les categoreyes dimandêyes]].",
        "categoriesfrom": "Håyner les categoreyes a pårti di:",
        "special-categories-sort-count": "relére pa nombe di cayets",
        "listusers-submit": "Vey",
        "listusers-noresult": "Nol uzeu di trové.",
        "listusers-blocked": "({{GENDER:$1|bloké|blokêye}})",
+       "activeusers-hidebots": "Catchî les robots",
        "listgrouprights-members": "(djivêye des mimbes)",
        "mailnologin": "Nole adresse d' evoyeu",
        "mailnologintext": "Po-z evoyî èn emile a èn ôte uzeu i vs fåt esse [[Special:UserLogin|elodjî]] eyet aveur ene adresse emile d' evoyeu ki soeye valide dins vos [[Special:Preferences|preferinces]].",
        "notanarticle": "Nén èn årtike",
        "watchlist-details": "Vos avoz {{PLURAL:$1|$1 pådje shuvowe|$1 pådjes shuvowes}} (sins conter les pådjes di copene).",
        "wlheader-enotif": "Li notifiaedje pa emile est en alaedje.",
-       "wlheader-showupdated": "Les pådjes k' ont candjî dispoy vosse dierinne vizite sont metowes e '''cråssès letes'''",
+       "wlheader-showupdated": "Les pådjes k' ont candjî dispoy vosse dierinne vizite sont metowes e <strong>cråssès letes</strong>.",
        "wlnote": "Chal pa dzo {{PLURAL:$1|li dierin candjmint|les '''$1''' dierins candjmints}} {{PLURAL:$2|del dierinne eure|des '''$2''' dierinnès eures}}, disk' å $3 a $4.",
-       "wlshowlast": "Mostrer les dierin(nè)s $1 eures, $2 djoûs ou",
+       "wlshowlast": "Mostrer les dierin(nè)s $1 eures, $2 djoûs",
+       "watchlist-hide": "Catchî",
+       "watchlist-submit": "Mostrer",
        "watchlist-options": "Tchuzes del djivêye des shuvous",
        "enotif_reset": "Mårker totes les pådjes come vizitêyes",
        "enotif_lastvisited": "Loukîz $1 po tos les candjmints dispoy vosse dierinne vizite.",
-       "enotif_body": "Binamé $WATCHINGUSERNAME,\n\nLi pådje «$PAGETITLE» so {{SITENAME}} a stî $CHANGEDORCREATED li $PAGEEDITDATE pa $PAGEEDITOR,\nloukîz $PAGETITLE_URL pol modêye do moumint.\n\n$NEWPAGE\n\nComintaire do candjeu: $PAGESUMMARY $PAGEMINOREDIT\n\nContak do candjeu:\nemile: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nI n' årè nén d' ôtes notifiaedjes po ds ôtes candjmints di ç' minme pådje ci tant k' vos n' l' åroz nén vizitêye.\nVos ploz eto rimete a noû les drapeas di notifiaedje po totes les pådjes di vosse djivêye des pådjes a shuve.\n\n\nVosse binamé sistinme di notifiaedje so {{SITENAME}}\n\n--\nPo candjî l' apontiaedje di vos notifiaedjes pa emile, loukîz\n{{canonicalurl:{{#special:Preferences}}}}\n\nPo candjî l' apontiaedje di vosse djivêye a shuve, loukîz\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPo rsaetchî l' pådje di vosse djivêye a shuve, alez so\n$UNWATCHURL\n\nPo pus d' aidance:\n$HELPPAGE",
+       "enotif_body": "Binamé $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nComintaire do candjeu: $PAGESUMMARY $PAGEMINOREDIT\n\nContak do candjeu:\nemile: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nI n' årè nén d' ôtes notifiaedjes po ds ôtes candjmints di ç' minme pådje ci tant k' vos n' l' åroz nén vizitêye (tot estant elodjî).\nVos ploz eto rimete a noû les drapeas di notifiaedje po totes les pådjes di vosse djivêye des pådjes a shuve.\n\n\nVosse binamé sistinme di notifiaedje so {{SITENAME}}\n\n--\nPo candjî l' apontiaedje di vos notifiaedjes pa emile, loukîz\n{{canonicalurl:{{#special:Preferences}}}}\n\nPo candjî l' apontiaedje di vosse djivêye a shuve, loukîz\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPo rsaetchî l' pådje di vosse djivêye a shuve, alez so\n$UNWATCHURL\n\nPo pus d' aidance:\n$HELPPAGE",
        "created": "ahivêye",
        "changed": "candjeye",
        "deletepage": "Disfacer l' pådje",
        "delete-confirm": "Disfacer «$1»",
        "delete-legend": "Disfacer",
        "historywarning": "'''Asteme:''' Li pådje ki vos alez disfacer a-st ene istwere avou a pô près $1 modêye{{PLURAL:$1||s}}:",
+       "historyaction-submit": "Mostrer",
        "confirmdeletetext": "Vos alez disfacer ene pådje avou tote si istwere.\nAcertinez s' i vs plait ki c' est bén çoula ki vos vloz fé,\nki vos comprindoz les consecwinces, et ki vos fjhoz çoula\ntot [[{{MediaWiki:Policy-url}}|shuvant les rîles]].",
        "actioncomplete": "Fwait",
        "actionfailed": "L' accion a fwait berwete",
        "delete-edit-reasonlist": "Candjî les råjhons do disfaçaedje",
        "delete-toobig": "Cisse pådje ci a ene foû grande istwere, avou dpus di $1 modêye{{PLURAL:$1||s}}.\nLi disfaçaedje des sfwaitès pådjes a stî dismetou po-z espaitchî k' i gn åye des problinmes so {{SITENAME}}.",
        "delete-warning-toobig": "Cisse pådje ci a ene foû grande istwere, avou dpus di $1 modêye{{PLURAL:$1||s}}.\nSi disfaçaedje pôreut fé des problinmes avou l' rotaedje del båze di dnêyes so {{SITENAME}}; \nnel fijhoz k' avou asteme.",
+       "rollback": "Disfé les candjmints",
        "rollbacklink": "netyî",
+       "rollbacklinkcount": "disfé $1 {{PLURAL:$1|candjmint|candjmints}}",
+       "rollbackfailed": "Li disfijhaedje a fwait berwete",
        "cantrollback": "Dji n' sai disfé les candjmints; li dierin contribouweu est li seu oteur po cist årtike ci.",
        "alreadyrolled": "Dji n' sai disfé li dierin candjmint di [[$1]] fwait pa [[User:$2|$2]] ([[User talk:$2|Copene]]);\nene sakî d' ôte a ddja candjî l' årtike ou ddja rmetou l' modêye di dvant.\n\nLi dierin candjmint a stî fwait pa [[User:$3|$3]] ([[User talk:$3|Copene]]).",
        "editcomment": "Li rascourti do candjmint esteut: <em>$1</em>.",
        "revertpage": "Disfwait les candjmints da [[Special:Contributions/$2|$2]] ([[User talk:$2|copene]]); li dierin candjmint est asteure da [[User:$1|$1]]",
+       "rollback-success": "Disfwait les candjmints da $1;\nli dierin candjmint est asteure da $2.",
        "protectlogpage": "Djournå des protedjaedjes",
        "protectlogtext": "Chal pa dzo c' est ene djivêye des protedjaedjes et disprotedjaedjes des pådjes.\nLoukîz al [[Special:ProtectedPages|djivêye des pådjes protedjeyes]] po vey les protedjaedjes ki sont en alaedje pol moumint.",
        "protectedarticle": "«[[$1]]» protedjî",
        "undelete-missing-filearchive": "Nén possibe d' aler rapexhî li fitchî avou l’ ID $1 pask' i n' est nén dins l' båze di dnêyes. Motoit k' il a ddja stî rapexhî dvant.",
        "namespace": "Espåce di lomaedje:",
        "invert": "Tchuze å rvier",
+       "namespace_association": "Espåce di lomaedje aloyî",
        "blanknamespace": "(Mwaisse)",
-       "contributions": "Ovraedjes di l' uzeu",
+       "contributions": "Ovraedjes di l' {{GENDER:$1|uzeu|uzeuse}}",
        "contributions-title": "Djivêye des ovraedjes di l' {{GENDER:$1|uzeu|uzeuse}} $1",
        "mycontris": "Mi ovraedje",
        "contribsub2": "Po l' uzeu $1 ($2)",
        "whatlinkshere-hidelinks": "$1 les loyaedjes",
        "whatlinkshere-hideimages": "$1 fitchîs k' eploynut cist imådje ci",
        "whatlinkshere-filters": "Passetes",
+       "whatlinkshere-submit": "Vey",
        "autoblockid": "Blocaedje otomatike #$1",
        "blockip": "Bloker èn uzeu",
        "blockiptext": "Rimplixhoz les tchamps chal pa dzo po bloker\nl' accès e scrijhaedje d' èn uzeu dné ou a pårt d' ene\nadresse IP dnêye. Çouci èn doet esse fwait ki po-z arester les\nvandales, et çoula doet esse fwait tot shuvant les\n[[{{MediaWiki:Policy-url}}|rîles]].\nDinez ene råjhon do blocaedje (eg: dijhoz les pådjes k' ont\nstî vandalijheyes).",
        "importlogpagetext": "Ristitchaedjes (import) administratifs di pådjes avou leus istorikes di candjmints, a pårti d' ôtes wikis.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|modêye|modêyes}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|modêye|modêyes}} foû di $2",
-       "tooltip-pt-userpage": "Pådje d' uzeu da minne",
+       "tooltip-pt-userpage": "Pådje d' {{GENDER:|uzeu|uzeuse}} da minne",
        "tooltip-pt-anonuserpage": "Li pådje d' uzeu po l' adresse IP ki vos eployîz pol moumint",
        "tooltip-pt-mytalk": "Pådje di copene da minne",
        "tooltip-pt-anontalk": "Pådje di copene po les candjmints fwaits a pårti di ciste adresse IP ci",
        "tooltip-pt-mycontris": "Djivêye des ovraedjes da minne",
        "tooltip-pt-login": "Vos estoz ecoraedjî d' vos elodjî, mins nerén, c' est nén oblidjî.",
        "tooltip-pt-logout": "Vos dislodjî",
+       "tooltip-pt-createaccount": "Nos vs ricomandans d' ahiver on conte et di vs elodjî; mins nerén, c' est nén oblidjî",
        "tooltip-ca-talk": "Copene åd fwait do contnou del pådje",
-       "tooltip-ca-edit": "Vos ploz candjî cisse pådje ci. S' i vs plait, eployîz l' boton «Vey divant» po vs acertiner k' tot est comifåt dvant d' schaper vos candjmints.",
+       "tooltip-ca-edit": "Candjî l' pådje",
        "tooltip-ca-addsection": "Radjouter ene novele seccion",
        "tooltip-ca-viewsource": "Cisse pådje ci est protedjeye.\nVos ploz seulmint vey li côde sourdant, mins nén l' candjî.",
        "tooltip-ca-history": "Viyès modêyes del pådje.",
        "tooltip-t-recentchangeslinked": "Dierins candjmints fwaits so des pådjes ki cisse pådje ci a des loyéns viè zeles",
        "tooltip-feed-rss": "Sindicåcion RSS po cisse pådje ci",
        "tooltip-feed-atom": "Sindicåcion Atom po cisse pådje ci",
-       "tooltip-t-contributions": "Vey li djivêye des ovraedjes fwait pa cist uzeu ci",
+       "tooltip-t-contributions": "Vey li djivêye des ovraedjes fwait pa {{GENDER:$1|cist uzeu|ciste uzeuse}} ci",
        "tooltip-t-emailuser": "Evoyî èn emile a cist uzeu ci",
        "tooltip-t-upload": "Eberweter sol sierveu des imådjes ou fitchîs media",
        "tooltip-t-specialpages": "Djivêye di totes les pådjes sipeciåles",
        "tooltip-ca-nstab-main": "Vey li pådje di contnou",
        "tooltip-ca-nstab-user": "Vey li pådje di l' uzeu",
        "tooltip-ca-nstab-media": "Vey li pådje di media",
-       "tooltip-ca-nstab-special": "Çouchal, c' est ene pådje sipeciåle, vos n' poloz nén candjî l' pådje leye-minme.",
+       "tooltip-ca-nstab-special": "Çouchal, c' est ene pådje sipeciåle, ele ni s' pout nén candjî.",
        "tooltip-ca-nstab-project": "Vey li pådje di pordjet",
        "tooltip-ca-nstab-image": "Vey li pådje do fitchî",
        "tooltip-ca-nstab-mediawiki": "Vey li messaedje ratournåve do sistinme",
        "anonusers": "$1, {{PLURAL:$2|uzeu anonime|uzeus anonimes}} di {{SITENAME}}",
        "creditspage": "Pådje di credits",
        "nocredits": "I n' a pont d' infôrmåcion di credits po cisse pådje ci.",
+       "spam_reverting": "Rimetaedje al dierinne modêye sins nou loyén viè $1",
        "pageinfo-title": "Infôrmåcion po «$1»",
        "pageinfo-watchers": "Nombe di shuveus",
        "pageinfo-edits": "Nombe di candjmints",
        "pageinfo-authors": "Nombe d' oteurs diferins",
+       "pageinfo-toolboxlink": "Infôrmåcion sol pådje",
        "markaspatrolleddiff": "Marké come ricoridjî",
        "markaspatrolledtext": "Marker cisse pådje ci come dedja patrouyeye",
        "patrol-log-page": "Djournå des patrouyaedjes",
        "previousdiff": "← Diferinces des candjmints di dvant",
        "nextdiff": "Diferinces des candjmints shuvants →",
        "mediawarning": "'''Asteme''': Ci fitchî chal pôreut esse evirussé.\nSi vos l' enondez vos pôrîz infecter l' sistinme da vosse.",
-       "imagemaxsize": "Limite pol grandeu des imådjes:<br />''(ezès pådjes d'i discrijhaedje di fitchîs)''",
-       "thumbsize": "Grandeu po les imådjetes (thumb):",
+       "imagemaxsize": "Limite pol grandeur des imådjes:<br /><em>(ezès pådjes di discrijhaedje di fitchîs)</em>",
+       "thumbsize": "Grandeur po les imådjetes (thumb):",
        "widthheightpage": "$1 × $2, $3 pådje{{PLURAL:$3||s}}",
        "file-info-size": "$1 × $2 picsels, groxheur do fitchî: $3, del sôre \"MIME\": $4",
        "file-nohires": "I n' a nén di pus grande finté.",
        "svg-long-desc": "Fitchî SVG, finté di $1 × $2 picsels, grandeu: $3",
-       "show-big-image": "Imådje a si grandeur d' oridjinne",
+       "show-big-image": "Fitchî d' oridjinne",
+       "show-big-image-preview": "Grandeur do préveyaedje: $1.",
+       "show-big-image-other": "{{PLURAL:$2|Ôte finté|Ôtès fintés}}: $1.",
+       "show-big-image-size": "$1 × $2 picsels",
        "newimages": "Galreye des nouvès imådjes",
        "imagelisttext": "Chal pa dzo c' est ene djivêye di '''$1''' {{PLURAL:$1|imådje relîte|imådjes relîtes}} $2.",
        "noimages": "I n' a rén a vey.",
        "fileduplicatesearch": "Cweraedje après les dobes fitchîs",
        "fileduplicatesearch-submit": "Cweri",
        "specialpages": "Pådjes sipeciåles",
+       "specialpages-note-top": "Ledjinde",
        "specialpages-group-maintenance": "Etertinance",
        "specialpages-group-other": "Ôtès pådjes especiåles",
        "specialpages-group-login": "S' elodjî / si rashire",
        "intentionallyblankpage": "Cisse pådje ci est vude en esprès.",
        "tag-filter": "Passete po ls [[Special:Tags|etiketes]]:",
        "tag-filter-submit": "Passete",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Etikete|Etiketes}}]]: $2)",
        "tags-edit": "candjî",
        "tags-hitcount": "$1 candjmint{{PLURAL:$1||s}}",
        "comparepages": "Comparer des pådjes",
        "logentry-patrol-patrol": "$1 a marké come patrouyî l' candjmint $4 del pådje $3",
        "logentry-patrol-patrol-auto": "$1 a marké otomaticmint come patrouyî l' candjmint $4 del pådje $3",
        "logentry-newusers-newusers": "$1 a-st ahivé on conte d' uzeu",
-       "logentry-newusers-create": "$1 a-st ahivé on conte d' uzeu",
+       "logentry-newusers-create": "Li conte d' uzeu $1 a stî ahivé",
        "logentry-newusers-create2": "$1 a-st ahivé on conte d' uzeu $3",
        "logentry-newusers-autocreate": "li conte $1 a stî ahivé otomaticmint",
+       "logentry-upload-upload": "$1 {{GENDER:$2|}}a-st eberweté $3",
        "rightsnone": "(nouk)",
        "feedback-adding": "Vosse messaedje a stî håyné sol pådje...",
        "feedback-cancel": "Rinoncî",
index 6125556..28dc0d8 100644 (file)
        "createaccountreason": "Rason:",
        "createacct-reason": "Rason",
        "createacct-reason-ph": "Kay ano nahimo ka hin usa pa nga akawnt",
-       "createacct-submit": "Ighimo an im akawnt",
+       "createacct-submit": "Ighimo an im account",
        "createacct-another-submit": "Paghimo hin account",
        "createacct-benefit-heading": "{{SITENAME}} in ginhimo hin tawo nga sugad ha imo.",
        "createacct-benefit-body1": "{{PLURAL:$1|pagliwat|mga pagliwat}}",
        "nocookieslogin": "{{SITENAME}} in nagkikinahanglan hin mga kuki para makapagpalog-in hin mga gumaramit.  An im mga kuki in diri nagana.\nAlayon paganaha hira ngan utro liwat.",
        "nocookiesfornew": "An imo akawnt han gumaramit in waray nahimo, kay tungod diri kami nakakakompirma han tinikangan.\nSiguradoha nga an mga cookies in nakaandar, igreload ini nga pakli ngan utroha.",
        "noname": "Waray ka nakahatag hin maupay nga agnay-hit-gumaramit.",
-       "loginsuccesstitle": "Malinamposon an pagsulod",
+       "loginsuccesstitle": "Nakalog-in",
        "loginsuccess": "'''Ikaw in nakalog-in ha {{SITENAME}} komo \"$1\".'''",
        "nosuchuser": "Waray gumaramit an may-ada ngaran nga \"$1\".\nIt mga agnay-hi-gumaramit in case sensitive.\nPanginano-a it imo pagbaybay, o [[Special:UserLogin/signup|paghimo hin bag-o nga akawnt]].",
        "nosuchusershort": "Waray nagamit it may ngaran nga \"$1\".\nKitaa kun amo it im pagbaybay.",
        "newarticle": "(Bag-o)",
        "newarticletext": "Ginsunod mo an pakli nga waray pa kahihimo.  Para ighimo an pakli, tikanga pagmakinilya ha kahon nga aada ha ubos (kitaa an [$1 nabulig nga pakli] para han kadugangan nga pananabutan).  Kun sayop an imo pagkanhi, igpidlit an imo kanan panngaykay (''browser'') '''balik''' (''back'') nga piridlitan.",
        "anontalkpagetext": "----\n''Ini in hiruhimangraw-nga-pakli para han waray magpakilala nga gumaramit, nga waray pa hinmimo hin akawnt.''\nMagamit la kami hin IP address para makilal-an hiya.\nSugad hini nga IP address, in puydi sinmaro hiton pipira nga mga gumaramit.\nKun ikaw in waray magpakilala nga gumaramit, ngan pag-abat mo in may mga diri naangay nga komento an ginpapadangat ha imo, alayon nala [[Special:UserLogin/signup|paghimo hin akawnt]] o [[Special:UserLogin|pag-log in]] para malikyan an sumurunod nga mga pagkalipat nga dapat para ha iba nga waray magpakilala nga mga gumaramit.",
-       "noarticletext": "Waray yana nahasurat hini nga pakli.\nPuyde hi ikaw [[Special:Search/{{PAGENAME}}|magbiling para han ngaran hini nga pakli]] ha iba nga mga pakli,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} binga an mga nanginginlabot nga mga log],\no [{{fullurl:{{FULLPAGENAME}}|action=edit}} igliwat ini nga pakli]</span>.",
+       "noarticletext": "Waray yana teksto ha sulod hinin nga pakli.\nPuyde ka [[Special:Search/{{PAGENAME}}|mamiling hin titulo hinin nga pakli]] ha iba pa nga mga pakli,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} pamilnga an may mga pagkahisumpay nga mga talaan],\no [{{fullurl:{{FULLPAGENAME}}|action=edit}} igliwat ini nga pakli]</span>.",
        "noarticletext-nopermission": "Waray yana nahasurat hini nga pakli\nPuyde hi ikaw [[Special:Search/{{PAGENAME}}|magbiling han ngaran hini nga pakli]] ha iba nga mga pakli,\no <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} mamiling han mga nanginginlabot nga mga talaan]</span>, kundi diri ka gintutugotan hin paghímò hini nga pakli.",
        "missing-revision": "Waray na an rebisyon #$1 han pakli nga ginngaranan nga  \"{{FULLPAGENAME}}\".\n\nIni in agsob tungod han pagsunod hin daan nga sumpay hin kaagi ha pakli nga ginpara.\nAn mga detalye in mabibilngan ha [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
        "userpage-userdoesnotexist": "Diri nakarehistro an akawnt han gumaramit nga \"$1\".\nAlayon pagpamuruotbuot kun karuyag mo maghimo/mag-edit hini nga pakli.",
        "grant-createaccount": "Pahimo hin mga account",
        "grant-createeditmovepage": "Paghimo, pagliwat, ngan pagbalhin hin mga pakli",
        "grant-delete": "Pagpara hin mga pakli, mga rebisyon, ngan mga iginsulod ha log",
+       "grant-sendemail": "Igpadara hin email ngadto ha iba nga mga gumaramit",
+       "grant-uploadeditmovefile": "Pagkarga, pagsaliwan, ngan pagbalhin hin mga file",
+       "grant-uploadfile": "Pagkarga hin bag-o nga mga file",
+       "grant-basic": "Mga panguna nga katungod",
+       "grant-viewdeleted": "Kitaa an mga pinanmara nga file ngan pakli",
+       "grant-viewmywatchlist": "Kitaa an imo mga barantayon",
        "newuserlogpage": "Talaan han paghimo hin gumaramit",
        "newuserlogpagetext": "Ini an talaan han mga nagkahihimo nga mga gumaramit.",
        "rightslog": "Talaan hin mga katungod han gumaramit",
+       "rightslogtext": "Ini an talaan han mga pagbag-o han mga katungod hit gumaramit.",
        "action-read": "basaha ini nga pakli",
        "action-edit": "liwata ini nga pakli",
        "action-createpage": "pahimo hin mga pakli",
        "import-rootpage-invalid": "An ginhatag nga gamot-pakli in uska diri balido nga titulo.",
        "import-rootpage-nosubpage": "Ngaran-lat'ang nga \"$1\" han gamot-pakli in diri natugot hin mga bahin-pakli.",
        "importlogpage": "Talaan hin pan-aangbit",
-       "javascripttest-pagetext-skins": "Pagpili hin panit para ha pag-paandar han:",
-       "tooltip-pt-userpage": "An imo pakli hin gumaramit",
-       "tooltip-pt-mytalk": "An imo pakli hin hiruhimangraw",
-       "tooltip-pt-preferences": "An imo mga karuyag",
+       "tooltip-pt-userpage": "{{GENDER:|An imo gumaramit}} nga pakli",
+       "tooltip-pt-mytalk": "{{GENDER:|An imo}} hiruhimangraw nga pakli",
+       "tooltip-pt-preferences": "{{GENDER:|An imo}} mga karuyag",
        "tooltip-pt-watchlist": "An talaan hin mga pakli nga imo ginsisinubay para hin mga kabag-ohan",
-       "tooltip-pt-mycontris": "Talaan han imo mga ámot",
+       "tooltip-pt-mycontris": "Listahan han {{GENDER:|imo}} mga gin-amot",
        "tooltip-pt-login": "Gin-aaghat ka nga mag log-in, pero diri ini ginpipirit.",
        "tooltip-pt-logout": "gawas",
        "tooltip-pt-createaccount": "Ginaag-hat ka nga maghimo hin account ngan maglog-in; pero diri ini mandatorya",
        "tooltip-t-recentchangeslinked": "Mga bag-o nga kabag-ohan ha mga pakli nga nahasumpay tikang hini nga pakli",
        "tooltip-feed-rss": "RSS nga pangarga para hini nga pakli",
        "tooltip-feed-atom": "Atom nga pangarga para hini nga pakli",
-       "tooltip-t-contributions": "Kitaa an talaan hin mga amot hini nga nágámit",
+       "tooltip-t-contributions": "Kitaa an listahan hin mga amot {{GENDER:$1|hinin nga gumaramit}}",
        "tooltip-t-emailuser": "Padad-i hin e-mail ini nga nágámit",
        "tooltip-t-upload": "Pagkarga hin mga paypay",
        "tooltip-t-specialpages": "Talaan hin mga pinaurog nga pakli",
index 0f15351..a397552 100644 (file)
        "perfcachedts": "下头是缓存数据,阿末一趟更新辰光是$1。缓存里最多有{{PLURAL:$4|$4条结果}}。",
        "querypage-no-updates": "当前禁止对此页面进行更新。箇搭个数据弗好立即刷新。",
        "viewsource": "望源码",
-       "viewsource-title": "望“$1”个源码",
+       "viewsource-title": "望“$1”个源码",
        "actionthrottled": "动作已压制",
        "actionthrottledtext": "基于反滥用个考量,限制垃拉短时间内多趟重复箇只操作。请过脱几分钟再试试看。",
        "protectedpagetext": "箇页锁牢定,防编搭各许操作。",
        "whitelistedittext": "请$1编辑。",
        "confirmedittext": "垃拉编辑此页之前侬必须确认侬个邮箱地址。请通过[[Special:Preferences|个人设置]]设置并验证侬个邮箱地址。",
        "nosuchsectiontitle": "寻弗着箇只段落",
-       "nosuchsectiontext": "侬尝试编辑个章节弗存在。\n作兴是垃拉侬查看页面个辰光已经移动或者畀删除。",
+       "nosuchsectiontext": "侬尝试编辑个章节弗存在。作兴是垃拉侬望页面个辰光已经畀移动或者删脱。",
        "loginreqtitle": "必须登录",
        "loginreqlink": "登录",
        "loginreqpagetext": "请$1来望其他页面。",
        "permissionserrorstext-withaction": "为仔下头个{{PLURAL:$1|原因|原因}}咾侬无权进行$2操作:",
        "recreate-moveddeleted-warn": "<strong>警告:你来上重新创建一只老早删过个页面。</strong>\n\n你应该考虑继续编辑箇只页面啊合适。为方便起见,箇只页面个删除搭移动记录提供勒下底:",
        "moveddeleted-notice": "箇页删脱哉。箇页个删除搭移动记录提供垃拉下头以便参考。",
-       "log-fulllog": "æ\9f¥ç\9c\8b完整日志",
+       "log-fulllog": "æ\9c\9b完整日志",
        "edit-hook-aborted": "编辑畀钩子取消。\n渠弗曾畀出解释。",
        "edit-gone-missing": "弗好更新页面。\n渠作兴齐巧畀删除。",
        "edit-conflict": "编辑冲突",
        "textmatches": "页面内容匹配",
        "notextmatches": "呒没匹配个页面文本",
        "prevn": "前$1个",
-       "nextn": "$1个",
+       "nextn": "$1个",
        "prev-page": "上页",
        "next-page": "下页",
        "prevn-title": "前$1个结果",
        "nextn-title": "后$1个结果",
        "shown-title": "一页显示$1个结果",
-       "viewprevnext": "æ\9f¥ç\9c\8b($1 {{int:pipe-separator}} $2)($3)",
+       "viewprevnext": "æ\9c\9b($1 {{int:pipe-separator}} $2)($3)",
        "searchmenu-exists": "'''箇wiki里有一页名字“[[:$1]]”哉'''",
        "searchmenu-new": "<strong>登箇Wiki上建“[[:$1]]”页!</strong>{{PLURAL:$2|0=|另见寻着个页面。|另见搜寻个结果。}}",
        "searchprofile-articles": "内容页",
        "recentchanges-legend": "近段辰光个改动选项",
        "recentchanges-summary": "登该个页面浪跟踪最近对维基百科个改动。",
        "recentchanges-feed-description": "跟踪此订阅垃拉 wiki 高头个最近更改。",
-       "recentchanges-label-newpage": "箇编辑建立着新页",
+       "recentchanges-label-newpage": "箇编辑建立着新页",
        "recentchanges-label-minor": "箇是小编写",
        "recentchanges-label-bot": "箇编辑由机器人执行",
-       "recentchanges-label-unpatrolled": "编辑还朆巡查",
+       "recentchanges-label-unpatrolled": "编辑还朆巡查",
        "recentchanges-label-plusminus": "箇页面字节数前后个变化",
        "recentchanges-legend-heading": "<strong>说明:</strong>",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}(见[[Special:NewPages|新页列表]])",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}(见[[Special:NewPages|新页列表]])",
        "rclistfrom": "显示 $3 $2 以来个新改动",
        "rcshowhideminor": "$1小编写",
        "rcshowhideminor-show": "显示",
        "fileuploadsummary": "小结:",
        "filereuploadsummary": "文件更改:",
        "filestatus": "版权状态:",
-       "filesource": "来源:",
+       "filesource": "来源",
        "ignorewarning": "弗管警告,随便哪亨要保存文件。",
        "ignorewarnings": "忽略所有警告",
        "minlength1": "文件名至少一個字。",
        "restriction-move": "捅荡",
        "undeletepage": "查看搭仔恢复删脱个页面",
        "viewdeletedpage": "望望相删脱个页面",
-       "undeletelink": "æ\9f¥ç\9c\8b/è¿\98å\8e\9f",
+       "undeletelink": "æ\9c\9b\81¢å¤\8d",
        "undeleteviewlink": "望",
        "undeletecomment": "理由:",
        "undelete-search-submit": "搜尋",
        "tooltip-ca-talk": "讨论内容页",
        "tooltip-ca-edit": "编辑箇页",
        "tooltip-ca-addsection": "开始新段",
-       "tooltip-ca-viewsource": "箇页受保护,你好望源代码",
+       "tooltip-ca-viewsource": "箇页畀保护勒上。你好望源码",
        "tooltip-ca-history": "该只页面老早个版本",
        "tooltip-ca-protect": "保护箇页",
        "tooltip-ca-delete": "删脱箇页",
        "tooltip-t-print": "箇页个打印版",
        "tooltip-t-permalink": "箇页当前版本个老世链接",
        "tooltip-ca-nstab-main": "望内容页",
-       "tooltip-ca-nstab-user": "æ\9f¥ç\9c\8b用户页",
-       "tooltip-ca-nstab-media": "æ\9f¥ç\9c\8b媒体页",
+       "tooltip-ca-nstab-user": "æ\9c\9b用户页",
+       "tooltip-ca-nstab-media": "æ\9c\9b媒体页",
        "tooltip-ca-nstab-special": "箇是特别页面,弗好编辑",
        "tooltip-ca-nstab-project": "望项目页",
        "tooltip-ca-nstab-image": "望文件页",
-       "tooltip-ca-nstab-mediawiki": "æ\9f¥ç\9c\8bç³»ç»\9f讯息",
+       "tooltip-ca-nstab-mediawiki": "æ\9c\9bç³»ç»\9fæ¶\88息",
        "tooltip-ca-nstab-template": "望模板",
-       "tooltip-ca-nstab-help": "æ\9f¥ç\9c\8b帮å¿\99页é\9d¢",
+       "tooltip-ca-nstab-help": "æ\9c\9b帮å¿\99页",
        "tooltip-ca-nstab-category": "望分类页",
        "tooltip-minoredit": "标作小编写",
        "tooltip-save": "保存侬个修改",
index 915ca6b..dbcefa4 100644 (file)
        "printableversion": "Барин бәәдл",
        "permalink": "Даңгин заалһ",
        "print": "Барлх",
+       "view": "Хәләвр",
        "edit": "Ясх",
        "create": "Бүтәх",
        "editthispage": "Эн халх ясх",
        "notextmatches": "Халхсин бичәснд ирлцән уга",
        "prevn": "урдк {{PLURAL:$1|$1}}",
        "nextn": "дарук {{PLURAL:$1|$1}}",
+       "shown-title": "Халхар $1 аш үзүлх",
        "viewprevnext": "Хәләх ($1 {{int:pipe-separator}} $2) ($3)",
        "searchprofile-articles": "Зүүлс",
        "searchprofile-images": "Үзгдл-соңсвр",
        "searchprofile-advanced": "Нәрн",
        "searchprofile-articles-tooltip": "$1 дотр хәәх",
        "searchprofile-images-tooltip": "Боомг хәәх",
+       "searchprofile-everything-tooltip": "Хамг зокъял хәәх (күүндвр халх орлцулҗ)",
+       "searchprofile-advanced-tooltip": "Заасн нердин делкәст хәәх",
        "search-result-size": "$1 ({{PLURAL:$2|$2 үг|$2 үг|$2 үг}})",
        "search-redirect": "(туудг $1)",
        "search-section": "(«$1» салвр)",
        "grouppage-bot": "{{ns:project}}:Көдлгчүд",
        "grouppage-sysop": "{{ns:project}}:Закрачуд",
        "grouppage-bureaucrat": "{{ns:project}}:Нойнчуд",
+       "right-writeapi": "API бичхин төлә кергллт",
        "newuserlogpage": "Бичгдлһнә седкүл",
        "rightslog": "Демнәчна зөвин седкүл",
        "action-edit": "эн халх ясх",
        "imagelinks": "Боомг керглән",
        "linkstoimage": "Эн $1 халх эн боомгур заана:",
        "sharedupload": "Эн боомг $1 ормас. Териг талдан төсвд олзлҗ болх.",
+       "sharedupload-desc-here": "Эн боомг $1 талас, бус төслд керглҗ болх.\nБичлһнь [$2 боомгин бичлһнә халх] доракшан үзгднә.",
        "uploadnewversion-linktext": "Тер боомгин шин һарц тәвх",
        "randompage": "Уршг зүүл",
        "statistics": "То бүрткл",
        "tooltip-pt-mycontris": "Тана демнлһнә сеткүл",
        "tooltip-pt-login": "Та орсн күцх бәәнәт, болв кергтә биш.",
        "tooltip-pt-logout": "Һарх",
+       "tooltip-pt-createaccount": "Танд бичгдлһн бүтәҗ, дигләнд орхар сәәшгднә, эн даалhврго чигн",
        "tooltip-ca-talk": "Халхин дотрин туск меткән",
-       "tooltip-ca-edit": "Та Ñ\8dн Ñ\85алÑ\85иг Ñ\87иклÒ\97 Ñ\87аднаÑ\82.\nÐ\91Ñ\83йн Ð±Ð¾Ð»Ñ\82Ñ\85а, Ñ\85адһлһна ÐºÒ¯Ñ\80Ñ\82л Ñ\85Ó\99лÓ\99вÑ\80 Ð¾Ð»Ð·Ð»Ñ\82н.",
+       "tooltip-ca-edit": "Эн Ñ\85алÑ\85 Ñ\8fÑ\81Ñ\85",
        "tooltip-ca-addsection": "Шин хүв эклх",
        "tooltip-ca-viewsource": "Эн халх харссн бәәнә.\nТа энүнә медсн үзҗ чаднат.",
        "tooltip-ca-history": "Эн халхна шидрә чикллһн",
        "tooltip-ca-nstab-main": "Халхнь",
        "tooltip-ca-nstab-user": "Демнчна халхиг үзүлх",
        "tooltip-ca-nstab-media": "Боомгин халх үзх",
-       "tooltip-ca-nstab-special": "Эн көдлхнә халх. Та эниг чиклҗ чадхшв.",
+       "tooltip-ca-nstab-special": "Эн көдлхнә халх, эн ясгдшго.",
        "tooltip-ca-nstab-project": "Төслин халх",
        "tooltip-ca-nstab-image": "Боомгин халхиг",
        "tooltip-ca-nstab-mediawiki": "MediaWiki зәңгин халх",
        "file-info-size": "$1 × $2 цегтә, боомгин кемҗән: $3, MIME янз: $4",
        "file-nohires": "Икәр чинртә янз уга.",
        "svg-long-desc": "SVG боомг, $1 × $2 мет цегтә, боомгин кемҗән: $3",
-       "show-big-image": "Күцц чинр",
+       "show-big-image": "Эк боомг",
+       "show-big-image-preview": "Хәләврин аһу: $1.",
+       "show-big-image-other": "Бус нигтрл: $1.",
+       "show-big-image-size": "$1 × $2 цегтә",
        "file-info-gif-looped": "билцгсн",
        "bad_image_list": "Эн темдглһн кергтә:\n\nБүртклин мөчүд һанцхн оньгтан авх (мөрәд * эклцта).\nТүрүн мөрәнә заалһ - тәвх хөрсн зургин заалһ.\nДарук заалһуд эн мөрәд хаҗилһн болх (халхс зургиг орулҗ болх).",
        "metadata": "Мета өггцн",
        "metadata-help": "Эн боомг дәкәд өггцтә. Тер өггцн то камерар аль сканерар немсмн. Боомг бүтәлһнә хөөн чиклсн бәәхлә, зәрм кемҗәд одахн зургд әдл биш болх.",
        "metadata-expand": "Ик тодрхасиг үзүлх",
        "metadata-collapse": "Ик тодрхасиг бултулх",
-       "metadata-fields": "Эн җигсәмҗд нерлгдсн мета өггцин аһу, дүрслгч халхд герәсләр үзүлгдх, наадкснь бултулгдх.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
+       "metadata-fields": "Эн бүртклд нерәдсн зургин мета то-дигин теегмүд мета то-дигин көснг эвкснд зургин халхт үзгднә. Наадк теегмүд таарсар нуугдх.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "exif-imagewidth": "Өргн",
        "exif-imagelength": "Өндр",
        "exif-bitspersample": "Өңгин гүн",
        "specialpages-group-spam": "Спамас зевсг",
        "blankpage": "Хоосн халх",
        "intentionallyblankpage": "Тер  халх хоосн күслтә бәәнә.",
+       "tag-filter": "[[Special:Tags|Царадын]] шүр:",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Царан|Царад}}]]: $2)",
        "htmlform-reset": "Сольлһиг уга кех",
        "htmlform-selectorother-other": "Талдан",
+       "logentry-newusers-create": "$1 демнәчин бичгдлһн бүтәгдв",
        "rightsnone": "(уга)",
        "searchsuggest-search": "Хәәвр"
 }
index bc98445..19b3bec 100644 (file)
@@ -15,7 +15,8 @@
                        "아라",
                        "Silovan",
                        "David1010",
-                       "Macofe"
+                       "Macofe",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "რცხუეფიშ ათოღაზუა:",
        "recentchangeslinked-page": "ხასილაშ ჯოხო:",
        "recentchangeslinked-to": "მანგიერო ქაძირე ათე ხასილაშა მერცხილ ხასილეფშა მიშაღალირ თირაფეფ",
        "recentchanges-page-added-to-category": "[[:$1]] გეძინელჷ რე კატეგორიას",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] დო {{PLURAL:$2|ართ ხასჷლა|$2 ხასჷლა}} გეძინელ რე კატეგორიას",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] დო [[Special:WhatLinksHere/$1|{{PLURAL:$2|ართ ხასჷლა|$2 ხასჷლა}}]] გეძინელ რე კატეგორიას",
        "recentchanges-page-removed-from-category": "[[:$1]] ლასირი რე კატეგორიაშე",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] დო {{PLURAL:$2|ართ ხასჷლა|$2 ხასჷლა}} ლასირი რე კატეგორიაშე",
        "upload": "ფაილიშ ეხარგუა",
index d5f5776..b86339e 100644 (file)
@@ -16,7 +16,8 @@
                        "Amire80",
                        "පසිඳු කාවින්ද",
                        "Matma Rex",
-                       "Macofe"
+                       "Macofe",
+                       "Nemo bis"
                ]
        },
        "tog-underline": "שטרייכט אונטער לינקען",
        "recentchangeslinked-page": "בלאַט נאָמען:",
        "recentchangeslinked-to": "צייג ענדערונגען צו בלעטער פארבינדן צו דעם בלאט אנשטאט",
        "recentchanges-page-added-to-category": "[[:$1]] צוגעלייגט צו קאטעגאריע",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] און {{PLURAL:$2|איין בלאט|$2 בלעטער}} צוגעלייגט צו קאטעגאריע",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] און [[Special:WhatLinksHere/$1|{{PLURAL:$2]]|איין בלאט|$2 בלעטער}} צוגעלייגט צו קאטעגאריע",
        "recentchanges-page-removed-from-category": "[[:$1]] אראפגענומען פון קאטעגאריע",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] און {{PLURAL:$2|איין בלאט|$2 בלעטער}} אראפגענומען פון קאטעגאריע",
        "autochange-username": "מעדיעוויקי אויטאמאטישער טויש",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}} אימפארטירט",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}} אימפארטירט פֿון $2",
        "javascripttest": "JavaScript טעסט",
-       "javascripttest-pagetext-noframework": " דער בלאט איז רעזערווירט פאר JavaScript. פרואוון.",
-       "javascripttest-pagetext-unknownframework": "אומבאקאנטער טעסטן גערעם \"$1\".",
        "javascripttest-pagetext-unknownaction": "אומבאַקאַנטע אַקציע '$1'",
-       "javascripttest-pagetext-frameworks": "ביטע קלויבט איינעם פון די פאלגנדע טעסטן־גערעם: $1",
-       "javascripttest-pagetext-skins": "קלויבט א באניצער־אייבערפלאך מיט וואס דורכצופירן די בדיקות:",
        "javascripttest-qunit-intro": "זעט [$1 דאקומענטאציע פאר טעסטן] בײַ mediawiki.org.",
        "tooltip-pt-userpage": "אייער {{GENDER:|באניצער|באניצערין}} בלאט",
        "tooltip-pt-anonuserpage": "באַניצער בלאַט פון דעם IP אַדרעס",
        "version-entrypoints-header-url": "URL",
        "version-libraries-library": "ביבליאטעק",
        "version-libraries-version": "ווערסיע",
-       "redirect-legend": "ווײַטערײַטערפירונג צו א טעקע אדער בלאט",
        "redirect-submit": "גייט",
        "redirect-lookup": "זוכן:",
        "redirect-value": "ווערט:",
        "special-characters-group-khmer": "כמער",
        "special-characters-title-endash": "ען טירע",
        "special-characters-title-emdash": "עם טירע",
-       "special-characters-title-minus": "מינוס"
+       "special-characters-title-minus": "מינוס",
+       "log-action-filter-upload": "טיפ ארויפֿלאד:",
+       "log-action-filter-all": "אַלע",
+       "log-action-filter-delete-delete": "אויסמעקן בלאט",
+       "log-action-filter-protect-unprotect": "אראפנעמען שיץ"
 }
index 6d63e20..8f01a17 100644 (file)
        "recentchangeslinked-page": "頁名:",
        "recentchangeslinked-to": "顯示連到所畀到嘅版",
        "recentchanges-page-added-to-category": "[[:$1]] 加咗落分類",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] 同另外 {{PLURAL:$2|1 版|$2 版}}加咗落分類",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] 同另外 [[Special:WhatLinksHere/$1|{{PLURAL:$2|1 版|$2 版}}]]加咗落分類",
        "recentchanges-page-removed-from-category": "[[:$1]] 拎走咗分類",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] 同另外 {{PLURAL:$2|1 版|$2 版}}拎走咗分類",
        "autochange-username": "MediaWiki 自動改動",
index ea691f9..5d07d5e 100644 (file)
        "noemail": "用户\"$1\"没有登记电子邮件地址。",
        "noemailcreate": "您需要提供一个有效的电子邮件地址",
        "passwordsent": "用户\"$1\"的新密码已经寄往所登记的电子邮件地址。\n请在收到后再登录。",
-       "blocked-mailpassword": "你的IP地址被禁止编辑,为预防滥用,密码恢复功能也被禁止使用。",
+       "blocked-mailpassword": "您的IP地址被禁止编辑,为预防滥用,也不允许从该IP地址使用密码恢复功能。",
        "eauthentsent": "一封确认信已经发送至您设定的邮件地址。\n在任何其他邮件发送至您的账户前,您将不得不根据邮件中的指示,确认那个账户确实是您的。",
        "throttled-mailpassword": "密码提醒已在最近$1小时内发送。为了安全起见,在每$1小时内只能发送一个密码提醒。",
        "mailerror": "发送邮件错误:$1",
        "botpasswords-insert-failed": "无法添加机器人名“$1”。它是否已添加?",
        "botpasswords-update-failed": "无法更新机器人名“$1”。它是否已删除?",
        "botpasswords-created-title": "机器人密码已创建",
-       "botpasswords-created-body": "机器人密码“$1”已更新。",
+       "botpasswords-created-body": "用于用户“$2”的机器人名称“$1”的机器人密码已创建。",
        "botpasswords-updated-title": "机器人密码已更新",
-       "botpasswords-updated-body": "机器人密码“$1”已更新。",
+       "botpasswords-updated-body": "用于用户“$2”的机器人名称“$1”的机器人密码已更新。",
        "botpasswords-deleted-title": "机器人密码已删除",
-       "botpasswords-deleted-body": "机器人密码“$1”已删除。",
+       "botpasswords-deleted-body": "用于用户“$2”的机器人名称“$1”的机器人密码已删除。",
        "botpasswords-newpassword": "用于登录<strong>$1</strong>的新密码是<strong>$2</strong>。<em>请记住它以备今后参考。</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider不可用。",
        "botpasswords-restriction-failed": "机器人密码限制阻止此次登录。",
        "rev-deleted-no-diff": "您不能查看该差异,因为其中一个版本已被<strong>删除</strong>。详情请见[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 删除日志]。",
        "rev-suppressed-no-diff": "无法查看该差异,因为其中一个版本已被<strong>删除<strong>。",
        "rev-deleted-unhide-diff": "该差异对比的其中的一个版本已经被<strong>删除</strong>。在[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 删除日志]中可以找到更多的信息。如果您想继续的话,您仍然可以[$1 查看此版本]。",
-       "rev-suppressed-unhide-diff": "该页面的其中一次版本已经被<strong>监督隐藏</strong>。\n在[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 监督日志]中可以找到更多的资料。如果您想继续的话,您可以仍然[$1 去查看这版本]。",
+       "rev-suppressed-unhide-diff": "该页面的其中一次版本已经被<strong>屏蔽</strong>。在[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 监督日志]中可以找到更多的资料。如果您想继续的话,您仍然可以[$1 查看该差异]。",
        "rev-deleted-diff-view": "差异对比中的一次版本已被<strong>删除</strong>。您可以对比此差异。详细信息可在[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 删除日志]中找到。",
-       "rev-suppressed-diff-view": "差异对比中的一个版本已被<strong>监督隐藏</strong>。您可以对比此差异。详细信息可在[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 监督日志]中找到。",
+       "rev-suppressed-diff-view": "差异对比中的一个版本已被<strong>屏蔽</strong>。您可以对比此差异;详细信息可在[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 监督日志]中找到。",
        "rev-delundel": "更改可见性",
        "rev-showdeleted": "显示",
        "revisiondelete": "删除/还原版本",
        "recentchangeslinked-page": "页面名称:",
        "recentchangeslinked-to": "显示链到所给出的页面",
        "recentchanges-page-added-to-category": "[[:$1]]已添加至分类",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]]及其他{{PLURAL:$2|$2个页面}}已添加至分类",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]]及[[Special:WhatLinksHere/$1|其他{{PLURAL:$2|$2个页面}}]]已添加至分类",
        "recentchanges-page-removed-from-category": "[[:$1]]已从分类中移除",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]]及其他{{PLURAL:$2|$2个页面}}已从分类中移除",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]]及[[Special:WhatLinksHere/$1|其他{{PLURAL:$2|$2个页面}}]]已从分类中移除",
        "autochange-username": "MediaWiki自动化更改",
        "upload": "上传文件",
        "uploadbtn": "上传文件",
        "uploadstash-badtoken": "执行对应操作失败。可能是因为您的编辑凭证已过期。请重试。",
        "uploadstash-errclear": "清除文件失败。",
        "uploadstash-refresh": "更新文件列表",
+       "uploadstash-thumbnail": "显示缩略图",
        "invalid-chunk-offset": "无效区块偏移量",
        "img-auth-accessdenied": "拒绝访问",
        "img-auth-nopathinfo": "PATH_INFO缺失。\n您的服务器尚未设置传送该信息。\n它可能基于CGI,因而不支持img_auth。\n请参见https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization。",
        "changecontentmodel-title-label": "页面标题",
        "changecontentmodel-model-label": "新的内容模型",
        "changecontentmodel-reason-label": "原因:",
+       "changecontentmodel-submit": "更改",
        "changecontentmodel-success-title": "内容模型已更改",
        "changecontentmodel-success-text": "[[:$1]]的内容类型被更改。",
        "changecontentmodel-cannot-convert": "[[:$1]]上的内容不能转换为$2的一个类型。",
        "ipb-hardblock": "阻止登录用户使用该IP地址编辑",
        "ipbcreateaccount": "阻止创建新账号",
        "ipbemailban": "阻止用户发送电子邮件",
-       "ipbenableautoblock": "自动封禁该用户最后使用的IP地址,以及他们随后试图用于编辑的所有IP地址",
+       "ipbenableautoblock": "自动封禁该用户最后使用的IP地址,以及随后试图用于编辑的所有IP地址",
        "ipbsubmit": "封禁该用户",
        "ipbother": "其它时间:",
        "ipboptions": "2小时:2 hours,1天:1 day,3天:3 days,1周:1 week,2周:2 weeks,1个月:1 month,3个月:3 months,6个月:6 months,1年:1 year,不限期:infinite",
        "ipb-unblock": "解封用户名或IP地址",
        "ipb-blocklist": "查看现有封禁",
        "ipb-blocklist-contribs": "{{GENDER:$1|$1}}的贡献",
+       "ipb-blocklist-duration-left": "剩余$1",
        "unblockip": "解封用户",
        "unblockiptext": "使用下列表单来恢复之前被封禁的IP地址或用户名的写权限。",
        "ipusubmit": "解除此封禁",
        "import-logentry-upload-detail": "导入$1个{{PLURAL:$1|版本}}",
        "import-logentry-interwiki-detail": "来自$2的$1个{{PLURAL:$1|版本}}已导入",
        "javascripttest": "JavaScript测试",
-       "javascripttest-pagetext-noframework": "本页面被保留进行JavaScript测试。",
-       "javascripttest-pagetext-unknownframework": "未知的框架“$1”。",
        "javascripttest-pagetext-unknownaction": "未知操作“$1”。",
-       "javascripttest-pagetext-frameworks": "请选择以下的框架之一:$1",
-       "javascripttest-pagetext-skins": "选择外观来运行测试:",
        "javascripttest-qunit-intro": "请见mediawiki.org的[$1 测试说明文件]。",
        "tooltip-pt-userpage": "{{GENDER:|您的用户}}页",
-       "tooltip-pt-anonuserpage": "用于编辑的IP地址的用户页面",
+       "tooltip-pt-anonuserpage": "用于编辑的IP地址的用户页面",
        "tooltip-pt-mytalk": "{{GENDER:|您}}的讨论页面",
        "tooltip-pt-anontalk": "有关本IP地址的编辑的讨论",
        "tooltip-pt-preferences": "{{GENDER:|您}}的设置",
        "tooltip-ca-talk": "关于内容页面的讨论",
        "tooltip-ca-edit": "编辑本页",
        "tooltip-ca-addsection": "开始新段落",
-       "tooltip-ca-viewsource": "本页面受到保护。\n您可以查看其源代码",
+       "tooltip-ca-viewsource": "本页面受到保护。您可以查看其源代码",
        "tooltip-ca-history": "本页面过去的版本",
        "tooltip-ca-protect": "保护本页",
        "tooltip-ca-unprotect": "更改本页面的保护",
        "version-libraries-description": "描述",
        "version-libraries-authors": "作者",
        "redirect": "重定向(按文件、用户、页面、修订版本或日志ID)",
-       "redirect-legend": "重定向至文件或页面",
        "redirect-summary": "本特殊页面可以跳转至一个文件(提供文件名)、页面(提供修订版本ID或页面ID)、用户页(提供数字用户ID)或日志记录(提供日志ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]]、[[{{#Special:Redirect}}/user/101]]或[[{{#Special:Redirect}}/logid/186]]。",
        "redirect-submit": "提交",
        "redirect-lookup": "基于:",
        "revdelete-uname-unhid": "公开用户名",
        "revdelete-restricted": "应用对管理员的限制",
        "revdelete-unrestricted": "删除对管理员的限制",
-       "logentry-block-block": "$1{{GENDER:$2|å°\81ç¦\81äº\86}}{{GENDER:$4|$3}}ï¼\8cæ\8c\81ç»­æ\97¶é\97´$5 $6",
+       "logentry-block-block": "$1{{GENDER:$2|å°\81ç¦\81äº\86}}{{GENDER:$4|$3}}ï¼\8cæ\9c\9fé\99\90è\87³$5 $6",
        "logentry-block-unblock": "$1{{GENDER:$2|解封了}}{{GENDER:$4|$3}}",
        "logentry-block-reblock": "$1将{{GENDER:$4|$3}}的封禁设置{{GENDER:$2|更改为}}持续时间$5 $6",
        "logentry-suppress-block": "$1{{GENDER:$2|封禁了}}{{GENDER:$4|$3}},持续时间$5 $6",
        "logentry-protect-protect-cascade": "$1{{GENDER:$2|保护了}}$3 $4[级联]",
        "logentry-protect-modify": "$1{{GENDER:$2|更改了}}$3的保护等级$4",
        "logentry-protect-modify-cascade": "$1{{GENDER:$2|更改了}}$3的保护等级$4[级联]",
-       "logentry-rights-rights": "$1{{GENDER:$2|更改}}$3的用户组自$4至$5",
+       "logentry-rights-rights": "$1已将{{GENDER:$3|$3}}的用户组从$4{{GENDER:$2|更改}}至$5",
        "logentry-rights-rights-legacy": "$1更改$3的用户组",
        "logentry-rights-autopromote": "$1被自动地{{GENDER:$2|提升}}自$4至$5",
        "logentry-upload-upload": "$1{{GENDER:$2|上传}}$3",
        "api-error-unknownerror": "未知错误:$1。",
        "api-error-uploaddisabled": "该wiki停用上传。",
        "api-error-verification-error": "该文件可能损坏或扩展名错误。",
+       "api-error-was-deleted": "此名称的文件曾被上传,随后被删除。",
        "duration-seconds": "$1秒",
        "duration-minutes": "$1分",
        "duration-hours": "$1小时",
        "special-characters-group-ipa": "国际音标",
        "special-characters-group-symbols": "符号",
        "special-characters-group-greek": "希腊字母",
+       "special-characters-group-greekextended": "希腊字母扩展",
        "special-characters-group-cyrillic": "西里尔字母",
        "special-characters-group-arabic": "阿拉伯字母",
        "special-characters-group-arabicextended": "扩展阿拉伯字母",
        "sessionprovider-generic": "$1会话",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "基于cookie的会话",
        "sessionprovider-nocookies": "Cookie可能已被禁用。确保您已启用cookie,并重试。",
-       "randomrootpage": "随机根页面"
+       "randomrootpage": "随机根页面",
+       "log-action-filter-block": "封禁类型:",
+       "log-action-filter-delete": "删除类型:",
+       "log-action-filter-patrol": "巡查类型:",
+       "log-action-filter-protect": "保护类型:",
+       "log-action-filter-upload": "上传类型:",
+       "log-action-filter-all": "全部",
+       "log-action-filter-block-block": "封禁",
+       "log-action-filter-block-reblock": "封禁修改",
+       "log-action-filter-block-unblock": "解封",
+       "log-action-filter-delete-delete": "页面删除",
+       "log-action-filter-delete-restore": "页面还原",
+       "log-action-filter-delete-event": "日志删除",
+       "log-action-filter-delete-revision": "修订版本删除",
+       "log-action-filter-patrol-patrol": "手动巡查",
+       "log-action-filter-patrol-autopatrol": "自动巡查",
+       "log-action-filter-protect-protect": "保护",
+       "log-action-filter-protect-modify": "保护修改",
+       "log-action-filter-protect-unprotect": "解除保护",
+       "log-action-filter-upload-upload": "新上传",
+       "log-action-filter-upload-overwrite": "重新上传"
 }
index 3c4b6e8..04c2333 100644 (file)
@@ -68,7 +68,9 @@
                        "范",
                        "Jasonzhuocn",
                        "Bowleerin",
-                       "飞舞回堂前"
+                       "飞舞回堂前",
+                       "Bbslam",
+                       "Zerng07"
                ]
        },
        "tog-underline": "底線標示連結:",
        "feedlinks": "訂閱:",
        "feed-invalid": "無效的訂閱 Feed 類型。",
        "feed-unavailable": "目前未提供 RSS 或 Atom",
-       "site-rss-feed": "$1 的 RSS 摘要",
-       "site-atom-feed": "$1 的 Atom 摘要",
-       "page-rss-feed": "\"$1\" 的 RSS 摘要",
-       "page-atom-feed": "\"$1\" 的 Atom 摘要",
+       "site-rss-feed": "$1 的 RSS 來源",
+       "site-atom-feed": "$1 的 Atom 來源",
+       "page-rss-feed": "\"$1\" 的 RSS 來源",
+       "page-atom-feed": "\"$1\" 的 Atom 來源",
        "red-link-title": "$1 (頁面不存在)",
        "sort-descending": "降冪排序",
        "sort-ascending": "昇冪排序",
        "createaccount": "建立帳號",
        "gotaccount": "您已經擁有帳號了嗎? $1。",
        "gotaccountlink": "登入",
-       "userlogin-resetlink": "您忘記了登入的詳細資料?",
+       "userlogin-resetlink": "忘了您登入的詳細資料?",
        "userlogin-resetpassword-link": "忘記密碼?",
        "userlogin-helplink2": "登入協助",
        "userlogin-loggedin": "您目前已登入 {{GENDER:$1|$1}} 使用者,\n請使用下列表單改登入另一位使用者。",
        "newpassword": "新密碼:",
        "retypenew": "重新輸入新密碼:",
        "resetpass_submit": "設定密碼並登入",
-       "changepassword-success": "您的密碼已變更成功!",
+       "changepassword-success": "您的密碼已經變更!",
        "changepassword-throttled": "您最近嘗試了太多次登入。\n請等待 $1 後再試。",
        "botpasswords": "機器人密碼",
        "botpasswords-summary": "<em>機器人密碼</em> 可在不需帳號的主要登入密碼情況下,允許透過 API 存取使用者帳號。 可限制使用機器人密碼登入的使用者權限。\n\n若在尚無法了解為何要設定機器人密碼之前不應使用此功能。 且不該有任何人會向您索取機器人密碼。",
        "botpasswords-insert-failed": "新增機器人名稱 \"$1\" 失敗,是否已新增過?",
        "botpasswords-update-failed": "更新機器人名稱 \"$1\" 失敗,是否已刪除過?",
        "botpasswords-created-title": "已建立機器人密碼",
-       "botpasswords-created-body": "機器人密碼 \"$1\" 已建立成功。",
+       "botpasswords-created-body": "使用者''$2\"所擁有的機器人\"$1\"之密碼已建立。",
        "botpasswords-updated-title": "已更新機器人密碼",
-       "botpasswords-updated-body": "機器人密碼 \"$1\" 已修改成功。",
+       "botpasswords-updated-body": "使用者''$2\"所擁有的機器人\"$1\"之密碼已更新。",
        "botpasswords-deleted-title": "已刪除機器人密碼",
-       "botpasswords-deleted-body": "機器人密碼 \"$1\" 已刪除。",
+       "botpasswords-deleted-body": "使用者''$2\"所擁有的機器人\"$1\"之密碼已刪除。",
        "botpasswords-newpassword": "用來登入 <strong>$1</strong> 的新密碼為 <strong>$2</strong>。 <em>請記錄此密碼以供未來參考使用。</em>",
        "botpasswords-no-provider": "BotPasswordsSessionProvider 無法使用。",
        "botpasswords-restriction-failed": "機器人密碼限制已拒絕此次登入。",
        "resetpass-no-info": "您必須直接登入存取這個頁面。",
        "resetpass-submit-loggedin": "變更密碼",
        "resetpass-submit-cancel": "取消",
-       "resetpass-wrong-oldpass": "無效的臨時或現有密碼。\n您可能早已成功地變更了密碼,或者已經請求一個新的臨時密碼。",
+       "resetpass-wrong-oldpass": "無效的臨時或現有密碼。\n您可能已經變更了密碼,或者已經請求一個新的臨時密碼。",
        "resetpass-recycled": "請重設您的密碼為一個與目前不同的密碼。",
        "resetpass-temp-emailed": "您使用臨時電子郵件傳送的代碼登入。\n要完成登入,您必須在這裡設定一個新密碼:",
        "resetpass-temp-password": "臨時密碼:",
        "passwordreset-capture": "檢視電子郵件內容?",
        "passwordreset-capture-help": "若您勾選此核選方塊,電子郵件 (包含臨時密碼) 將直接顯示,並寄給使用者。",
        "passwordreset-email": "電子郵件地址:",
-       "passwordreset-emailtitle": "{{SITENAME}} 的帳號詳細資料",
+       "passwordreset-emailtitle": "在 {{SITENAME}} 的帳號詳細資料",
        "passwordreset-emailtext-ip": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件地址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略本訊息並且繼續使用您原本的密碼。",
        "passwordreset-emailtext-user": "使用者 $1 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件位址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
        "passwordreset-emailelement": "使用者名稱:\n$1\n\n臨時密碼:\n$2",
        "nosuchsectiontext": "您嘗試編輯的章節並不存在。\n可能在您檢視頁面時已經移動或刪除。",
        "loginreqtitle": "需要登入",
        "loginreqlink": "登入",
-       "loginreqpagetext": "æ\82¨å¿\85é \88 $1 æ\96¹å\8f¯æª¢è¦\96å\85¶ä»\96é \81é\9d¢ã\80\82",
+       "loginreqpagetext": "è«\8bå\85\88 $1 æ\96¹å\8f¯æª¢è¦\96å\85¶ä»\96é \81é\9d¢ã\80\82",
        "accmailtitle": "密碼已寄出",
        "accmailtext": "[[User talk:$1|$1]] 的隨機密碼已經寄送至 $2,可登入後至 <em>[[Special:ChangePassword|變更密碼]] 頁面更改</em>。",
        "newarticle": "(新)",
        "newarticletext": "您正連結至一頁不存在頁面。\n要建立該頁面,請在下方的編輯方塊中輸入內容 (詳情請參考 [$1 説明頁面]) 。\n如果您是不小心來到此頁面,請點選瀏覽器的 <strong>返回</strong> 按鈕。",
        "anontalkpagetext": "----\n<em>此討論頁面是給尚未建立帳號的匿名使用者使用</em>\n因此我們必須使用 IP 位址來辨識身份,但相同的 IP 位址可能由許多不同的使用者所共用。\n如果您是匿名使用者並且覺得評論的內容與您無關,請 [[Special:UserLogin/signup|建立新帳號]] 或 [[Special:UserLogin|登入]] 避免與其他匿名使用者混淆。",
-       "noarticletext": "此頁面目前沒有內容,您可以在其它頁面中[[Special:Search/{{PAGENAME}}|搜尋此頁面標題]]、<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜尋相關日誌]或[{{fullurl:{{FULLPAGENAME}}|action=edit}} 編輯此頁]</span>。",
+       "noarticletext": "此頁面目前沒有內容,您可以在其它頁面中[[Special:Search/{{PAGENAME}}|搜尋此頁面標題]]、<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜尋相關日誌]或[{{fullurl:{{FULLPAGENAME}}|action=edit}} 建立此頁]</span>。",
        "noarticletext-nopermission": "此頁面目前沒有內容,\n您可以在其它頁面中 [[Special:Search/{{PAGENAME}}|搜尋此頁面標題]],或 <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜尋相關日誌]</span>,但您沒有權限建立此頁面。",
        "missing-revision": "頁面名稱 \"{{FULLPAGENAME}}\" 的 #$1 修訂版本不存在。\n\n通常是因連結到過期的歷史頁面,該頁面已被刪除。\n詳情請參考 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌]。",
        "userpage-userdoesnotexist": "使用者帳號 \"$1\" 尚未註冊。\n若您要建立/編輯此頁面,請先檢查是否正確。",
        "previewnote": "<strong>您目前正在預覽,您的變更還尚未儲存!</strong>",
        "continue-editing": "前往編輯框",
        "previewconflict": "此預覽顯示了您於上方文字編輯框中的內容儲存之後將會顯示的結果。",
-       "session_fail_preview": "<strong>很抱歉!由於連線階段的資料遺失,我們無法處理您的編輯動作。</strong>\n請再試一次。\n如果仍然失敗,請 [[Special:UserLogout|登出]] 後重新登入。",
-       "session_fail_preview_html": "<strong>很抱歉!由於連線階段的資料遺失,我們無法處理您的編輯動作。</strong>\n\n<em>由於 {{SITENAME}} 開啟了原始 HTML 模式,將不會顯示預覽畫面以避免 JavaScript 攻擊。</em>\n\n<strong>若這是符合規範的編輯動作,請再試一次。</strong>\n如果仍然有問題,請 [[Special:UserLogout|登出]] 後再重新登入一次。",
+       "session_fail_preview": "很抱歉!由於連線階段的資料遺失,以至於我們無法處理您的編輯動作。\n您可能已經登出了。<strong>請您確認您仍然在登入狀態,並請再試一次<strong/>。\n請再試一次。\n如果仍然失敗,請 [[Special:UserLogout|登出]] 後重新登入,並請您確認您的瀏覽器允許此網站的Cookie。",
+       "session_fail_preview_html": "<strong>抱歉!由於是次登入時段出現資料遺失,我們無法處理您所作出的編輯。</strong>\n\n<em> {{SITENAME}} 已開啟了原始 HTML 模式,故此預覽畫面將不會顯示以避免 JavaScript 攻擊。</em>\n\n<strong>如您希望真正能夠作出這次編輯,請再試一次。</strong>\n如果仍不成功,請 [[Special:UserLogout|登出]] 後再重新登入,並確保瀏覽器設定為「允許這個網域的cookie」。",
        "token_suffix_mismatch": "<strong>因您使用的瀏覽器破壞了編輯密鑰中的特殊符號,您的編輯已被拒絕。</strong>\n為了避免破壞頁面內容,已拒絕此次編輯動作,\n會發生這個問題通常是因為您使用了有問題的匿名網頁代理伺服器。",
        "edit_form_incomplete": "<strong>部份編輯的內容未送至伺服器,請檢查您的編輯內容是否完整並再試一次。</strong>",
        "editing": "正在編輯 $1",
        "revdelete-unsuppress": "移除已還原修訂上的顯示限制",
        "revdelete-log": "原因:",
        "revdelete-submit": "套用至已選取的{{PLURAL:$1|一筆|多筆}}修訂",
-       "revdelete-success": "已成功更新修訂的顯示設定。",
+       "revdelete-success": "已成功更新檢示修訂內容的權限設定。",
        "revdelete-failure": "無法更新修訂的顯示設定:\n$1",
-       "logdelete-success": "å·²æ\88\90å\8a\9fæ\9b´æ\96°æ\97¥èª\8cç\9a\84顯示設定。",
+       "logdelete-success": "å·²æ\88\90å\8a\9fæ\9b´æ\96°æª¢è¦\96æ\97¥èª\8cç\9a\84æ¬\8aé\99\90設定。",
        "logdelete-failure": "無法更新日誌的顯示設定:\n$1",
        "revdel-restore": "變更能見度",
        "pagehist": "頁面歷史",
        "mergehistory-empty": "沒有可以合併的修訂",
        "mergehistory-done": "$1 中 $3 次修訂已合併至 [[:$2]]。",
        "mergehistory-fail": "無法進行歷史合併,請重新檢查該頁面及時間參數。",
+       "mergehistory-fail-bad-timestamp": "時間值無效。",
+       "mergehistory-fail-invalid-source": "來源頁面無效。",
+       "mergehistory-fail-invalid-dest": "目標頁面無效。",
+       "mergehistory-fail-no-change": "歷史合併尚未合併任何修訂歷史紀錄。請再次檢查頁面以及時間參數。",
+       "mergehistory-fail-permission": "權限不足,無法合併歷史。",
+       "mergehistory-fail-self-merge": "來源頁面與目標頁面的名稱相同。",
+       "mergehistory-fail-timestamps-overlap": "來源修訂版本重複,或在目標修訂版本之後才出現。",
        "mergehistory-fail-toobig": "超過 $1 個修訂移動的上限,無法進行歷史合併。",
        "mergehistory-no-source": "來源頁面 $1 不存在。",
        "mergehistory-no-destination": "目標頁面 $1 不存在。",
        "userrights-changeable-col": "您可變更的群組",
        "userrights-unchangeable-col": "您不可變更的群組",
        "userrights-conflict": "使用者權限變更發生衝突!請檢閱並確認你的變更。",
-       "userrights-removed-self": "您已成功移除自己的權限,您已無法再次存取此頁面。",
+       "userrights-removed-self": "您已移除自己的權限,故您已無法再次存取此頁面。",
        "group": "群組:",
        "group-user": "使用者",
        "group-autoconfirmed": "自動確認的使用者",
        "recentchanges-label-bot": "該編輯由機器人執行",
        "recentchanges-label-unpatrolled": "該編輯尚未巡查",
        "recentchanges-label-plusminus": "該頁面變更的大小 (位元組)",
-       "recentchanges-legend-heading": "<strong>說明:</strong>",
+       "recentchanges-legend-heading": "<strong>圖例:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (請參考[[Special:NewPages|新頁面]])",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "顯示",
        "rcshowhidecategorization": "$1 頁面分類",
        "rcshowhidecategorization-show": "顯示",
        "rcshowhidecategorization-hide": "隱藏",
-       "rclinks": "顯示最近 $2 天內的 $1 次更改。<br />$3",
+       "rclinks": "顯示最近 $2 天內的 $1 次變更。<br />$3",
        "diff": "差異",
        "hist": "歷史",
        "hide": "隱藏",
        "recentchangeslinked-page": "頁面名稱:",
        "recentchangeslinked-to": "改顯示連結至指定頁面的變更",
        "recentchanges-page-added-to-category": "[[:$1]] 已加入至分類",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] 與其他 {{PLURAL:$2|1 頁|$2 頁}}已加入至分類",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] 與[[Special:WhatLinksHere/$1|其他 {{PLURAL:$2|1 頁|$2 頁}}]]已加入至分類",
        "recentchanges-page-removed-from-category": "[[:$1]] 已自分類移除",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] 與其他 {{PLURAL:$2|1 頁|$2 頁}}已自分類移除",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] 與[[Special:WhatLinksHere/$1|其他 {{PLURAL:$2|1 頁|$2 頁}}]]已自分類移除",
        "autochange-username": "MediaWiki 自動變更",
        "upload": "上傳檔案",
        "uploadbtn": "上傳檔案",
        "backend-fail-read": "無法讀取檔案 \"$1\"。",
        "backend-fail-create": "無法寫入檔案 \"$1\"。",
        "backend-fail-maxsize": "由於檔案大小超過 $2 位元組,無法寫入檔案 \"$1\"​​。",
-       "backend-fail-readonly": "儲存庫的後端 \"$1\" 目前為唯讀模式。原因為:\"<em>$2</em>\"",
+       "backend-fail-readonly": "儲存庫的後端 \"$1\" 目前為唯讀模式。原因為:<em>$2</em>",
        "backend-fail-synced": "檔案 \"$1\" 與內部儲存庫後端內的狀態不一致。",
        "backend-fail-connect": "無法連結至儲存庫後端 \"$1\"。",
        "backend-fail-internal": "儲存庫後端 \"$1\" 發生了不明的錯誤。",
        "uploadstash-summary": "此頁面可存取已上傳或還在上傳程序但尚未在 Wiki 公開的檔案,這些檔案除了上傳的使用者本身外,其他人尚無法查看。",
        "uploadstash-clear": "清除儲藏庫檔案",
        "uploadstash-nofiles": "您沒有儲藏的檔案。",
-       "uploadstash-badtoken": "執行動作失敗您的編輯資訊可能已經過期,請重新再試。",
+       "uploadstash-badtoken": "執行動作失敗您的編輯資訊可能已經過期,請重新再試。",
        "uploadstash-errclear": "清除檔案失敗。",
        "uploadstash-refresh": "更新檔案清單",
+       "uploadstash-thumbnail": "檢視縮圖",
        "invalid-chunk-offset": "無效區塊位置",
        "img-auth-accessdenied": "拒絕存取",
        "img-auth-nopathinfo": "缺少 PATH_INFO 參數。\n您安裝的伺服器未傳遞此資訊,\n您可能使用 CGI 為基礎的伺服器,且不支援 img_auth 功能。\n請參考 https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization。",
        "apihelp": "API 說明",
        "apihelp-no-such-module": "查無模組 \"$1\"。",
        "apisandbox": "API 沙盒",
-       "apisandbox-api-disabled": "此網站已關閉 API 使用。",
-       "apisandbox-intro": "使用此頁面可測試 '''MediaWiki Web Service API'''。\n請參考 [//www.mediawiki.org/wiki/API:Main_page API 說明文件] 以取得詳細資訊。例:[//www.mediawiki.org/wiki/API#A_simple_example 取得主頁的內容]。 請選擇動作以取得更多範例。\n\n請注意,雖然此為沙盒,您在此頁所執行的動作仍有可能會修改到 Wiki。",
+       "apisandbox-jsonly": "需要 JavaScript 才能使用 API 沙箱。",
+       "apisandbox-api-disabled": "此網站已關閉 API。",
+       "apisandbox-intro": "使用此頁面可測試 <strong>MediaWiki web service API</strong>。\n請參考 [[mw:API:Main page|API 說明文件]] 以取得詳細資訊。例:[//www.mediawiki.org/wiki/API#A_simple_example 取得主頁的內容]。 請選擇動作以取得更多範例。\n\n請注意,雖然此為沙盒,您在此頁所執行的動作仍有可能會修改到 Wiki。",
        "apisandbox-fullscreen": "展開面板",
        "apisandbox-fullscreen-tooltip": "展開沙盒面板來填滿瀏覽器視窗。",
        "apisandbox-unfullscreen": "顯示頁面",
        "apisandbox-results": "結果",
        "apisandbox-sending-request": "傳送 API 請求中...",
        "apisandbox-loading-results": "接收 API 結果中...",
+       "apisandbox-results-error": "讀取 API 查詢回應時發生錯誤:$1。",
        "apisandbox-request-url-label": "請求 URL:",
        "apisandbox-request-time": "請求時間:{{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "更正密鑰並重新送出",
+       "apisandbox-results-fixtoken-fail": "取得 \"$1\" 密鑰失敗。",
+       "apisandbox-alert-page": "此頁面上的欄位無效。",
+       "apisandbox-alert-field": "此欄位的值無效。",
        "booksources": "圖書資源",
        "booksources-search-legend": "尋找圖書資源",
        "booksources-isbn": "國際標準書號:",
        "changecontentmodel-title-label": "頁面標題",
        "changecontentmodel-model-label": "新內容模型",
        "changecontentmodel-reason-label": "原因:",
+       "changecontentmodel-submit": "變更",
        "changecontentmodel-success-title": "已變更內容模型",
        "changecontentmodel-success-text": "已變更 [[:$1]] 的內容類型。",
        "changecontentmodel-cannot-convert": "[[:$1]] 的內容無法轉換為 $2 類型。",
        "changecontentmodel-nodirectediting": "$1 的內容模型不支援直接編輯",
        "log-name-contentmodel": "內容模型變更日誌",
        "log-description-contentmodel": "與頁面內容模型相關的事件",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|已使用}}非預設的內容模型 \"$5\" 建立頁面 $3",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|已變更}}頁面 $3 的內容模型自 \"$4\" 至 \"$5\"",
        "logentry-contentmodel-change-revertlink": "還原",
        "logentry-contentmodel-change-revert": "還原",
        "block-log-flags-hiddenname": "隱藏使用者名稱",
        "range_block_disabled": "管理員可建立範圍封鎖的權限已被關閉。",
        "ipb_expiry_invalid": "無效的期限。",
+       "ipb_expiry_old": "到期時間已過。",
        "ipb_expiry_temp": "隱藏使用者名稱的封鎖不可設定期限。",
        "ipb_hide_invalid": "無法禁止顯示此帳號;它擁有超過 $1 次的編輯。",
        "ipb_already_blocked": "已經封鎖 \"$1\"。",
        "import": "匯入頁面",
        "importinterwiki": "從其他 wiki 匯入",
        "import-interwiki-text": "請選擇一個 Wiki 與頁面標題以進行匯入。\n會同時記錄修訂日期和編輯者的名稱。\n所有的從跨 Wiki 匯入操作都會被記錄在 [[Special:Log/import|匯入日誌]]。",
-       "import-interwiki-sourcewiki": "來源 Wiki:",
+       "import-interwiki-sourcewiki": "來源 wiki:",
        "import-interwiki-sourcepage": "來源頁面:",
        "import-interwiki-history": "複製此頁面的所有歷史修訂",
        "import-interwiki-templates": "包含所有模板",
        "import-nonewrevisions": "未匯入任何修訂 (修訂已存在,或因錯誤跳過)。",
        "xml-error-string": "$1 於行 $2,欄 $3 ($4 位元組):$5",
        "import-upload": "上傳 XML 資料",
-       "import-token-mismatch": "連線階段資料遺失。\n請再試一次。",
+       "import-token-mismatch": "連線階段資料遺失。\n\n您可能已被登出。<strong>請確認您是否仍在登入狀態並再試一次</strong>。\n若仍無法運作,請嘗試[[Special:UserLogout|登出]]再登入一次,並檢查您的瀏覽器是否允許本站使用 cookie。",
        "import-invalid-interwiki": "不能從指定的 Wiki 匯入。",
        "import-error-edit": "您沒有權限編輯頁面 \"$1\",無法匯入。",
        "import-error-create": "您沒有權限建立頁面 \"$1\",無法匯入。",
        "import-logentry-upload-detail": "已匯入 $1 筆{{PLURAL:$1|修訂}}",
        "import-logentry-interwiki-detail": "已從 $2 匯入 $1 筆{{PLURAL:$1|修訂}}",
        "javascripttest": "JavaScript 測試",
-       "javascripttest-pagetext-noframework": "此頁面保留用來作為 JavaScript 測試使用。",
-       "javascripttest-pagetext-unknownframework": "不明的測試 Framework \"$1\"。",
        "javascripttest-pagetext-unknownaction": "不明操作 \"$1\"。",
-       "javascripttest-pagetext-frameworks": "請選擇下列一種測試 Framework:$1",
-       "javascripttest-pagetext-skins": "選擇執行測試的外觀:",
        "javascripttest-qunit-intro": "請參考 mediawiki.org 的 [$1 測試說明文件]。",
        "tooltip-pt-userpage": "{{GENDER:|您的使用者}}頁面",
        "tooltip-pt-anonuserpage": "您正在作為以下身分編輯此 IP 位址的使用者頁面",
        "tooltip-ca-talk": "有關頁面內容的討論",
        "tooltip-ca-edit": "編輯此頁面",
        "tooltip-ca-addsection": "開始一個新章節",
-       "tooltip-ca-viewsource": "此頁面已被保護。\n您可檢視此頁面原始碼",
+       "tooltip-ca-viewsource": "此頁面已被保護。您可檢視此頁面原始碼",
        "tooltip-ca-history": "此頁面先前的修訂",
        "tooltip-ca-protect": "保護此頁面",
        "tooltip-ca-unprotect": "變更此頁面保護",
        "tooltip-n-mainpage-description": "前往首頁",
        "tooltip-n-portal": "關於本專案、您可以做什麼、哪裡可以找到您需要的事物",
        "tooltip-n-currentevents": "於新聞事件中找到相關背景資料",
-       "tooltip-n-recentchanges": "列出此Wiki中的最近更改清單",
+       "tooltip-n-recentchanges": "列出此 Wiki 中的最近變更清單",
        "tooltip-n-randompage": "隨機進入一個頁面",
        "tooltip-n-help": "尋求協助的地方",
        "tooltip-t-whatlinkshere": "列出所有連結此頁面的頁面",
        "tooltip-t-recentchangeslinked": "此頁面連結至其他頁面的最近變更",
-       "tooltip-feed-rss": "此頁面的 RSS 摘要",
-       "tooltip-feed-atom": "此頁面的 Atom 摘要",
+       "tooltip-feed-rss": "此頁面的 RSS 來源",
+       "tooltip-feed-atom": "此頁面的 Atom 來源",
        "tooltip-t-contributions": "{{GENDER:$1|此使用者}}的貢獻清單",
        "tooltip-t-emailuser": "傳送電子郵件聯絡{{GENDER:$1|這位使用者}}",
        "tooltip-t-info": "更多關於此頁面的資訊",
        "version-antispam": "垃圾訊息防止",
        "version-other": "其他",
        "version-mediahandlers": "媒體處理器",
-       "version-hooks": "鉤",
+       "version-hooks": "鉤",
        "version-parser-extensiontags": "解析器擴充標籤",
-       "version-parser-function-hooks": "剖析器函數鉤",
-       "version-hook-name": "鉤名",
+       "version-parser-function-hooks": "語法分析函數掛鉤",
+       "version-hook-name": "掛鉤名稱",
        "version-hook-subscribedby": "署名",
        "version-version": "($1)",
        "version-no-ext-name": "[未命名]",
        "version-libraries-description": "描述",
        "version-libraries-authors": "作者",
        "redirect": "依檔案、使用者、頁面、修訂或日誌 ID 來重新導向",
-       "redirect-legend": "重新導向至檔案或頁面",
        "redirect-summary": "此特殊頁面可用來重新導向至檔案 (指定檔案名稱)、頁面 (指定修訂 ID 或頁面 ID)、使用者頁面 (指定使用者 ID)、或者日誌項目 (指定日誌 ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]]、[[{{#Special:Redirect}}/user/101]] 或 [[{{#Special:Redirect}}/logid/186]]。",
        "redirect-submit": "執行",
        "redirect-lookup": "查詢:",
        "tags-deactivate": "停用",
        "tags-hitcount": "$1 次變更",
        "tags-manage-no-permission": "您沒有權限管理變更標籤。",
+       "tags-manage-blocked": "您無法在被封鎖的情況下管理變更標籤。",
        "tags-create-heading": "建立新標籤",
        "tags-create-explanation": "在預設情況下,新建立的標籤可被使用者及機器人使用。",
        "tags-create-tag-name": "標籤名稱:",
        "tags-delete-not-allowed": "無法刪除由擴充套件定義的標籤,除非該擴充套件允許。",
        "tags-delete-not-found": "標籤 \"$1\" 不存在。",
        "tags-delete-too-many-uses": "標籤 \"$1\" 會套用至 $2 筆以上的{{PLURAL:$2|修訂|修訂}},這代表該標籤將無法刪除。",
-       "tags-delete-warnings-after-delete": "標籤 \"$1\" 已刪除成功,但發生下列{{PLURAL:$2|警告|警告}}:",
+       "tags-delete-warnings-after-delete": "標籤 \"$1\" 已刪除,但發生下列{{PLURAL:$2|警告|警告}}:",
        "tags-activate-title": "啟動標籤",
        "tags-activate-question": "您正要啟動標籤 \"$1\"。",
        "tags-activate-reason": "原因:",
        "tags-deactivate-not-allowed": "無法停用標籤 \"$1\"。",
        "tags-deactivate-submit": "停用",
        "tags-apply-no-permission": "您沒有權限連同您的變更一起套用標籤。",
+       "tags-apply-blocked": "您無法在被封鎖的情況下套用變更標籤為您的變更。",
        "tags-apply-not-allowed-one": "不允許手動套用標籤 \"$1\"。",
        "tags-apply-not-allowed-multi": "不允許手動套用以下{{PLURAL:$2|標籤|標籤}}:$1",
        "tags-update-no-permission": "您沒有權限加入與移除任何於各別修訂與日誌項目的標籤",
+       "tags-update-blocked": "您無法在被封鎖的情況下移除變更標籤。",
        "tags-update-add-not-allowed-one": "不允許手動加入標籤 \"$1\"。",
        "tags-update-add-not-allowed-multi": "不允許手動加入以下{{PLURAL:$2|標籤|標籤}}:$1",
        "tags-update-remove-not-allowed-one": "不允許手動移除標籤 \"$1\"。",
        "tags-edit-reason": "原因:",
        "tags-edit-revision-submit": "套用變更至{{PLURAL:$1|此修訂|$1 筆修訂}}",
        "tags-edit-logentry-submit": "套用變更至{{PLURAL:$1|此日誌項目|$1 筆日誌項目}}",
-       "tags-edit-success": "已成功套用變更。",
+       "tags-edit-success": "已套用變更。",
        "tags-edit-failure": "變更被無法套用:\n$1",
        "tags-edit-nooldid-title": "無效的目標修訂",
        "tags-edit-nooldid-text": "您沒有指定任何要執行此功能的目標修訂或指定的修訂並不存在。",
        "expand_templates_preview": "預覽",
        "expand_templates_preview_fail_html": "<em>因連線階段的資料遺失且 {{SITENAME}} 已開啟顯示原始 HTML 功能,為預防 JavaScript 攻擊已隱藏預覽內容。</em>\n\n<strong>若您目前的預覽動作並無非法,請再試一次。</strong>\n若仍然無效,請嘗試[[Special:UserLogout|登出]]並再登入一次。",
        "expand_templates_preview_fail_html_anon": "<em>因您尚未登入且 {{SITENAME}} 已開啟顯示原始 HTML 功能,為預防 JavaScript 攻擊已隱藏預覽內容。</em>\n\n<strong>若您目前的預覽動作並無非法,請[[Special:UserLogin|登入]]後再試一次。</strong>",
+       "expand_templates_input_missing": "您至少需要提供一些輸入文字。",
        "pagelanguage": "變更頁面語言",
        "pagelang-name": "頁面",
        "pagelang-language": "語言",
        "mw-widgets-titleinput-description-new-page": "頁面不存在",
        "mw-widgets-titleinput-description-redirect": "重新導向至 $1",
        "api-error-blacklisted": "請選擇另一個更具描述性的標題。",
+       "sessionmanager-tie": "無法合併多個請求認証類型:$1。",
        "sessionprovider-generic": "$1 連線階段",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "以 cookie 為基礎的連線階段",
        "sessionprovider-nocookies": "Cookie 功能可能已被關閉,請確認您改開啟 Cookie 功能並重新啟動。",
-       "randomrootpage": "隨機根頁面"
+       "randomrootpage": "隨機根頁面",
+       "log-action-filter-block": "封鎖類型:",
+       "log-action-filter-delete": "刪除類型:",
+       "log-action-filter-patrol": "巡查類型:",
+       "log-action-filter-protect": "保護類型:",
+       "log-action-filter-upload": "上傳類型:",
+       "log-action-filter-all": "全部",
+       "log-action-filter-block-block": "封鎖",
+       "log-action-filter-block-reblock": "封鎖修改",
+       "log-action-filter-block-unblock": "解除封鎖",
+       "log-action-filter-delete-delete": "頁面刪除",
+       "log-action-filter-delete-restore": "頁面取消刪除",
+       "log-action-filter-delete-event": "日誌刪除",
+       "log-action-filter-delete-revision": "修訂刪除",
+       "log-action-filter-patrol-patrol": "手動巡查",
+       "log-action-filter-patrol-autopatrol": "自動巡查",
+       "log-action-filter-protect-protect": "保護",
+       "log-action-filter-protect-modify": "保護修改",
+       "log-action-filter-protect-unprotect": "解除保護",
+       "log-action-filter-upload-upload": "新上傳",
+       "log-action-filter-upload-overwrite": "重新上傳"
 }
index 181032c..d6dab21 100644 (file)
@@ -59,12 +59,12 @@ $magicWords = [
        'namespace'                 => [ '1', 'NAAMSPASIE', 'NAMESPACE' ],
        'talkspace'                 => [ '1', 'BESPREKINGSBLADSY', 'TALKSPACE' ],
        'fullpagename'              => [ '1', 'VOLBLADSYNAAM', 'FULLPAGENAME' ],
-       'img_thumbnail'             => [ '1', 'duimnael', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'duimnael', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'regs', 'right' ],
        'img_left'                  => [ '1', 'links', 'left' ],
        'img_none'                  => [ '1', 'geen', 'none' ],
        'img_center'                => [ '1', 'senter', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'omraam', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'omraam', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'raamloos', 'frameless' ],
        'img_border'                => [ '1', 'raam', 'border' ],
        'img_top'                   => [ '1', 'bo', 'top' ],
index 33b1107..038566b 100644 (file)
@@ -44,7 +44,7 @@ $magicWords = [
        'namespace'                 => [ '1', 'ESPACIODENOMBRES', 'ESPACIODENOMBRE', 'NAMESPACE' ],
        'namespacee'                => [ '1', 'ESPACIODENOMBRESE', 'ESPACIODENOMBREC', 'NAMESPACEE' ],
        'img_right'                 => [ '1', 'dreita', 'derecha', 'dcha', 'der', 'right' ],
-       'img_left'                  => [ '1', 'cucha', 'zurda', 'izquierda', 'izda', 'izq', 'left' ],
+       'img_left'                  => [ '1', 'cucha', 'izquierda', 'zurda', 'izda', 'izq', 'left' ],
        'ns'                        => [ '0', 'EN:', 'EDN:', 'NS:' ],
        'displaytitle'              => [ '1', 'TÍTOL', 'MOSTRARTÍTULO', 'MOSTRARTITULO', 'DISPLAYTITLE' ],
        'currentversion'            => [ '1', 'BERSIÓNAUTUAL', 'BERSIONAUTUAL', 'REVISIÓNACTUAL', 'VERSIONACTUAL', 'VERSIÓNACTUAL', 'CURRENTVERSION' ],
index e76e419..a83b717 100644 (file)
@@ -196,14 +196,14 @@ $magicWords = [
        'subst'                     => [ '0', 'نسخ:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'نسخ_آمن:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'رسالة_بدون_تهيئة:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'تصغير', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'تصغير', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'تصغير=$1', 'مصغر=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'يمين', 'right' ],
        'img_left'                  => [ '1', 'يسار', 'left' ],
        'img_none'                  => [ '1', 'بدون', 'بلا', 'none' ],
        'img_width'                 => [ '1', '$1بك', '$1عن', '$1px' ],
        'img_center'                => [ '1', 'مركز', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'إطار', 'بإطار', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'إطار', 'بإطار', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'لاإطار', 'frameless' ],
        'img_lang'                  => [ '1', 'لغة=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'صفحة=$1', 'صفحة_$1', 'page=$1', 'page $1' ],
index 91dc377..0c1b668 100644 (file)
@@ -108,7 +108,7 @@ $magicWords = [
        'pagenamee'                 => [ '1', 'ܟܘܢܝܐ_ܕܦܐܬܐ', 'PAGENAMEE' ],
        'namespace'                 => [ '1', 'ܚܩܠܐ', 'NAMESPACE' ],
        'msg'                       => [ '0', 'ܐܓܪܬܐ:', 'MSG:' ],
-       'img_thumbnail'             => [ '1', 'ܙܥܘܪܬܐ', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'ܙܥܘܪܬܐ', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'ܙܥܘܪܬܐ=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'ܝܡܝܢܐ', 'right' ],
        'img_left'                  => [ '1', 'ܣܡܠܐ', 'left' ],
index f3377ae..2e69353 100644 (file)
@@ -208,15 +208,15 @@ $magicWords = [
        'subst'                     => [ '0', 'نسخ:', 'إحلال:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'نسخ_آمن:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'رسالة_من_غير_تهيئه:', 'رسالة_بدون_تهيئة:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'تصغير', 'مصغر', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'تصغير', 'مصغر', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'تصغير=$1', 'مصغر=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'يمين', 'right' ],
        'img_left'                  => [ '1', 'يسار', 'left' ],
        'img_none'                  => [ '1', 'بدون', 'بلا', 'none' ],
        'img_width'                 => [ '1', '$1بك', '$1عن', '$1px' ],
        'img_center'                => [ '1', 'مركز', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'إطار', 'بإطار', 'framed', 'enframed', 'frame' ],
-       'img_frameless'             => [ '1', 'Ù\85Ù\86_غÙ\8aر_اطار', 'Ù\84اإطار', 'frameless' ],
+       'img_framed'                => [ '1', 'إطار', 'بإطار', 'frame', 'framed', 'enframed' ],
+       'img_frameless'             => [ '1', 'Ù\84اإطار', 'Ù\85Ù\86_غÙ\8aر_اطار', 'frameless' ],
        'img_lang'                  => [ '1', 'لغه=$1', 'لغة=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'صفح=$1', 'صفحه_$1', 'صفحة=$1', 'صفحة_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'معدول', 'معدول=$1', 'معدول_$1', 'upright', 'upright=$1', 'upright $1' ],
index 840d17b..92ca0f8 100644 (file)
@@ -81,6 +81,6 @@ $magicWords = [
        'img_right'                 => [ '1', 'ساغ', 'راست', 'right' ],
        'img_left'                  => [ '1', 'سول', 'چپ', 'left' ],
        'img_none'                  => [ '1', 'هئچ', 'هیچ', 'none' ],
-       'img_framed'                => [ '1', 'قابیق', 'قاب', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'قابیق', 'قاب', 'frame', 'framed', 'enframed' ],
 ];
 
index 475ba9b..0b0d42e 100644 (file)
@@ -67,7 +67,7 @@ $magicWords = [
        'img_left'                  => [ '1', 'wala', 'left' ],
        'img_none'                  => [ '1', 'mayò', 'none' ],
        'img_center'                => [ '1', 'sentro', 'tangâ', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'nakakawadro', 'kwadro', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'nakakawadro', 'kwadro', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'daing kwadro', 'frameless' ],
        'img_page'                  => [ '1', 'pahina=$1', 'pahina $1', 'page=$1', 'page $1' ],
        'localurl'                  => [ '0', 'LOKALURL', 'LOCALURL:' ],
index c306ba4..9822436 100644 (file)
@@ -34,14 +34,14 @@ $namespaceAliases = [
 ];
 
 $magicWords = [
-       'img_thumbnail'             => [ '1', 'міні', 'мініяцюра', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'міні', 'мініяцюра', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'міні=$1', 'мініяцюра=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'справа', 'right' ],
        'img_left'                  => [ '1', 'злева', 'left' ],
        'img_none'                  => [ '1', 'няма', 'none' ],
        'img_width'                 => [ '1', '$1пкс', '$1px' ],
        'img_center'                => [ '1', 'цэнтр', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'безрамкі', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'безрамкі', 'frame', 'framed', 'enframed' ],
 ];
 
 $bookstoreList = [
index d775d25..74b7fe0 100644 (file)
@@ -162,14 +162,14 @@ $magicWords = [
        'msg'                       => [ '0', 'СЪОБЩ:', 'MSG:' ],
        'subst'                     => [ '0', 'ЗАМЕСТ:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'СЪОБЩБУ:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'мини', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'мини', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'мини=$1', 'thumbnail=$1', 'thumb=$1' ],
-       'img_right'                 => [ '1', 'вдÑ\8fÑ\81но', 'дясно', 'д', 'right' ],
-       'img_left'                  => [ '1', 'влÑ\8fво', 'ляво', 'л', 'left' ],
+       'img_right'                 => [ '1', 'дÑ\8fÑ\81но', 'вдясно', 'д', 'right' ],
+       'img_left'                  => [ '1', 'лÑ\8fво', 'вляво', 'л', 'left' ],
        'img_none'                  => [ '1', 'н', 'none' ],
        'img_width'                 => [ '1', '$1пкс', '$1п', '$1px' ],
-       'img_center'                => [ '1', 'център', 'центр', 'ц', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'рамка', 'врамка', 'framed', 'enframed', 'frame' ],
+       'img_center'                => [ '1', 'център', 'ц', 'центр', 'center', 'centre' ],
+       'img_framed'                => [ '1', 'рамка', 'врамка', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'безрамка', 'frameless' ],
        'img_border'                => [ '1', 'ръб', 'контур', 'border' ],
        'int'                       => [ '0', 'ВЪТР:', 'INT:' ],
index c020b09..6211da2 100644 (file)
@@ -13,7 +13,7 @@ $namespaceNames = [
        NS_SPECIAL          => 'Posebno',
        NS_TALK             => 'Razgovor',
        NS_USER             => 'Korisnik',
-       NS_USER_TALK        => 'Razgovor_sa_korisnikom',
+       NS_USER_TALK        => 'Razgovor_s_korisnikom',
        NS_PROJECT_TALK     => 'Razgovor_{{grammar:instrumental|$1}}',
        NS_FILE             => 'Datoteka',
        NS_FILE_TALK        => 'Razgovor_o_datoteci',
@@ -28,6 +28,7 @@ $namespaceNames = [
 ];
 
 $namespaceAliases = [
+       'Razgovor_sa_korisnikom' => NS_USER_TALK,
        'Medija' => NS_MEDIA,
        'Slika' => NS_FILE,
        'Razgovor_o_datoteci' => NS_FILE_TALK,
@@ -186,14 +187,14 @@ $magicWords = [
        'msg'                       => [ '0', 'POR:', 'MSG:' ],
        'subst'                     => [ '0', 'ZAMJENI:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'NVPOR:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'mini', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'desno', 'd', 'right' ],
        'img_left'                  => [ '1', 'lijevo', 'l', 'left' ],
        'img_none'                  => [ '1', 'n', 'bez', 'none' ],
        'img_width'                 => [ '1', '$1piksel', '$1p', '$1px' ],
        'img_center'                => [ '1', 'centar', 'c', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'okvir', 'ram', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'okvir', 'ram', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'bez_okvira', 'frameless' ],
        'img_page'                  => [ '1', 'stranica=$1', 'stranica $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'na_gore', 'na_gore=$1', 'na_gore_$1', 'upright', 'upright=$1', 'upright $1' ],
index d83a364..d442f07 100644 (file)
@@ -221,20 +221,20 @@ $magicWords = [
        'msg'                       => [ '0', 'ХААМ:', 'СООБЩЕНИЕ:', 'СООБЩ:', 'MSG:' ],
        'subst'                     => [ '0', 'ХӀОТТОР:', 'ХӀОТТ:', 'ПОДСТАНОВКА:', 'ПОДСТ:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'ВИКИ_ХААМ_БОЦАШ:', 'СООБЩ_БЕЗ_ВИКИ:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'жима', 'жимо', 'мини', 'миниаÑ\82Ñ\8eÑ\80а', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'мини', 'жима', 'жимо', 'миниаÑ\82Ñ\8eÑ\80а', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'жима=$1', 'жимо=$1', 'мини=$1', 'миниатюра=$1', 'thumbnail=$1', 'thumb=$1' ],
-       'img_right'                 => [ '1', 'бакъхьа', 'справа', 'right' ],
-       'img_left'                  => [ '1', 'Ñ\85аÑ\80Ñ\86Ñ\85Ñ\8cа', 'Ñ\81лева', 'left' ],
+       'img_right'                 => [ '1', 'справа', 'бакъхьа', 'right' ],
+       'img_left'                  => [ '1', 'Ñ\81лева', 'Ñ\85аÑ\80Ñ\86Ñ\85Ñ\8cа', 'left' ],
        'img_none'                  => [ '1', 'йоцуш', 'без', 'none' ],
        'img_width'                 => [ '1', '$1пкс', '$1px' ],
-       'img_center'                => [ '1', 'Ñ\8eккÑ\8a', 'Ñ\86енÑ\82Ñ\80', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'гурабе', 'обрамить', 'framed', 'enframed', 'frame' ],
-       'img_frameless'             => [ '1', 'гÑ\83Ñ\80абоÑ\86аÑ\88', 'безÑ\80амки', 'frameless' ],
+       'img_center'                => [ '1', 'Ñ\86енÑ\82Ñ\80', 'Ñ\8eккÑ\8a', 'center', 'centre' ],
+       'img_framed'                => [ '1', 'гурабе', 'обрамить', 'frame', 'framed', 'enframed' ],
+       'img_frameless'             => [ '1', 'безÑ\80амки', 'гÑ\83Ñ\80абоÑ\86аÑ\88', 'frameless' ],
        'img_page'                  => [ '1', 'агlо=$1', 'агlо_$1', 'page_$1', 'страница=$1', 'страница_$1', 'страница $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'бакъхьалакхо', 'бакъхьалакхо=$1', 'бакъхьалакхо_$1', 'upright_$1', 'сверхусправа', 'сверхусправа=$1', 'сверхусправа_$1', 'сверхусправа $1', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', 'доза', 'граница', 'border' ],
        'img_baseline'              => [ '1', 'бух', 'основание', 'baseline' ],
-       'img_sub'                   => [ '1', 'бÑ\83Ñ\85а', 'под', 'sub' ],
+       'img_sub'                   => [ '1', 'под', 'бÑ\83Ñ\85а', 'sub' ],
        'img_super'                 => [ '1', 'тӀе', 'над', 'super', 'sup' ],
        'img_top'                   => [ '1', 'лакхахь', 'сверху', 'top' ],
        'img_text_top'              => [ '1', 'лакххьара-йоза', 'текст-сверху', 'text-top' ],
index a010c2c..ad45b66 100644 (file)
@@ -109,12 +109,12 @@ $specialPageAliases = [
 ];
 
 $magicWords = [
-       'img_thumbnail'             => [ '1', 'وێنۆک', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'وێنۆک', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'ڕاست', 'right' ],
        'img_left'                  => [ '1', 'چەپ', 'left' ],
        'img_width'                 => [ '1', '$1پیکسڵ', '$1px' ],
        'img_center'                => [ '1', 'ناوەڕاست', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'چوارچێوە', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'چوارچێوە', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'بێچوارچێوە', 'frameless' ],
        'img_border'                => [ '1', 'سنوور', 'border' ],
 ];
index 3cd652b..548b78c 100644 (file)
@@ -72,12 +72,12 @@ $specialPageAliases = [
        'Filepath'                  => [ 'Cesta_k_souboru' ],
        'Import'                    => [ 'Importovat_stránky' ],
        'Invalidateemail'           => [ 'Zneplatnit_e-mail', 'Zrušit_potvrzení_e-mailu' ],
-       'BlockList'                 => [ 'Blokovaní_uživatelé', 'Blokovani_uzivatele' ],
+       'BlockList'                 => [ 'Blokovaní_uživatelé', 'Blokovani_uzivatele', 'Zablokovaní_uživatelé' ],
        'LinkSearch'                => [ 'Hledání_odkazů', 'Hledani_odkazu' ],
        'Listadmins'                => [ 'Seznam_správců', 'Seznam_spravcu' ],
        'Listbots'                  => [ 'Seznam_botů', 'Seznam_botu' ],
        'Listfiles'                 => [ 'Seznam_souborů', 'Seznam_souboru' ],
-       'Listgrouprights'           => [ 'Seznam_uživatelských_práv', 'Seznam_uzivatelskych_prav' ],
+       'Listgrouprights'           => [ 'Práva_uživatelských_skupin', 'Seznam_uživatelských_práv', 'Seznam_uzivatelskych_prav' ],
        'Listredirects'             => [ 'Seznam_přesměrování', 'Seznam_presmerovani' ],
        'Listusers'                 => [ 'Uživatelé', 'Uzivatele', 'Seznam_uživatelů', 'Seznam_uzivatelu' ],
        'Lockdb'                    => [ 'Zamknout_databázi', 'Zamknout_databazi' ],
@@ -92,7 +92,7 @@ $specialPageAliases = [
        'Mostlinkedcategories'      => [ 'Nejpoužívanější_kategorie', 'Nejpouzivanejsi_kategorie' ],
        'Mostlinkedtemplates'       => [ 'Nejpoužívanější_šablony', 'Nejpouzivanejsi_sablony' ],
        'Mostrevisions'             => [ 'Stránky_s_nejvíce_editacemi', 'Stranky_s_nejvice_editacemi', 'Stránky_s_nejvyšším_počtem_editací' ],
-       'Movepage'                  => [ 'Přesunout_stránku' ],
+       'Movepage'                  => [ 'Přesunout_stránku', 'Přejmenovat_stránku' ],
        'Mycontributions'           => [ 'Mé_příspěvky', 'Me_prispevky' ],
        'Mypage'                    => [ 'Moje_stránka', 'Moje_stranka' ],
        'Mytalk'                    => [ 'Moje_diskuse' ],
@@ -191,14 +191,14 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'NÁZEVČLÁNKUE', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'subst'                     => [ '0', 'VLOŽIT:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'VLOŽITNW:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'náhled', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'náhled', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'náhled=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'vpravo', 'right' ],
        'img_left'                  => [ '1', 'vlevo', 'left' ],
        'img_none'                  => [ '1', 'žádné', 'none' ],
        'img_width'                 => [ '1', '$1pixelů', '$1px' ],
        'img_center'                => [ '1', 'střed', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'rám', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'rám', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'bezrámu', 'frameless' ],
        'img_lang'                  => [ '1', 'jazyk=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'strana=$1', 'strana_$1', 'page=$1', 'page $1' ],
index 8306461..a569f16 100644 (file)
@@ -53,7 +53,7 @@ $magicWords = [
        'subpagenamee'              => [ '1', 'ENWISDUDALENE', 'SUBPAGENAMEE' ],
        'talkpagename'              => [ '1', 'ENWTUDALENSGWRS', 'TALKPAGENAME' ],
        'talkpagenamee'             => [ '1', 'ENWTUDALENSGWRSE', 'TALKPAGENAMEE' ],
-       'img_thumbnail'             => [ '1', 'ewin_bawd', 'bawd', 'mân-lun', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'bawd', 'ewin_bawd', 'mân-lun', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'mân-lun=$1', 'bawd=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'de', 'right' ],
        'img_left'                  => [ '1', 'chwith', 'left' ],
index 0a53ff5..5fc359e 100644 (file)
@@ -208,21 +208,21 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'HAUPTSEITENNAME_URL', 'VORDERSEITE_URL', 'HAUPTSEITE_URL', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'subst'                     => [ '0', 'ERS:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'SICHER_ERS:', 'SICHERERS:', 'SAFESUBST:' ],
-       'img_thumbnail'             => [ '1', 'mini', 'miniatur', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatur', 'mini', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatur=$1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'rechts', 'right' ],
        'img_left'                  => [ '1', 'links', 'left' ],
        'img_none'                  => [ '1', 'ohne', 'none' ],
        'img_center'                => [ '1', 'zentriert', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'gerahmt', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'gerahmt', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'rahmenlos', 'frameless' ],
        'img_lang'                  => [ '1', 'sprache=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'seite=$1', 'seite_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'hochkant', 'hochkant=$1', 'hochkant_$1', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', 'rand', 'border' ],
        'img_baseline'              => [ '1', 'grundlinie', 'baseline' ],
-       'img_sub'                   => [ '1', 'tiefgestellt', 'tief', 'sub' ],
-       'img_super'                 => [ '1', 'hochgestellt', 'hoch', 'super', 'sup' ],
+       'img_sub'                   => [ '1', 'tief', 'tiefgestellt', 'sub' ],
+       'img_super'                 => [ '1', 'hoch', 'hochgestellt', 'super', 'sup' ],
        'img_top'                   => [ '1', 'oben', 'top' ],
        'img_text_top'              => [ '1', 'text-oben', 'text-top' ],
        'img_middle'                => [ '1', 'mitte', 'middle' ],
index 03cf459..c81fd34 100644 (file)
@@ -224,14 +224,14 @@ $magicWords = [
        'subst'                     => [ '0', 'KOPYAKE', 'ATEBERDE', 'SUBST:' ],
        'safesubst'                 => [ '0', 'EMELEYATEBERDE', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'MSCNW:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'resmoqıckek', 'qıckek', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'resmoqıckek', 'qıckek', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'resmoqıckek=$1', 'qıckek=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'raşt', 'right' ],
        'img_left'                  => [ '1', 'çep', 'left' ],
        'img_none'                  => [ '1', 'çıniyo', 'none' ],
        'img_width'                 => [ '1', '$1pik', '$1piksel', '$1px' ],
        'img_center'                => [ '1', 'werte', 'miyan', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'çerçeweyın', 'çerçewekerden', 'çerçewe', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'çerçeweyın', 'çerçewekerden', 'çerçewe', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'béçerçewe', 'frameless' ],
        'img_lang'                  => [ '1', 'zuwan=1$', 'lang=$1' ],
        'img_page'                  => [ '1', 'pera=$1', 'pera_$1', 'page=$1', 'page $1' ],
@@ -239,7 +239,7 @@ $magicWords = [
        'img_border'                => [ '1', 'sinor', 'border' ],
        'img_baseline'              => [ '1', 'Sinoréerdi', 'baseline' ],
        'img_sub'                   => [ '1', 'anvar', 'sub' ],
-       'img_super'                 => [ '1', 'corén', 'cor', 'super', 'sup' ],
+       'img_super'                 => [ '1', 'cor', 'corén', 'super', 'sup' ],
        'img_top'                   => [ '1', 'gedug', 'top' ],
        'img_text_top'              => [ '1', 'gedug-metin', 'text-top' ],
        'img_middle'                => [ '1', 'merkez', 'middle' ],
index 763f9fa..dd7cd68 100644 (file)
@@ -215,14 +215,14 @@ $magicWords = [
        'msg'                       => [ '0', 'ΚΕΙΜΕΝΟ:', 'MSG:' ],
        'subst'                     => [ '0', 'ΑΛΛΑΓΗ:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'ΑΠΛΟΚΕΙΜΕΝΟ:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'μικρογραφία', 'μινιατούρα', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'μικρογραφία', 'μινιατούρα', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'μικρογραφία=$1', 'μινιατούρα=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'δεξιά', 'right' ],
        'img_left'                  => [ '1', 'αριστερά', 'left' ],
        'img_none'                  => [ '1', 'καθόλου', 'none' ],
        'img_width'                 => [ '1', '$1εσ', '$1px' ],
        'img_center'                => [ '1', 'κέντρο', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'με-πλαίσιο', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'με-πλαίσιο', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'χωρίς-πλαίσιο', 'frameless' ],
        'img_page'                  => [ '1', 'σελίδα=$1', 'σελίδα_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'κατακόρυφα', 'κατακόρυφα=$1', 'κατακόρυφα_$1', 'upright', 'upright=$1', 'upright $1' ],
index d6ed235..674be13 100644 (file)
@@ -197,9 +197,16 @@ $bookstoreList = [
  * IDs must be valid identifiers, they cannot contain hyphens.
  * CASE is 0 to match all case variants, 1 for case-sensitive
  *
- * Note to translators:
- *   Please include the English words as synonyms.  This allows people
- *   from other wikis to contribute more easily.
+ * Note to localisers:
+ *   - Include the English magic words as synonyms. This allows people from
+ *     other wikis that do not speak the language to contribute more easily.
+ *   - The first alias listed MUST be the preferred alias in that language.
+ *     Tools (like Visual Editor) are expected to use the first listed alias
+ *     when editing or creating new content.
+ *   - Order the other aliases so that common aliases occur before more rarely
+ *     used aliases. The aliases SHOULD be sorted by the following convention:
+ *     1. Local first, English last, then
+ *     2. Most common first, least common last.
  *
  * This array can be modified at runtime with the LanguageGetMagic hook
  */
@@ -265,14 +272,14 @@ $magicWords = [
        'subst'                   => [ 0, 'SUBST:' ],
        'safesubst'               => [ 0, 'SAFESUBST:' ],
        'msgnw'                   => [ 0, 'MSGNW:' ],
-       'img_thumbnail'           => [ 1, 'thumbnail', 'thumb' ],
+       'img_thumbnail'           => [ 1, 'thumb', 'thumbnail' ],
        'img_manualthumb'         => [ 1, 'thumbnail=$1', 'thumb=$1' ],
        'img_right'               => [ 1, 'right' ],
        'img_left'                => [ 1, 'left' ],
        'img_none'                => [ 1, 'none' ],
        'img_width'               => [ 1, '$1px' ],
        'img_center'              => [ 1, 'center', 'centre' ],
-       'img_framed'              => [ 1, 'framed', 'enframed', 'frame' ],
+       'img_framed'              => [ 1, 'frame', 'framed', 'enframed' ],
        'img_frameless'           => [ 1, 'frameless' ],
        'img_lang'                => [ 1, 'lang=$1' ],
        'img_page'                => [ 1, 'page=$1', 'page $1' ],
index 45ea18b..9c6b7be 100644 (file)
@@ -202,14 +202,14 @@ $magicWords = [
        'subst'                     => [ '0', 'ANSTAT:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'SEKURANSTAT:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'NVMSĜ:', 'NVMSGX:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'eta', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'eta', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'eta=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'dekstra', 'dekstre', 'right' ],
        'img_left'                  => [ '1', 'maldekstra', 'maldekstre', 'left' ],
-       'img_none'                  => [ '1', 'nenio', 'neniu', 'none' ],
+       'img_none'                  => [ '1', 'neniu', 'nenio', 'none' ],
        'img_width'                 => [ '1', '$1ra', '$1px' ],
        'img_center'                => [ '1', 'centra', 'meza', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'kadro', 'enkadrita', 'enkadrite', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'kadro', 'enkadrita', 'enkadrite', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'senkadra', 'frameless' ],
        'img_page'                  => [ '1', 'paĝo=$1', 'paĝo $1', 'pagxo=$1', 'pagxo_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'altdekstre', 'altdekstre=$1', 'altdekstre_$1', 'upright', 'upright=$1', 'upright $1' ],
index a9f1d08..3b7c4bc 100644 (file)
@@ -201,13 +201,13 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'NOMBREDEPAGINADETEMAC', 'NOMBREDEPÁGINADETEMAC', 'NOMBREDEPÁGINADEASUNTOC', 'NOMBREDEPAGINADEASUNTOC', 'NOMBREDEPAGINADEARTICULOC', 'NOMBREDEPÁGINADEARTÍCULOC', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'msg'                       => [ '0', 'MSJ:', 'MSG:' ],
        'subst'                     => [ '0', 'SUST:', 'FIJAR:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'miniaturadeimagen', 'miniatura', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniaturadeimagen', 'miniatura', 'mini', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniaturadeimagen=$1', 'miniatura=$1', 'thumbnail=$1', 'thumb=$1' ],
-       'img_right'                 => [ '1', 'derecha', 'dcha', 'der', 'right' ],
+       'img_right'                 => [ '1', 'derecha', 'der', 'dcha', 'right' ],
        'img_left'                  => [ '1', 'izquierda', 'izda', 'izq', 'left' ],
-       'img_none'                  => [ '1', 'ninguna', 'nada', 'no', 'ninguno', 'none' ],
+       'img_none'                  => [ '1', 'no', 'ninguna', 'ninguno', 'nada', 'none' ],
        'img_center'                => [ '1', 'centro', 'centrado', 'centrada', 'centrar', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'marco', 'enmarcado', 'enmarcada', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'marco', 'enmarcado', 'enmarcada', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'sinmarco', 'sin_enmarcar', 'sinenmarcar', 'frameless' ],
        'img_lang'                  => [ '1', 'idioma=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'pagina=$1', 'página=$1', 'pagina_$1', 'página_$1', 'page=$1', 'page $1' ],
index 681d2ff..8a53d9e 100644 (file)
@@ -204,13 +204,13 @@ $magicWords = [
        'talkpagename'              => [ '1', 'ARUTELUNIMI', 'TALKPAGENAME' ],
        'talkpagenamee'             => [ '1', 'ARUTELUNIMI1', 'TALKPAGENAMEE' ],
        'subst'                     => [ '0', 'ASENDA:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'pisi', 'pisipilt', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'pisi', 'pisipilt', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'pisi=$1', 'pisipilt=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'paremal', 'right' ],
        'img_left'                  => [ '1', 'vasakul', 'left' ],
        'img_none'                  => [ '1', 'tühi', 'none' ],
        'img_center'                => [ '1', 'keskel', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'raam', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'raam', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'raamita', 'frameless' ],
        'img_lang'                  => [ '1', 'keel=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'lehekülg=$1', 'lehekülg_$1', 'page=$1', 'page $1' ],
index 564445b..eee9793 100644 (file)
@@ -211,14 +211,14 @@ $magicWords = [
        'subst'                     => [ '0', 'جایگزین:', 'جا:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'جایگزین_امن:', 'جام:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'پیغام‌بی‌بسط:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'بندانگشتی', 'انگشتدان', 'انگشتی', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'بندانگشتی', 'انگشتی', 'انگشتدان', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'بندانگشتی=$1', 'انگشتدان=$1', 'انگشتی=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'راست', 'right' ],
        'img_left'                  => [ '1', 'چپ', 'left' ],
        'img_none'                  => [ '1', 'هیچ', 'none' ],
        'img_width'                 => [ '1', '$1پیکسل', '$1px' ],
        'img_center'                => [ '1', 'وسط', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'قاب', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'قاب', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'بی‌قاب', 'بیقاب', 'بی_قاب', 'frameless' ],
        'img_lang'                  => [ '1', 'زبان=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'صفحه=$1', 'صفحه_$1', 'page=$1', 'page $1' ],
index 3013ea6..0d1abbd 100644 (file)
@@ -190,13 +190,13 @@ $magicWords = [
        'subjectpagename'           => [ '1', 'AIHESIVUNIMI', 'ARTIKKELISIVUNIMI', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
        'subjectpagenamee'          => [ '1', 'AIHESIVUNIMIE', 'ARTIKKELISIVUNIMIE', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'subst'                     => [ '0', 'VASTINE:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'pienoiskuva', 'pienois', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'pienoiskuva', 'pienois', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'pienoiskuva=$1', 'pienois=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'oikea', 'right' ],
        'img_left'                  => [ '1', 'vasen', 'left' ],
        'img_none'                  => [ '1', 'tyhjä', 'none' ],
-       'img_center'                => [ '1', 'keskitetty', 'keski', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'kehys', 'kehystetty', 'framed', 'enframed', 'frame' ],
+       'img_center'                => [ '1', 'keski', 'keskitetty', 'center', 'centre' ],
+       'img_framed'                => [ '1', 'kehys', 'kehystetty', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'kehyksetön', 'frameless' ],
        'img_page'                  => [ '1', 'sivu=$1', 'sivu_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'yläoikea', 'yläoikea=$1', 'yläoikea_$1', 'upright', 'upright=$1', 'upright $1' ],
index d69149c..9bb02da 100644 (file)
@@ -196,18 +196,18 @@ $magicWords = [
        'talkpagenamee'             => [ '1', 'NOMPAGEDISCUSSIONX', 'TALKPAGENAMEE' ],
        'subjectpagename'           => [ '1', 'NOMPAGESUJET', 'NOMPAGEARTICLE', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
        'subjectpagenamee'          => [ '1', 'NOMPAGESUJETX', 'NOMPAGEARTICLEX', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
-       'img_thumbnail'             => [ '1', 'vignette', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'vignette', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'vignette=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'droite', 'right' ],
        'img_left'                  => [ '1', 'gauche', 'left' ],
        'img_none'                  => [ '1', 'néant', 'neant', 'none' ],
        'img_center'                => [ '1', 'centré', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'cadre', 'encadré', 'encadre', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'cadre', 'encadré', 'encadre', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'sans_cadre', 'non_encadré', 'non_encadre', 'frameless' ],
        'img_lang'                  => [ '1', 'langue=$1', 'lang=$1' ],
        'img_upright'               => [ '1', 'redresse', 'redresse=$1', 'redresse_$1', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', 'bordure', 'border' ],
-       'img_baseline'              => [ '1', 'ligne-de-base', 'base', 'baseline' ],
+       'img_baseline'              => [ '1', 'base', 'ligne-de-base', 'baseline' ],
        'img_sub'                   => [ '1', 'indice', 'ind', 'sub' ],
        'img_super'                 => [ '1', 'exposant', 'exp', 'super', 'sup' ],
        'img_top'                   => [ '1', 'haut', 'top' ],
index dd6d1c8..106ba5e 100644 (file)
@@ -196,13 +196,13 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'NOM_DE_LA_PÂGE_DU_SUJÈT_URL', 'NOM_DE_LA_PÂGE_DE_L_ARTICLLO_URL', 'NOMPAGESUJETX', 'NOMPAGEARTICLEX', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'msg'                       => [ '0', 'MSJ:', 'MSG:' ],
        'msgnw'                     => [ '0', 'MSJNV:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'figura', 'vignette', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'figura', 'vignette', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'figura=$1', 'vignette=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'drêta', 'droite', 'right' ],
        'img_left'                  => [ '1', 'gôche', 'gauche', 'left' ],
        'img_none'                  => [ '1', 'vouedo', 'néant', 'neant', 'none' ],
        'img_center'                => [ '1', 'centrâ', 'centré', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'encâdrâ', 'câdro', 'cadre', 'encadré', 'encadre', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'encâdrâ', 'câdro', 'cadre', 'encadré', 'encadre', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'sen_câdro', 'pas_encâdrâ', 'sans_cadre', 'non_encadré', 'non_encadre', 'frameless' ],
        'img_page'                  => [ '1', 'pâge=$1', 'pâge $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'drêt', 'drêt=$1', 'drêt $1', 'redresse', 'redresse=$1', 'redresse $1', 'redresse_$1', 'upright', 'upright=$1', 'upright $1' ],
index 7c00dc7..a508790 100644 (file)
@@ -30,12 +30,12 @@ $magicWords = [
        'msg'                       => [ '0', 'TCHT:', 'MSG:' ],
        'subst'                     => [ '0', 'IONAD:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'TCHTFS:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'mionsamhail', 'mion', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'mion', 'mionsamhail', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'deas', 'right' ],
        'img_left'                  => [ '1', 'clé', 'left' ],
        'img_none'                  => [ '1', 'faic', 'none' ],
        'img_center'                => [ '1', 'lár', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'fráma', 'frámaithe', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'fráma', 'frámaithe', 'frame', 'framed', 'enframed' ],
        'int'                       => [ '0', 'INMH:', 'INT:' ],
        'sitename'                  => [ '1', 'AINMANTSUÍMH', 'SITENAME' ],
        'ns'                        => [ '0', 'AS:', 'NS:' ],
index 092226c..8f1d4a7 100644 (file)
@@ -200,17 +200,17 @@ $magicWords = [
        'basepagename'              => [ '1', 'NOMEDAPÁXINABASE', 'NOMEDAPAGINABASE', 'NOMEDAPÁGINABASE', 'BASEPAGENAME' ],
        'talkpagename'              => [ '1', 'NOMEDAPÁXINADECONVERSA', 'NOMEDAPAGINADEDISCUSSAO', 'NOMEDAPÁGINADEDISCUSSÃO', 'TALKPAGENAME' ],
        'subjectpagename'           => [ '1', 'NOMEDAPÁXINADECONTIDO', 'NOMEDAPAGINADECONTEUDO', 'NOMEDAPÁGINADECONTEÚDO', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
-       'img_thumbnail'             => [ '1', 'miniatura', 'miniaturadaimaxe', 'miniaturadaimagem', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatura', 'miniaturadaimagem', 'miniaturadaimaxe', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatura=$1', 'miniaturadaimaxe=$1', 'miniaturadaimagem=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'dereita', 'direita', 'right' ],
        'img_left'                  => [ '1', 'esquerda', 'left' ],
        'img_none'                  => [ '1', 'ningún', 'nenhum', 'none' ],
        'img_center'                => [ '1', 'centro', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'conmarco', 'conbordo', 'marco', 'commoldura', 'comborda', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'conmarco', 'marco', 'conbordo', 'commoldura', 'comborda', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'senmarco', 'senbordo', 'semmoldura', 'semborda', 'frameless' ],
        'img_page'                  => [ '1', 'páxina=$1', 'páxina_$1', 'página=$1', 'página_$1', 'página $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'arribaádereita', 'arribaádereita=$1', 'arribaádereita_$1', 'superiordireito', 'superiordireito=$1', 'superiordireito_$1', 'superiordireito $1', 'upright', 'upright=$1', 'upright $1' ],
-       'img_border'                => [ '1', 'bordo', 'borda', 'border' ],
+       'img_border'                => [ '1', 'borda', 'bordo', 'border' ],
        'img_baseline'              => [ '1', 'liñadebase', 'linhadebase', 'baseline' ],
        'img_top'                   => [ '1', 'arriba', 'acima', 'top' ],
        'img_text_top'              => [ '1', 'texto-arriba', 'text-top' ],
index 217e5cb..9e03942 100644 (file)
@@ -211,18 +211,18 @@ $magicWords = [
        'subst'                     => [ '0', 'ס:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'ס בטוח:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'הכללת מקור', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'ממוזער', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'ממוזער', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'ממוזער=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'ימין', 'right' ],
        'img_left'                  => [ '1', 'שמאל', 'left' ],
        'img_none'                  => [ '1', 'ללא', 'none' ],
        'img_width'                 => [ '1', '$1 פיקסלים', '$1px' ],
        'img_center'                => [ '1', 'מרכז', 'center', 'centre' ],
-       'img_framed'                => [ '1', '×\9e×\9e×\95ס×\92ר', '×\9eס×\92רת', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', '×\9eס×\92רת', '×\9e×\9e×\95ס×\92ר', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'לא ממוסגר', 'ללא מסגרת', 'frameless' ],
        'img_page'                  => [ '1', 'דף=$1', 'דף $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'ימין למעלה', 'ימין למעלה=$1', 'ימין למעלה $1', 'upright', 'upright=$1', 'upright $1' ],
-       'img_border'                => [ '1', 'גבולות', 'גבול', 'border' ],
+       'img_border'                => [ '1', 'גבול', 'גבולות', 'border' ],
        'img_baseline'              => [ '1', 'שורת הבסיס', 'baseline' ],
        'img_sub'                   => [ '1', 'תחתי', 'sub' ],
        'img_super'                 => [ '1', 'עילי', 'super', 'sup' ],
index 30902e3..3f3b007 100644 (file)
@@ -179,19 +179,19 @@ $magicWords = [
        'subst'                     => [ '0', 'प्रति:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'सुरक्षित_प्रति:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'सन्देश_नोविकी:', 'संदेश_नोविकी:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'अंगूठाकार', 'अंगूठा', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'अंगूठाकार', 'अंगूठा', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'अंगूठाकार=$1', 'अंगूठा=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'दाएँ', 'दायें', 'दाएं', 'right' ],
-       'img_left'                  => [ '1', 'बाà¤\8fà¤\81', 'बायà¥\87à¤\82', 'बाà¤\8fं', 'left' ],
+       'img_left'                  => [ '1', 'बाà¤\8fà¤\81', 'बाà¤\8fà¤\82', 'बायà¥\87ं', 'left' ],
        'img_none'                  => [ '1', 'कोई_नहीं', 'none' ],
        'img_width'                 => [ '1', '$1पिक्सेल', '$1px' ],
-       'img_center'                => [ '1', 'à¤\95à¥\87नà¥\8dदà¥\8dर', 'à¤\95à¥\87à¤\82द्र', 'केन्द्रित', 'केंद्रित', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'फ़à¥\8dरà¥\87म', 'फà¥\8dरà¥\87म', 'framed', 'enframed', 'frame' ],
+       'img_center'                => [ '1', 'à¤\95à¥\87à¤\82दà¥\8dर', 'à¤\95à¥\87नà¥\8dद्र', 'केन्द्रित', 'केंद्रित', 'center', 'centre' ],
+       'img_framed'                => [ '1', 'फà¥\8dरà¥\87म', 'फ़à¥\8dरà¥\87म', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'फ़्रेमहीन', 'फ्रेमहीन', 'frameless' ],
        'img_lang'                  => [ '1', 'भाषा=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'पृष्ठ=$1', 'पृष्ठ_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'खड़ी', 'खड़ी=$1', 'खड़ी_$1', 'upright', 'upright=$1', 'upright $1' ],
-       'img_border'                => [ '1', 'à¤\95िनारा', 'बà¥\89रà¥\8dडर', 'border' ],
+       'img_border'                => [ '1', 'बà¥\89रà¥\8dडर', 'à¤\95िनारा', 'border' ],
        'img_baseline'              => [ '1', 'आधार_रेखा', 'baseline' ],
        'img_sub'                   => [ '1', 'पद', 'sub' ],
        'img_super'                 => [ '1', 'मूर्ध', 'super', 'sup' ],
index ee06560..97cac52 100644 (file)
@@ -181,20 +181,20 @@ $magicWords = [
        'subjectpagename'           => [ '1', 'IMEGLAVNESTRANICE', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
        'subjectpagenamee'          => [ '1', 'IMEGLAVNESTRANICEE', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'subst'                     => [ '0', 'ZAMJENA:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'minijatura', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'mini', 'minijatura', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'minijatura=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'desno', 'right' ],
        'img_left'                  => [ '1', 'lijevo', 'left' ],
        'img_none'                  => [ '1', 'ništa', 'none' ],
        'img_center'                => [ '1', 'središte', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'okvir', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'okvir', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'bezokvira', 'frameless' ],
        'img_lang'                  => [ '1', 'jezik=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'stranica=$1', 'stranica $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'uspravno=$1', 'uspravno $1', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', 'obrub', 'border' ],
        'img_baseline'              => [ '1', 'osnovnacrta', 'baseline' ],
-       'img_sub'                   => [ '1', 'potpis', 'ind', 'sub' ],
+       'img_sub'                   => [ '1', 'ind', 'potpis', 'sub' ],
        'img_super'                 => [ '1', 'natpis', 'eks', 'super', 'sup' ],
        'img_top'                   => [ '1', 'vrh', 'top' ],
        'img_text_top'              => [ '1', 'tekst-vrh', 'text-top' ],
index 93a7f5a..6ba075a 100644 (file)
@@ -207,13 +207,13 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'SZÓCIKKNEVEE', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'msg'                       => [ '0', 'ÜZENET:', 'ÜZ:', 'MSG:' ],
        'subst'                     => [ '0', 'BEILLESZT:', 'BEMÁSOL:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'bélyegkép', 'bélyeg', 'miniatűr', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'bélyegkép', 'bélyeg', 'miniatűr', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'bélyegkép=$1', 'bélyeg=$1', 'miniatűr=$1', 'thumbnail=$1', 'thumb=$1' ],
-       'img_right'                 => [ '1', 'jobb', 'jobbra', 'right' ],
-       'img_left'                  => [ '1', 'bal', 'balra', 'left' ],
+       'img_right'                 => [ '1', 'jobbra', 'jobb', 'right' ],
+       'img_left'                  => [ '1', 'balra', 'bal', 'left' ],
        'img_none'                  => [ '1', 'semmi', 'none' ],
-       'img_center'                => [ '1', 'közép', 'középre', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'keretezett', 'keretes', 'keretben', 'kerettel', 'framed', 'enframed', 'frame' ],
+       'img_center'                => [ '1', 'középre', 'közép', 'center', 'centre' ],
+       'img_framed'                => [ '1', 'keretezett', 'keretben', 'keretes', 'kerettel', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'keretnélküli', 'frameless' ],
        'img_page'                  => [ '1', 'oldal=$1', 'oldal $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'fennjobbra', 'fennjobbra=$1', 'fennjobbra $1', 'upright', 'upright=$1', 'upright $1' ],
@@ -224,7 +224,7 @@ $magicWords = [
        'img_top'                   => [ '1', 'fenn', 'fent', 'top' ],
        'img_text_top'              => [ '1', 'szöveg-fenn', 'szöveg-fent', 'text-top' ],
        'img_middle'                => [ '1', 'vközépen', 'vközépre', 'middle' ],
-       'img_bottom'                => [ '1', 'lenn', 'lent', 'bottom' ],
+       'img_bottom'                => [ '1', 'lent', 'lenn', 'bottom' ],
        'img_text_bottom'           => [ '1', 'szöveg-lenn', 'szöveg-lent', 'text-bottom' ],
        'sitename'                  => [ '1', 'WIKINEVE', 'SITENAME' ],
        'ns'                        => [ '0', 'NÉVTÉR:', 'NS:' ],
index 28c3a4d..ab1d198 100644 (file)
@@ -130,14 +130,14 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'ՀՈԴՎԱԾԻ_ԷՋԻ_ԱՆՎԱՆՈՒՄԸ_2', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'msg'                       => [ '0', 'ՀՈՂՈՐԴ՝', 'MSG:' ],
        'msgnw'                     => [ '0', 'ՀՈՂՈՐԴ_ԱՌԱՆՑ_ՎԻՔԻԻ՝', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'մինի', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'մինի', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'մինի=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'աջից', 'right' ],
        'img_left'                  => [ '1', 'ձախից', 'left' ],
        'img_none'                  => [ '1', 'առանց', 'none' ],
        'img_width'                 => [ '1', '$1փքս', '$1px' ],
        'img_center'                => [ '1', 'կենտրոն', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'շրջափակել', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'շրջափակել', 'frame', 'framed', 'enframed' ],
        'img_page'                  => [ '1', 'էջը=$1', 'էջ $1', 'page=$1', 'page $1' ],
        'int'                       => [ '0', 'ՆԵՐՔ՝', 'INT:' ],
        'sitename'                  => [ '1', 'ԿԱՅՔԻ_ԱՆՈՒՆԸ', 'SITENAME' ],
index bf1d4d9..5fee306 100644 (file)
@@ -105,13 +105,13 @@ $magicWords = [
        'msg'                       => [ '0', 'PSN:', 'PESAN:', 'MSG:' ],
        'subst'                     => [ '0', 'GNT:', 'GANTI:', 'TUKAR:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'TPL:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'jmpl', 'jempol', 'mini', 'miniatur', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'jmpl', 'jempol', 'mini', 'miniatur', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'jmpl=$1', 'jempol=$1', 'mini=$1', 'miniatur=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'ka', 'kanan', 'right' ],
-       'img_left'                  => [ '1', 'ki', 'kiri', 'left' ],
+       'img_left'                  => [ '1', 'kiri', 'ki', 'left' ],
        'img_none'                  => [ '1', 'nir', 'tanpa', 'none' ],
        'img_center'                => [ '1', 'pus', 'pusat', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'bing', 'bingkai', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'bingkai', 'bing', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'nirbing', 'tanpabingkai', 'frameless' ],
        'img_lang'                  => [ '1', 'bhs=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'hal=$1', 'halaman=$1', 'hal_$1', 'halaman_$1', 'page=$1', 'page $1' ],
index 19cb171..8714c72 100644 (file)
@@ -188,13 +188,13 @@ $magicWords = [
        'subpagename'               => [ '1', 'NOMESOTTOPAGINA', 'SUBPAGENAME' ],
        'subpagenamee'              => [ '1', 'NOMESOTTOPAGINAE', 'SUBPAGENAMEE' ],
        'subst'                     => [ '0', 'SOST:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'miniatura', 'min', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatura', 'min', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatura=$1', 'min=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'destra', 'right' ],
        'img_left'                  => [ '1', 'sinistra', 'left' ],
        'img_none'                  => [ '1', 'nessuno', 'none' ],
        'img_center'                => [ '1', 'centro', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'riquadrato', 'incorniciato', 'originale', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'riquadrato', 'originale', 'incorniciato', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'senza_cornice', 'frameless' ],
        'img_page'                  => [ '1', 'pagina=$1', 'pagina_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'verticale', 'verticale=$1', 'verticale_$1', 'upright', 'upright=$1', 'upright $1' ],
index ef20b15..b905345 100644 (file)
@@ -229,19 +229,19 @@ $magicWords = [
        'subst'                     => [ '0', '展開:', '展開:', 'SUBST:' ],
        'safesubst'                 => [ '0', '安全展開:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'ウィキ無効メッセージ:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'サムネイル', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'サムネイル', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', '代替画像=$1', 'サムネイル=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', '右', 'right' ],
        'img_left'                  => [ '1', '左', 'left' ],
        'img_none'                  => [ '1', 'なし', '無し', 'none' ],
        'img_width'                 => [ '1', '$1ピクセル', '$1px' ],
        'img_center'                => [ '1', '中央', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'フレーム', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'フレーム', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'フレームなし', 'frameless' ],
        'img_page'                  => [ '1', 'ページ=$1', 'ページ $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', '右上', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', '境界', 'ボーダー', 'border' ],
-       'img_baseline'              => [ '1', '下線', 'ベースライン', 'baseline' ],
+       'img_baseline'              => [ '1', 'ベースライン', '下線', 'baseline' ],
        'img_sub'                   => [ '1', '下付き', 'sub' ],
        'img_super'                 => [ '1', '上付き', 'super', 'sup' ],
        'img_top'                   => [ '1', '上端', 'top' ],
index 00b98dc..7c55460 100644 (file)
@@ -126,7 +126,7 @@ $magicWords = [
        'namespace'                 => [ '1', 'სახელთა_სივრცე', 'NAMESPACE' ],
        'fullpagename'              => [ '1', 'გვერდის_სრული_სახელი', 'FULLPAGENAME' ],
        'subst'                     => [ '0', 'მიდგმ:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'მინიატიურა', 'მინი', 'მინიასლი', 'ცეროდენა', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'მინი', 'მინიატიურა', 'მინიასლი', 'ცეროდენა', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'მინიატიურა=$1', 'მინი=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'მარჯვნივ', 'right' ],
        'img_left'                  => [ '1', 'მარცხნივ', 'left' ],
index 6ae2e88..e970b17 100644 (file)
@@ -215,14 +215,14 @@ $magicWords = [
        'talkpagename'              => [ '1', 'ឈ្មោះទំព័រពិភាក្សា', 'TALKPAGENAME' ],
        'msg'                       => [ '0', 'សារ:', 'MSG:' ],
        'msgnw'                     => [ '0', 'សារមិនមែនជាកូដវិគី:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'រូបភាពតូច', 'រូបតូច', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'រូបភាពតូច', 'រូបតូច', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'រូបភាពតូច=$1', 'រូបតូច=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'ស្តាំ', 'ខាងស្តាំ', 'right' ],
        'img_left'                  => [ '1', 'ធ្វេង', 'ខាងធ្វេង', 'left' ],
        'img_none'                  => [ '1', 'ទទេ', 'គ្មាន', 'none' ],
        'img_width'                 => [ '1', '$1ភីកសែល', '$1ភស', '$1px' ],
        'img_center'                => [ '1', 'កណ្តាល', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'ស៊ុម', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'ស៊ុម', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'គ្មានស៊ុម', 'frameless' ],
        'img_page'                  => [ '1', 'ទំព័រ=$1', 'ទំព័រ$1', 'page=$1', 'page $1' ],
        'img_top'                   => [ '1', 'ផ្នែកលើ', 'ផ្នែកខាងលើ', 'top' ],
index 09acaad..4a3c15e 100644 (file)
@@ -245,14 +245,14 @@ $magicWords = [
        'subst'                     => [ '0', '풀기:', 'SUBST:' ],
        'safesubst'                 => [ '0', '안전풀기:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', '위키잘못메시지:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', '섬네일', '썸네일', '축소판', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', '섬네일', '썸네일', '축소판', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', '섬네일=$1', '썸네일=$1', '축소판=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', '오른쪽', 'right' ],
        'img_left'                  => [ '1', '왼쪽', 'left' ],
        'img_none'                  => [ '1', '없음', 'none' ],
        'img_width'                 => [ '1', '$1픽셀', '$1px' ],
        'img_center'                => [ '1', '가운데', 'center', 'centre' ],
-       'img_framed'                => [ '1', '프레임', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', '프레임', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', '프레임없음', 'frameless' ],
        'img_lang'                  => [ '1', '언어=$1', 'lang=$1' ],
        'img_page'                  => [ '1', '문서=$1', 'page=$1', 'page $1' ],
index f3aea35..b13578e 100644 (file)
@@ -202,7 +202,7 @@ $magicWords = [
        'nogallery'                 => [ '0', '__KEIN_JALLERIE__', '__KEINE_GALERIE__', '__KEINEGALERIE__', '__NOGALLERY__' ],
        'toc'                       => [ '0', '__ENHALLT__', '__INHALTSVERZEICHNIS__', '__TOC__' ],
        'img_right'                 => [ '1', 'rähß', 'räts', 'rechts', 'right' ],
-       'img_left'                  => [ '1', 'lengks', 'lenks', 'links', 'left' ],
+       'img_left'                  => [ '1', 'links', 'lengks', 'lenks', 'left' ],
        'language'                  => [ '0', '#SHPROOCH:', '#SPROCH:', '#SPRACHE:', '#LANGUAGE:' ],
        'hiddencat'                 => [ '1', '__VERSHTOCHE_SAACHJRUPP__', '__VERSTECKTE_KATEGORIE__', '__WARTUNGSKATEGORIE__', '__HIDDENCAT__' ],
 ];
index 45b9bb4..5a0a02b 100644 (file)
@@ -166,13 +166,13 @@ $magicWords = [
        'numberofedits'             => [ '1', 'NIVERAJANJYOW', 'NUMBEROFEDITS' ],
        'pagename'                  => [ '1', 'HANOWANFOLEN', 'PAGENAME' ],
        'fullpagename'              => [ '1', 'HANOWLEUNANFOLEN', 'FULLPAGENAME' ],
-       'img_thumbnail'             => [ '1', 'skeusennik', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'skeusennik', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'skeusennik=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'dyhow', 'right' ],
        'img_left'                  => [ '1', 'kledh', 'left' ],
        'img_none'                  => [ '1', 'nagonan', 'none' ],
        'img_center'                => [ '1', 'kresel', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'fremys', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'fremys', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'hebfram', 'frameless' ],
        'img_page'                  => [ '1', 'folen=$1', 'folen_$1', 'page=$1', 'page $1' ],
        'img_top'                   => [ '1', 'gwartha', 'top' ],
index 77a5b43..2f52faf 100644 (file)
@@ -169,15 +169,15 @@ $magicWords = [
        'namespace'                 => [ '1', 'Nummraum', 'NAMENSRAUM', 'NAMESPACE' ],
        'subjectspace'              => [ '1', 'Haaptnummraum', 'HAUPTNAMENSRAUM', 'SUBJECTSPACE', 'ARTICLESPACE' ],
        'subjectpagename'           => [ '1', 'Haaptsäit', 'HAUPTSEITE', 'HAUPTSEITENNAME', 'VORDERSEITE', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
-       'img_thumbnail'             => [ '1', 'Miniatur', 'miniatur', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatur', 'Miniatur', 'mini', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'riets', 'rechts', 'right' ],
        'img_left'                  => [ '1', 'lénks', 'links', 'left' ],
-       'img_none'                  => [ '1', 'ouni', 'ohne', 'none' ],
+       'img_none'                  => [ '1', 'ohne', 'ouni', 'none' ],
        'img_center'                => [ '1', 'zentréiert', 'zentriert', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'gerummt', 'gerahmt', 'framed', 'enframed', 'frame' ],
-       'img_frameless'             => [ '1', 'net_gerummt', 'rahmenlos', 'frameless' ],
+       'img_framed'                => [ '1', 'gerummt', 'gerahmt', 'frame', 'framed', 'enframed' ],
+       'img_frameless'             => [ '1', 'rahmenlos', 'net_gerummt', 'frameless' ],
        'img_page'                  => [ '1', 'Säit=$1', 'Säit_$1', 'seite=$1', 'seite $1', 'page=$1', 'page $1' ],
-       'img_border'                => [ '1', 'bord', 'rand', 'border' ],
+       'img_border'                => [ '1', 'rand', 'bord', 'border' ],
        'img_top'                   => [ '1', 'uewen', 'oben', 'top' ],
        'img_middle'                => [ '1', 'mëtt', 'mitte', 'middle' ],
        'img_bottom'                => [ '1', 'ënnen', 'unten', 'bottom' ],
index 289bd90..a8e6c77 100644 (file)
@@ -164,7 +164,7 @@ $magicWords = [
        'numberoffiles'             => [ '1', 'FAILŲSKAIČIUS', 'NUMBEROFFILES' ],
        'numberofusers'             => [ '1', 'NAUDOTOJŲSKAIČIUS', 'NUMBEROFUSERS' ],
        'numberofedits'             => [ '1', 'KEITIMŲSKAIČIUS', 'NUMBEROFEDITS' ],
-       'img_thumbnail'             => [ '1', 'miniatiūra', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatiūra', 'mini', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatiūra=$1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'dešinėje', 'right' ],
        'img_left'                  => [ '1', 'kairėje', 'left' ],
index 48720ad..653be83 100644 (file)
@@ -67,7 +67,7 @@ $magicWords = [
        'img_right'                 => [ '1', 'ankavanana', 'droite', 'right' ],
        'img_left'                  => [ '1', 'ankavia', 'gauche', 'left' ],
        'img_none'                  => [ '1', 'tsymisy', 'néant', 'neant', 'none' ],
-       'img_center'                => [ '1', 'ampivoany', 'anivony', 'centré', 'center', 'centre' ],
+       'img_center'                => [ '1', 'centré', 'ampivoany', 'anivony', 'center', 'centre' ],
        'img_page'                  => [ '1', 'pejy $1', 'page=$1', 'page $1' ],
        'img_border'                => [ '1', 'sisiny', 'bordure', 'border' ],
        'img_top'                   => [ '1', 'ambony', 'haut', 'top' ],
index 2d6e83a..99ab0e5 100644 (file)
@@ -81,7 +81,7 @@ $specialPageAliases = [
 ];
 
 $magicWords = [
-       'img_right'                 => [ '1', 'пурла', 'справа', 'right' ],
+       'img_right'                 => [ '1', 'справа', 'пурла', 'right' ],
        'img_left'                  => [ '1', 'шола', 'слева', 'left' ],
        'img_border'                => [ '1', 'чек', 'граница', 'border' ],
        'img_sub'                   => [ '1', 'йымалне', 'под', 'sub' ],
index cc76c61..c15b040 100644 (file)
@@ -252,14 +252,14 @@ $magicWords = [
        'subst'                     => [ '0', 'ЗАМЕНИ:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'БЕЗБЗАМЕНИ', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'ИЗВЕШТNW:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'мини', 'мини-слика', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'мини', 'мини-слика', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'мини-слика=$1', 'мини=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'десно', 'д', 'right' ],
        'img_left'                  => [ '1', 'лево', 'л', 'left' ],
        'img_none'                  => [ '1', 'н', 'нема', 'none' ],
        'img_width'                 => [ '1', '$1пкс', '$1п', '$1px' ],
        'img_center'                => [ '1', 'центар', 'ц', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'рамка', 'ворамка', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'рамка', 'ворамка', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'безрамка', 'frameless' ],
        'img_lang'                  => [ '1', 'јаз=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'страница=$1', 'страница_$1', 'page=$1', 'page $1' ],
index 0f2c189..2c9542b 100644 (file)
@@ -253,14 +253,14 @@ $magicWords = [
        'subst'                     => [ '0', 'ബദൽ:', 'ഉൾപ്പെടുത്തൽ:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'സംരക്ഷിതബദൽ:', 'സംരക്ഷിതയുൾപ്പെടുത്തൽ:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'മൂലരൂപം:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'ലഘുചിത്രം', 'ലഘു', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'ലഘുചിത്രം', 'ലഘു', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'ലഘുചിത്രം=$1', 'ലഘു=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'വലത്ത്‌', 'വലത്‌', 'right' ],
        'img_left'                  => [ '1', 'ഇടത്ത്‌', 'ഇടത്‌', 'left' ],
        'img_none'                  => [ '1', 'ശൂന്യം', 'none' ],
        'img_width'                 => [ '1', '$1ബിന്ദു', '$1px' ],
        'img_center'                => [ '1', 'നടുവിൽ', 'നടുക്ക്‌', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'ചട്ടം', 'ചട്ടത്തിൽ', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'ചട്ടം', 'ചട്ടത്തിൽ', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'ചട്ടരഹിതം', 'frameless' ],
        'img_lang'                  => [ '1', 'ഭാഷ=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'താൾ=$1', 'താൾ_$1', 'page=$1', 'page $1' ],
index 0ea16f9..61fc613 100644 (file)
@@ -223,14 +223,14 @@ $magicWords = [
        'msg'                       => [ '0', 'संदेश:', 'निरोप:', 'MSG:' ],
        'subst'                     => [ '0', 'पर्याय:', 'समाविष्टी:', 'अबाह्य:', 'निरकंसबिंब:', 'कंसत्याग:', 'साचाहिन:', 'साचान्तर:', 'साचापरिस्फोट:', 'साचोद्घाटन:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'संदेशनवा:', 'निरोपनवा:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'इवलेसे', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'इवलेसे', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'इवलेसे=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'उजवे', 'right' ],
        'img_left'                  => [ '1', 'डावे', 'left' ],
        'img_none'                  => [ '1', 'कोणतेचनाही', 'नन्ना', 'none' ],
        'img_width'                 => [ '1', '$1अंश', '$1कणी', '$1पक्ष', '$1px' ],
        'img_center'                => [ '1', 'मध्यवर्ती', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'चौकट', 'फ़्रेम', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'चौकट', 'फ़्रेम', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'विनाचौकट', 'विनाफ़्रेम', 'frameless' ],
        'img_page'                  => [ '1', 'पान=$1', 'पान_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'उभा', 'उभा=$1', 'उभा_$1', 'upright', 'upright=$1', 'upright $1' ],
index 50ea43b..aad38b7 100644 (file)
@@ -192,13 +192,13 @@ $magicWords = [
        'msg'                       => [ '0', 'MSĠ:', 'MSG:' ],
        'subst'                     => [ '0', 'BIDDEL:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'MSĠEW:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'daqsminuri', 'minuri', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'daqsminuri', 'minuri', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'daqsminuri=$1', 'minuri=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'lemin', 'right' ],
        'img_left'                  => [ '1', 'xellug', 'left' ],
        'img_none'                  => [ '1', 'xejn', 'none' ],
        'img_center'                => [ '1', 'nofs', 'ċentrali', 'ċentru', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'tilat', 'b\'tilar', 'tilar', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'tilat', 'b\'tilar', 'tilar', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'bla_tilar', 'frameless' ],
        'img_page'                  => [ '1', 'paġna=$1', 'paġna $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'wieqaf', 'wieqaf=$1', 'wieqaf $1', 'upright', 'upright=$1', 'upright $1' ],
index 53033c3..20057d5 100644 (file)
@@ -144,12 +144,12 @@ $magicWords = [
        'fullpagename'              => [ '1', 'ЛОПАЛЕМКУВАКАСТО', 'ПОЛНОЕ_НАЗВАНИЕ_СТРАНИЦЫ', 'FULLPAGENAME' ],
        'talkpagename'              => [ '1', 'КОРТАМОЛОПАЛЕМ', 'НАЗВАНИЕ_СТРАНИЦЫ_ОБСУЖДЕНИЯ', 'TALKPAGENAME' ],
        'msg'                       => [ '0', 'ПАЧТЯМНЭ:', 'СООБЩЕНИЕ:', 'СООБЩ:', 'MSG:' ],
-       'img_thumbnail'             => [ '1', 'кенжешка', 'мини', 'миниатюра', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'кенжешка', 'мини', 'миниатюра', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'вить_кедь', 'справа', 'right' ],
        'img_left'                  => [ '1', 'керш_кедь', 'слева', 'left' ],
        'img_none'                  => [ '1', 'вейкеяк_арась', 'без', 'none' ],
        'img_center'                => [ '1', 'куншкасо', 'центр', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'кундсо', 'обрамить', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'кундсо', 'обрамить', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'кундовтомо', 'безрамки', 'frameless' ],
        'img_page'                  => [ '1', 'лопа=$1', 'лопа_$1', 'страница=$1', 'страница_$1', 'страница $1', 'page=$1', 'page $1' ],
        'img_top'                   => [ '1', 'верькс', 'сверху', 'top' ],
index 8a18f2f..b04066c 100644 (file)
@@ -72,12 +72,12 @@ $magicWords = [
        'pagename'                  => [ '1', 'SIETNAAM', 'SEITENNAME', 'PAGENAME' ],
        'pagenamee'                 => [ '1', 'SIETNAAME', 'SEITENNAME_URL', 'PAGENAMEE' ],
        'namespace'                 => [ '1', 'NAAMRUUM', 'NAMENSRAUM', 'NAMESPACE' ],
-       'img_thumbnail'             => [ '1', 'duum', 'miniatur', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'duum', 'miniatur', 'mini', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'rechts', 'right' ],
        'img_left'                  => [ '1', 'links', 'left' ],
        'img_none'                  => [ '1', 'keen', 'ohne', 'none' ],
-       'img_center'                => [ '1', 'merrn', 'zentriert', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'rahmt', 'gerahmt', 'framed', 'enframed', 'frame' ],
+       'img_center'                => [ '1', 'zentriert', 'merrn', 'center', 'centre' ],
+       'img_framed'                => [ '1', 'gerahmt', 'rahmt', 'frame', 'framed', 'enframed' ],
        'sitename'                  => [ '1', 'STEEDNAAM', 'PROJEKTNAME', 'SITENAME' ],
        'ns'                        => [ '0', 'NR:', 'NS:' ],
        'localurl'                  => [ '0', 'STEEDURL:', 'LOKALE_URL:', 'LOCALURL:' ],
index 9ebb79f..dde2e04 100644 (file)
@@ -171,13 +171,13 @@ $magicWords = [
        'subst'                     => [ '0', 'VERV:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'VEILIGVERV:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'BERICHTNW', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'miniatuur', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatuur', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatuur=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'rechts', 'right' ],
        'img_left'                  => [ '1', 'links', 'left' ],
        'img_none'                  => [ '1', 'geen', 'none' ],
        'img_center'                => [ '1', 'gecentreerd', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'omkaderd', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'omkaderd', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'kaderloos', 'frameless' ],
        'img_lang'                  => [ '1', 'taal=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'pagina=$1', 'pagina_$1', 'page=$1', 'page $1' ],
index 49987ad..b8ae8d7 100644 (file)
@@ -132,14 +132,14 @@ $magicWords = [
        'subst'                     => [ '0', 'LIMINN:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'TRYGGLIMINN:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'IKWIKMELD:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'mini', 'miniatyr', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'mini', 'miniatyr', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'mini=$1', 'miniatyr=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'høgre', 'høyre', 'right' ],
        'img_left'                  => [ '1', 'venstre', 'left' ],
        'img_none'                  => [ '1', 'ingen', 'none' ],
        'img_width'                 => [ '1', '$1pk', '$1px' ],
        'img_center'                => [ '1', 'sentrum', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'ramme', 'ramma', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'ramme', 'ramma', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'rammelaus', 'frameless' ],
        'img_lang'                  => [ '1', 'språk=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'side=$1', 'side_$1', 'page=$1', 'page $1' ],
index 47f6b0a..6c7512b 100644 (file)
@@ -194,13 +194,13 @@ $magicWords = [
        'talkpagenamee'             => [ '1', 'NOMPAGINADISCUSSIONX', 'TALKPAGENAMEE' ],
        'subjectpagename'           => [ '1', 'NOMPAGINASUBJECTE', 'NOMPAGINASUBJÈCTE', 'NOMPAGINAARTICLE', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
        'subjectpagenamee'          => [ '1', 'NOMPAGINASUBJECTEX', 'NOMPAGINASUBJÈCTEX', 'NOMPAGINAARTICLEX', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
-       'img_thumbnail'             => [ '1', 'vinheta', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'vinheta', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'vinheta=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'drecha', 'dreta', 'right' ],
        'img_left'                  => [ '1', 'esquèrra', 'senèstra', 'gaucha', 'left' ],
        'img_none'                  => [ '1', 'neant', 'nonrés', 'none' ],
        'img_center'                => [ '1', 'centrat', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'quadre', 'enquagrat', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'quadre', 'enquagrat', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'sens_quadre', 'frameless' ],
        'img_upright'               => [ '1', 'redreça', 'redreça$1', 'redreça $1', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', 'bordadura', 'border' ],
index e84c4f6..4f500a7 100644 (file)
@@ -216,7 +216,7 @@ $magicWords = [
        'img_none'                  => [ '1', 'କିଛି_ନୁହେଁ', 'none' ],
        'img_width'                 => [ '1', '$1_ପିକସେଲ', '$1px' ],
        'img_center'                => [ '1', 'କେନ୍ଦ୍ର', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'ଫ୍ରେମକରା', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'ଫ୍ରେମକରା', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'ଫ୍ରେମନଥିବା', 'frameless' ],
        'img_border'                => [ '1', 'ବର୍ଡର', 'border' ],
        'img_baseline'              => [ '1', 'ବେସଲାଇନ', 'baseline' ],
index 26b3832..5ba4ff5 100644 (file)
@@ -169,7 +169,7 @@ $magicWords = [
        'numberofpages'             => [ '1', 'ФÆРСТЫНЫМÆЦ', 'КОЛИЧЕСТВО_СТРАНИЦ', 'NUMBEROFPAGES' ],
        'numberofarticles'          => [ '1', 'УАЦТЫНЫМÆЦ', 'КОЛИЧЕСТВО_СТАТЕЙ', 'NUMBEROFARTICLES' ],
        'pagename'                  => [ '1', 'ФАРСЫНОМ', 'НАЗВАНИЕ_СТРАНИЦЫ', 'PAGENAME' ],
-       'img_thumbnail'             => [ '1', 'кÑ\8aаддæÑ\80гонд', 'кÑ\8aаддæÑ\80', 'мини', 'миниаÑ\82Ñ\8eÑ\80а', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'мини', 'кÑ\8aаддæÑ\80гонд', 'кÑ\8aаддæÑ\80', 'миниаÑ\82Ñ\8eÑ\80а', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'къаддæргонд=$1', 'къаддæр=$1', 'мини=$1', 'миниатюра=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'рахиз', 'справа', 'right' ],
        'img_left'                  => [ '1', 'галиу', 'слева', 'left' ],
index 9c7264d..cfe0345 100644 (file)
@@ -266,13 +266,13 @@ $magicWords = [
        'basepagename'              => [ '1', 'BAZOWANAZWASTRONY', 'BASEPAGENAME' ],
        'talkpagename'              => [ '1', 'NAZWASTRONYDYSKUSJI', 'TALKPAGENAME' ],
        'subst'                     => [ '0', 'podst:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'mały', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'mały', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'mały=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'prawo', 'right' ],
        'img_left'                  => [ '1', 'lewo', 'left' ],
        'img_none'                  => [ '1', 'brak', 'none' ],
        'img_center'                => [ '1', 'centruj', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'ramka', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'ramka', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'bezramki', 'bez_ramki', 'frameless' ],
        'img_page'                  => [ '1', 'strona=$1', 'page=$1', 'page $1' ],
        'img_border'                => [ '1', 'tło', 'border' ],
index 4254b74..18c115b 100644 (file)
@@ -133,7 +133,7 @@ $magicWords = [
        'fullpagename'              => [ '1', 'دمخ_بشپړنوم', 'FULLPAGENAME' ],
        'fullpagenamee'             => [ '1', 'دمخ_بشپړنوم_نښه', 'FULLPAGENAMEE' ],
        'msg'                       => [ '0', 'پیغام:', 'پ:', 'MSG:' ],
-       'img_thumbnail'             => [ '1', 'بټنوک', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'بټنوک', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'ښي', 'right' ],
        'img_left'                  => [ '1', 'کيڼ', 'left' ],
        'img_none'                  => [ '1', 'هېڅ', 'none' ],
index dd6216e..5c3c191 100644 (file)
@@ -269,13 +269,13 @@ $magicWords = [
        'talkpagenamee'             => [ '1', 'NOMEDAPAGINADEDISCUSSAOC', 'NOMEDAPÁGINADEDISCUSSÃOC', 'TALKPAGENAMEE' ],
        'subjectpagename'           => [ '1', 'NOMEDAPAGINADECONTEUDO', 'NOMEDAPÁGINADECONTEÚDO', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
        'subjectpagenamee'          => [ '1', 'NOMEDAPAGINADECONTEUDOC', 'NOMEDAPÁGINADECONTEÚDOC', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
-       'img_thumbnail'             => [ '1', 'miniaturadaimagem', 'miniatura', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniaturadaimagem', 'miniatura', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniaturadaimagem=$1', 'miniatura=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'direita', 'right' ],
        'img_left'                  => [ '1', 'esquerda', 'left' ],
        'img_none'                  => [ '1', 'nenhum', 'none' ],
        'img_center'                => [ '1', 'centro', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'commoldura', 'comborda', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'commoldura', 'comborda', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'semmoldura', 'semborda', 'frameless' ],
        'img_page'                  => [ '1', 'página=$1', 'página_$1', 'página $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'superiordireito', 'superiordireito=$1', 'superiordireito_$1', 'superiordireito $1', 'upright', 'upright=$1', 'upright $1' ],
index 8339ad2..eb1c8d9 100644 (file)
@@ -197,13 +197,13 @@ $magicWords = [
        'msg'                       => [ '0', 'WILLA:', 'MSJ:', 'MSG:' ],
        'subst'                     => [ '0', 'WAKCHAY:', 'SUST:', 'FIJAR:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'WILLAMUSUQ:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'rikchacha', 'miniaturadeimagen', 'miniatura', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'rikchacha', 'miniaturadeimagen', 'mini', 'miniatura', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'rikchacha=$1', 'miniaturadeimagen=$1', 'miniatura=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'paña', 'alliq', 'derecha', 'dcha', 'der', 'right' ],
        'img_left'                  => [ '1', 'lluqi', 'ichuq', 'izquierda', 'izda', 'izq', 'left' ],
        'img_none'                  => [ '1', 'manaima', 'mana', 'ninguna', 'nada', 'no', 'ninguno', 'none' ],
        'img_center'                => [ '1', 'chawpi', 'centro', 'centrado', 'centrada', 'centrar', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'inchuyuq', 'inchu', 'marco', 'enmarcado', 'enmarcada', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'inchuyuq', 'inchu', 'marco', 'enmarcado', 'enmarcada', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'inchunnaq', 'sinmarco', 'sin_embarcar', 'sinenmarcar', 'sin_enmarcar', 'frameless' ],
        'img_page'                  => [ '1', 'panqa=$1', 'pagina=$1', 'página=$1', 'pagina_$1', 'página_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'sayaq', 'sayaq=$1', 'upright', 'upright=$1', 'upright $1' ],
index 8c04de8..7304dbf 100644 (file)
@@ -36,7 +36,7 @@ $namespaceNames = [
 
 $magicWords = [
        'redirect'                  => [ '0', '#RENVIAMENT', '#REDIRECT' ],
-       'img_thumbnail'             => [ '1', 'miniatura', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatura', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatura=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_upright'               => [ '1', 'sidretg', 'sidretg=$1', 'sidretg_$1', 'upright', 'upright=$1', 'upright $1' ],
 ];
index b1860f9..8b92171 100644 (file)
@@ -86,13 +86,13 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'NUMEEPAGINASUBIECT', 'NUMEEPAGINAARTICOL', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'msg'                       => [ '0', 'MSJ:', 'MSG:' ],
        'msgnw'                     => [ '0', 'MSJNOU:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'miniatura', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatura', 'mini', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatura=$1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'dreapta', 'right' ],
        'img_left'                  => [ '1', 'stanga', 'left' ],
        'img_none'                  => [ '1', 'nu', 'none' ],
        'img_center'                => [ '1', 'centru', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'cadru', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'cadru', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'faracadru', 'frameless' ],
        'img_page'                  => [ '1', 'pagina=$1', 'pagina $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'dreaptasus', 'dreaptasus=$1', 'dreaptasus $1', 'upright', 'upright=$1', 'upright $1' ],
index c273654..e1af8f3 100644 (file)
@@ -291,14 +291,14 @@ $magicWords = [
        'subst'                     => [ '0', 'ПОДСТАНОВКА:', 'ПОДСТ:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'ЗАЩПОДСТ:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'СООБЩ_БЕЗ_ВИКИ:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'мини', 'миниатюра', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'мини', 'миниатюра', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'мини=$1', 'миниатюра=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'справа', 'right' ],
        'img_left'                  => [ '1', 'слева', 'left' ],
        'img_none'                  => [ '1', 'без', 'none' ],
        'img_width'                 => [ '1', '$1пкс', '$1px' ],
        'img_center'                => [ '1', 'центр', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'обрамить', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'обрамить', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'безрамки', 'frameless' ],
        'img_page'                  => [ '1', 'страница=$1', 'страница $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'сверхусправа', 'сверхусправа=$1', 'сверхусправа $1', 'upright', 'upright=$1', 'upright $1' ],
index 21b5e63..4a369bd 100644 (file)
@@ -223,14 +223,14 @@ $magicWords = [
        'subjectpagename'           => [ '1', 'विषयपृष्ठनाम', 'लेखपृष्ठनाम', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
        'msg'                       => [ '0', 'सन्देश:', 'MSG:' ],
        'msgnw'                     => [ '0', 'नूतनसन्देश:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'लà¤\98à¥\81तà¥\8dतम', 'सà¤\99à¥\8dà¤\95à¥\81à¤\9aितà¤\9aितà¥\8dर', 'à¤\85à¤\99à¥\8dà¤\97à¥\81षà¥\8dठ', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'लà¤\98à¥\81तà¥\8dतम', 'à¤\85à¤\99à¥\8dà¤\97à¥\81षà¥\8dठ', 'सà¤\99à¥\8dà¤\95à¥\81à¤\9aितà¤\9aितà¥\8dर', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'सङ्कुचितचित्र=$1', 'अङ्गुष्ठ=$1', 'लघुत्तमचित्र=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'दक्षिणत', 'right' ],
        'img_left'                  => [ '1', 'वामतः', 'left' ],
        'img_none'                  => [ '1', 'नैव', 'none' ],
        'img_width'                 => [ '1', '$1पिट', '$1px' ],
        'img_center'                => [ '1', 'मध्य', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'आबन्ध', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'आबन्ध', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'निराबन्ध', 'frameless' ],
        'img_page'                  => [ '1', 'पृष्ठ=$1', 'पृष्ठ $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'उन्नत', 'उन्नत=$1', 'उन्नत $1', 'upright', 'upright=$1', 'upright $1' ],
index 0208991..e04b004 100644 (file)
@@ -126,7 +126,7 @@ $magicWords = [
        'numberofactiveusers'       => [ '1', 'AKTIIVAGEAVAHEDDJIIDMEARRI', ' AKTIIVAGEAVAHEADDJIMEARRI', ' AKTIIVAGEAVAHEADDJEMEARRI', 'NUMBEROFACTIVEUSERS' ],
        'numberofedits'             => [ '1', 'RIEVDADUSAIDMEARRI', ' RIEVDADUSMEARRI', 'NUMBEROFEDITS' ],
        'subst'                     => [ '0', 'LIIBME:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'mini', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'olgeš', 'right' ],
        'img_left'                  => [ '1', 'gurut', 'left' ],
index 3a821e2..fb79237 100644 (file)
@@ -158,14 +158,14 @@ $magicWords = [
        'msg'                       => [ '0', 'POR:', 'MSG:' ],
        'subst'                     => [ '0', 'ZAMJENI:', 'ZAMENI:', 'ZAMJENA:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'NVPOR:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'minijatura', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'mini', 'minijatura', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'minijatura=$1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'desno', 'right' ],
        'img_left'                  => [ '1', 'lijevo', 'levo', 'left' ],
-       'img_none'                  => [ '1', 'n', 'bez', 'ništa', 'none' ],
-       'img_center'                => [ '1', 'centar', 'središte', 'c', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'okvir', 'ram', 'framed', 'enframed', 'frame' ],
-       'img_frameless'             => [ '1', 'bez_okvira', 'bezokvira', 'frameless' ],
+       'img_none'                  => [ '1', 'n', 'ništa', 'bez', 'none' ],
+       'img_center'                => [ '1', 'centar', 'c', 'središte', 'center', 'centre' ],
+       'img_framed'                => [ '1', 'okvir', 'ram', 'frame', 'framed', 'enframed' ],
+       'img_frameless'             => [ '1', 'bezokvira', 'bez_okvira', 'frameless' ],
        'img_page'                  => [ '1', 'stranica=$1', 'stranica_$1', 'strana=$1', 'strana_$1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'na_gore', 'na_gore=$1', 'na_gore_$1', 'uspravno', 'uspravno=$1', 'uspravno_$1', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', 'granica', 'obrub', 'border' ],
index d1ac72f..299fd13 100644 (file)
@@ -220,13 +220,13 @@ $magicWords = [
        'subjectpagenamee'          => [ '1', 'NÁZOVČLÁNKUE', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'msg'                       => [ '0', 'SPRÁVA:', 'MSG:' ],
        'subst'                     => [ '0', 'NAHR:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'náhľad', 'náhľadobrázka', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'náhľad', 'náhľadobrázka', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'vpravo', 'right' ],
        'img_left'                  => [ '1', 'vľavo', 'left' ],
        'img_none'                  => [ '1', 'žiadny', 'none' ],
        'img_width'                 => [ '1', '$1bod', '$1px' ],
        'img_center'                => [ '1', 'stred', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'rám', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'rám', 'frame', 'framed', 'enframed' ],
        'img_border'                => [ '1', 'okraj', 'border' ],
        'sitename'                  => [ '1', 'NÁZOVLOKALITY', 'SITENAME' ],
        'ns'                        => [ '0', 'MP:', 'NS:' ],
index c434309..7599bc2 100644 (file)
@@ -119,14 +119,14 @@ $magicWords = [
        'forcetoc'                  => [ '0', '__VSILIKAZALOVSEBINE__', '__FORCETOC__' ],
        'toc'                       => [ '0', '__POGLAVJE__', '__TOC__' ],
        'noeditsection'             => [ '0', '__BREZUREJANJARAZDELKOV__', '__NOEDITSECTION__' ],
-       'img_thumbnail'             => [ '1', 'sličica', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'sličica', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'sličica=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'desno', 'right' ],
        'img_left'                  => [ '1', 'levo', 'left' ],
        'img_none'                  => [ '1', 'brez', 'none' ],
        'img_width'                 => [ '1', '$1_pik', '$1px' ],
        'img_center'                => [ '1', 'sredina', 'sredinsko', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'okvir', 'okvirjeno', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'okvir', 'okvirjeno', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'brezokvirja', 'frameless' ],
        'img_page'                  => [ '1', 'stran=$1', 'm_stran $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'zgorajdesno', 'zgorajdesno=$1', 'zgorajdesno $1', 'upright', 'upright=$1', 'upright $1' ],
index 20e3978..a0d88d4 100644 (file)
@@ -166,13 +166,13 @@ $magicWords = [
        'talkpagename'              => [ '1', 'EMRIIFAQESSËDISKUTIMIT', 'TALKPAGENAME' ],
        'talkpagenamee'             => [ '1', 'EMRIIFAQESSËDISKUTIMITE', 'TALKPAGENAMEE' ],
        'subst'                     => [ '0', 'ZËVN', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'parapamje', 'pamje', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'parapamje', 'pamje', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'parapamje=$1', 'pamje=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'djathtas', 'right' ],
        'img_left'                  => [ '1', 'majtas', 'left' ],
        'img_none'                  => [ '1', 's\'ka', 'none' ],
        'img_center'                => [ '1', 'qendër', 'qendrore', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'i_kornizuar', 'pa_kornizë', 'kornizë', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'i_kornizuar', 'pa_kornizë', 'kornizë', 'frame', 'framed', 'enframed' ],
        'img_page'                  => [ '1', 'faqja=$1', 'faqja $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'lartdjathtas', 'lartdjathtas=$1', 'lartdjathtas $1', 'upright', 'upright=$1', 'upright $1' ],
        'img_border'                => [ '1', 'kufi', 'border' ],
index 0815c71..8819be6 100644 (file)
@@ -249,13 +249,13 @@ $magicWords = [
        'msg'                       => [ '0', 'MED:', 'MSG:' ],
        'subst'                     => [ '0', 'BYT:', 'SUBST:' ],
        'msgnw'                     => [ '0', 'MEDNW:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'miniatyr', 'mini', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'miniatyr', 'mini', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'miniatyr=$1', 'mini=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'höger', 'right' ],
        'img_left'                  => [ '1', 'vänster', 'left' ],
        'img_none'                  => [ '1', 'ingen', 'none' ],
        'img_center'                => [ '1', 'centrerad', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'inramad', 'ram', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'ram', 'inramad', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'ramlös', 'frameless' ],
        'img_page'                  => [ '1', 'sida=$1', 'sida $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'stående', 'stående=$1', 'stående $1', 'upright', 'upright=$1', 'upright $1' ],
index 747f1e8..9e07263 100644 (file)
@@ -252,14 +252,14 @@ $magicWords = [
        'subst'                     => [ '0', 'YK:', 'YERİNEKOY:', 'KOPYALA:', 'AKTAR:', 'YAPIŞTIR:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'GÜVENLİYERİNEKOY:', 'GÜVENLİKOPYALA:', 'GÜVENLİAKTAR:', 'GÜVENLİYAPIŞTIR:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'MSJYN:', 'İLTYN:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'küçükresim', 'küçük', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'küçükresim', 'küçük', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'küçükresim=$1', 'küçük=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'sağ', 'right' ],
        'img_left'                  => [ '1', 'sol', 'left' ],
        'img_none'                  => [ '1', 'yok', 'none' ],
        'img_width'                 => [ '1', '$1pik', '$1piksel', '$1px' ],
        'img_center'                => [ '1', 'orta', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'çerçeveli', 'çerçeve', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'çerçeveli', 'çerçeve', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'çerçevesiz', 'frameless' ],
        'img_page'                  => [ '1', 'sayfa=$1', 'sayfa $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'dikey', 'dikey=$1', 'dikey $1', 'upright', 'upright=$1', 'upright $1' ],
@@ -267,7 +267,7 @@ $magicWords = [
        'img_baseline'              => [ '1', 'tabançizgisi', 'altçizgi', 'baseline' ],
        'img_sub'                   => [ '1', 'alt', 'sub' ],
        'img_super'                 => [ '1', 'üst', 'üs', 'super', 'sup' ],
-       'img_top'                   => [ '1', 'tavan', 'tepe', 'top' ],
+       'img_top'                   => [ '1', 'tepe', 'tavan', 'top' ],
        'img_text_top'              => [ '1', 'metin-tavan', 'metin-tepe', 'text-top' ],
        'img_middle'                => [ '1', 'merkez', 'middle' ],
        'img_bottom'                => [ '1', 'taban', 'bottom' ],
index d3bca66..369e0be 100644 (file)
@@ -274,14 +274,14 @@ $magicWords = [
        'subst'                     => [ '0', 'ПІДСТ:', 'ПІДСТАНОВКА:', 'ПОДСТАНОВКА:', 'ПОДСТ:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'БЕЗПЕЧНА_ПІДСТАНОВКА:', 'ЗАЩПОДСТ:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'ПОВІД_БЕЗ_ВІКІ:', 'СООБЩ_БЕЗ_ВИКИ:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'міні', 'мініатюра', 'мини', 'миниатюра', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'міні', 'мини', 'мініатюра', 'миниатюра', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'міні=$1', 'мініатюра=$1', 'мини=$1', 'миниатюра=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'праворуч', 'справа', 'right' ],
        'img_left'                  => [ '1', 'ліворуч', 'слева', 'left' ],
        'img_none'                  => [ '1', 'без', 'none' ],
        'img_width'                 => [ '1', '$1пкс', '$1px' ],
        'img_center'                => [ '1', 'центр', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'обрамити', 'рамка', 'обрамить', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'обрамити', 'рамка', 'обрамить', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'безрамки', 'frameless' ],
        'img_page'                  => [ '1', 'сторінка=$1', 'сторінка_$1', 'страница=$1', 'страница $1', 'page=$1', 'page $1' ],
        'img_upright'               => [ '1', 'зверхуправоруч', 'зверхуправоруч=$1', 'зверхуправоруч_$1', 'сверхусправа', 'сверхусправа=$1', 'сверхусправа $1', 'upright', 'upright=$1', 'upright $1' ],
index f70080b..f9da1ed 100644 (file)
@@ -152,7 +152,7 @@ $magicWords = [
        'msg'                       => [ '0', 'پیغام:', 'MSG:' ],
        'subst'                     => [ '0', 'جا:', 'نقل:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'محفوظ_جا:', 'محفوظ_نقل:', 'SAFESUBST:' ],
-       'img_thumbnail'             => [ '1', 'تصغیر', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'تصغیر', 'thumb', 'thumbnail' ],
        'img_right'                 => [ '1', 'دائیں', 'right' ],
        'img_left'                  => [ '1', 'بائیں', 'left' ],
        'img_center'                => [ '1', 'درمیان', 'center', 'centre' ],
index 593f61a..201a677 100644 (file)
@@ -220,13 +220,13 @@ $magicWords = [
        'subst'                     => [ '0', 'THẾ:', 'SUBST:' ],
        'safesubst'                 => [ '0', 'THẾ_AN_TOÀN:', 'SAFESUBST:' ],
        'msgnw'                     => [ '0', 'NHẮN_MỚI:', 'NHẮNMỚI:', 'MSGNW:' ],
-       'img_thumbnail'             => [ '1', 'nhỏ', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'nhỏ', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'nhỏ=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'phải', 'right' ],
        'img_left'                  => [ '1', 'trái', 'left' ],
        'img_none'                  => [ '1', 'không', 'none' ],
        'img_center'                => [ '1', 'giữa', 'center', 'centre' ],
-       'img_framed'                => [ '1', 'khung', 'framed', 'enframed', 'frame' ],
+       'img_framed'                => [ '1', 'khung', 'frame', 'framed', 'enframed' ],
        'img_frameless'             => [ '1', 'không_khung', 'frameless' ],
        'img_lang'                  => [ '1', 'tiếng=$1', 'ngôn_ngữ=$1', 'lang=$1' ],
        'img_page'                  => [ '1', 'trang=$1', 'trang_$1', 'page=$1', 'page $1' ],
index 074bf54..edc860e 100644 (file)
@@ -169,7 +169,7 @@ $magicWords = [
        'subpagename'               => [ '1', 'אונטערבלאטנאמען', 'שם דף המשנה', 'SUBPAGENAME' ],
        'talkpagename'              => [ '1', 'רעדנבלאטנאמען', 'שם דף השיחה', 'TALKPAGENAME' ],
        'subst'                     => [ '0', 'ס:', 'SUBST:' ],
-       'img_thumbnail'             => [ '1', 'קליין', 'ממוזער', 'thumbnail', 'thumb' ],
+       'img_thumbnail'             => [ '1', 'קליין', 'ממוזער', 'thumb', 'thumbnail' ],
        'img_manualthumb'           => [ '1', 'קליין=$1', 'ממוזער=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'                 => [ '1', 'רעכטס', 'ימין', 'right' ],
        'img_left'                  => [ '1', 'לינקס', 'שמאל', 'left' ],
index d30a348..2b97f7a 100644 (file)
--- a/load.php
+++ b/load.php
@@ -36,12 +36,15 @@ if ( !$wgRequest->checkUrlExtension() ) {
        return;
 }
 
-// Respond to ResourceLoader request
+// Set up ResourceLoader
 $resourceLoader = new ResourceLoader(
        ConfigFactory::getDefaultInstance()->makeConfig( 'main' ),
        LoggerFactory::getInstance( 'resourceloader' )
 );
-$resourceLoader->respond( new ResourceLoaderContext( $resourceLoader, $wgRequest ) );
+$context = new ResourceLoaderContext( $resourceLoader, $wgRequest );
+
+// Respond to ResourceLoader request
+$resourceLoader->respond( $context );
 
 Profiler::instance()->setTemplated( true );
 
index 777eddd..a08297a 100644 (file)
@@ -752,17 +752,19 @@ abstract class Maintenance {
 
                if ( isset( $this->mParams[$option] ) ) {
                        $multi = $this->mParams[$option]['multiOccurrence'];
-                       $exists = array_key_exists( $option, $options );
-                       if ( $multi && $exists ) {
-                               $options[$option][] = $value;
-                       } elseif ( $multi ) {
-                               $options[$option] = [ $value ];
-                       } elseif ( !$exists ) {
-                               $options[$option] = $value;
-                       } else {
-                               $this->error( "\nERROR: $option parameter given twice\n" );
-                               $this->maybeHelp( true );
-                       }
+               } else {
+                       $multi = false;
+               }
+               $exists = array_key_exists( $option, $options );
+               if ( $multi && $exists ) {
+                       $options[$option][] = $value;
+               } elseif ( $multi ) {
+                       $options[$option] = [ $value ];
+               } elseif ( !$exists ) {
+                       $options[$option] = $value;
+               } else {
+                       $this->error( "\nERROR: $option parameter given twice\n" );
+                       $this->maybeHelp( true );
                }
        }
 
diff --git a/maintenance/archives/patch-add-cl_collation_ext_index.sql b/maintenance/archives/patch-add-cl_collation_ext_index.sql
new file mode 100644 (file)
index 0000000..8137dc6
--- /dev/null
@@ -0,0 +1,2 @@
+-- @since 1.27
+CREATE INDEX /*i*/cl_collation_ext ON /*_*/categorylinks (cl_collation, cl_to, cl_type, cl_from);
index c1499c1..f5ff1f1 100644 (file)
@@ -13,7 +13,7 @@ ALTER TABLE /*$wgDBprefix*/categorylinks
        ADD COLUMN cl_sortkey_prefix varchar(255) binary NOT NULL default '',
        ADD COLUMN cl_collation varbinary(32) NOT NULL default '',
        ADD COLUMN cl_type ENUM('page', 'subcat', 'file') NOT NULL default 'page',
-       ADD INDEX (cl_collation),
+-- rm'd in 1.27        ADD INDEX (cl_collation),
        DROP INDEX cl_sortkey,
        ADD INDEX cl_sortkey (cl_to, cl_type, cl_sortkey, cl_from);
 INSERT IGNORE INTO /*$wgDBprefix*/updatelog (ul_key) VALUES ('cl_fields_update');
diff --git a/maintenance/archives/patch-kill-cl_collation_index.sql b/maintenance/archives/patch-kill-cl_collation_index.sql
new file mode 100644 (file)
index 0000000..7f75a62
--- /dev/null
@@ -0,0 +1,7 @@
+--
+-- Kill cl_collation index.
+-- @since 1.27
+--
+
+DROP INDEX /*i*/cl_collation ON /*_*/categorylinks;
+
diff --git a/maintenance/archives/patch-watchlist-wl_id.sql b/maintenance/archives/patch-watchlist-wl_id.sql
new file mode 100644 (file)
index 0000000..a73e514
--- /dev/null
@@ -0,0 +1,5 @@
+-- Primary key in watchlist
+
+ALTER TABLE /*$wgDBprefix*/watchlist
+  ADD COLUMN wl_id int unsigned NOT NULL AUTO_INCREMENT FIRST,
+  ADD PRIMARY KEY (wl_id);
index bdb197f..c92a720 100644 (file)
 require_once __DIR__ . '/Benchmarker.php';
 
 /**
- * This little benchmark executes the regexp used in Language->checkTitleEncoding()
- * and compares its execution time against that of mb_check_encoding, if available.
+ * This little benchmark executes the regexp formerly used in Language->checkTitleEncoding()
+ * and compares its execution time against that of mb_check_encoding.
  *
  * @ingroup Benchmark
  */
 class BenchUtf8TitleCheck extends Benchmarker {
-       private $canRun;
-
        private $data;
 
        public function __construct() {
                parent::__construct();
 
                // @codingStandardsIgnoreStart Ignore long line warnings.
-               $this->data = array(
+               $this->data = [
                        "",
                        "United States of America", // 7bit ASCII
                        "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e",
@@ -58,23 +56,14 @@ class BenchUtf8TitleCheck extends Benchmarker {
                        . "Saison%207%20des%20Experts%7CSaison%208%20des%20Experts%7CSaison%209%20des%20Experts%7C"
                        . "Sara%20Sidle%7CSofia%20Curtis%7CS%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e%7CWallace%20Langham%7C"
                        . "Warrick%20Brown%7CWendy%20Simms%7C%C3%89tats-Unis"
-               );
+               ];
                // @codingStandardsIgnoreEnd
 
-               $this->canRun = function_exists( 'mb_check_encoding' );
-
-               if ( $this->canRun ) {
-                       $this->addDescription( "Benchmark for using a regexp vs. mb_check_encoding " .
-                               "to check for UTF-8 encoding." );
-               } else {
-                       $this->addDescription( 'CANNOT RUN benchmark using mb_check_encoding: function not available.' );
-               }
+               $this->addDescription( "Benchmark for using a regexp vs. mb_check_encoding " .
+                       "to check for UTF-8 encoding." );
        }
 
        public function execute() {
-               if ( !$this->canRun ) {
-                       return;
-               }
                $benchmarks = [];
                foreach ( $this->data as $val ) {
                        $benchmarks[] = [
index 559dbd6..cd7a842 100644 (file)
@@ -47,7 +47,7 @@ class UploadStashCleanup extends Maintenance {
                $repo = RepoGroup::singleton()->getLocalRepo();
                $tempRepo = $repo->getTempRepo();
 
-               $dbr = $repo->getSlaveDb();
+               $dbr = $repo->getSlaveDB();
 
                // how far back should this look for files to delete?
                $cutoff = time() - $wgUploadStashMaxAge;
index e871a4e..206e046 100644 (file)
@@ -25,20 +25,27 @@ require_once __DIR__ . '/Maintenance.php';
 
 // @codingStandardsIgnoreStart MediaWiki.NamingConventions.ValidGlobalName.wgPrefix
 global $optionsWithArgs;
+global $optionsWithoutArgs;
 // @codingStandardsIgnoreEnd
 if ( !isset( $optionsWithArgs ) ) {
        $optionsWithArgs = [];
 }
+if ( !isset( $optionsWithoutArgs ) ) {
+       $optionsWithoutArgs = [];
+}
 
 class CommandLineInc extends Maintenance {
        public function __construct() {
                // @codingStandardsIgnoreStart MediaWiki.NamingConventions.ValidGlobalName.wgPrefix
-               global $optionsWithArgs;
+               global $optionsWithArgs, $optionsWithoutArgs;
                // @codingStandardsIgnoreEnd
                parent::__construct();
                foreach ( $optionsWithArgs as $name ) {
                        $this->addOption( $name, '', false, true );
                }
+               foreach ( $optionsWithoutArgs as $name ) {
+                       $this->addOption( $name, '', false, false );
+               }
        }
 
        /**
index 9abc297..848c2f7 100644 (file)
@@ -79,11 +79,16 @@ class CreateAndPromote extends Maintenance {
 
                $groups = array_filter( self::$permitRoles, [ $this, 'hasOption' ] );
                if ( $this->hasOption( 'custom-groups' ) ) {
+                       $allGroups = array_flip( User::getAllGroups() );
                        $customGroupsText = $this->getOption( 'custom-groups' );
                        if ( $customGroupsText !== '' ) {
                                $customGroups = explode( ',', $customGroupsText );
                                foreach ( $customGroups as $customGroup ) {
-                                       $groups[] = trim( $customGroup );
+                                       if ( isset( $allGroups[$customGroup] ) ) {
+                                               $groups[] = trim( $customGroup );
+                                       } else {
+                                               $this->output( "$customGroup is not a valid group, ignoring!\n" );
+                                       }
                                }
                        }
                }
index 6d5472e..914336f 100644 (file)
@@ -538,7 +538,6 @@ asctime
 asdf
 aspx
 assert
-astriks
 asymp
 async
 at
index 1904325..d4255a0 100644 (file)
@@ -102,7 +102,9 @@ TEXT
                                $this->fatalError( "Unable to open file {$filename}\n" );
                        }
                        $pages = array_map( 'trim', $pages );
-                       $this->pages = array_filter( $pages, create_function( '$x', 'return $x !== "";' ) );
+                       $this->pages = array_filter( $pages, function ( $x ) {
+                               return $x !== '';
+                       } );
                }
 
                if ( $this->hasOption( 'start' ) ) {
index 157a323..b1e4fa9 100644 (file)
@@ -42,8 +42,8 @@ class ExportSites extends Maintenance {
 
                $exporter = new SiteExporter( $handle );
 
-               $sites = SiteSQLStore::newInstance()->getSites( 'recache' );
-               $exporter->exportSites( $sites );
+               $siteLookup = \MediaWiki\MediaWikiServices::getInstance()->getSiteLookup();
+               $exporter->exportSites( $siteLookup->getSites() );
 
                fclose( $handle );
 
index f0c6569..512c38c 100644 (file)
@@ -36,6 +36,12 @@ $optionsWithArgs = [
        'extensions', 'comment', 'comment-file', 'comment-ext', 'summary', 'user',
        'license', 'sleep', 'limit', 'from', 'source-wiki-url', 'timestamp',
 ];
+
+$optionsWithoutArgs = [
+       'protect', 'unprotect', 'search-recursively', 'check-userblock', 'overwrite',
+       'skip-dupes', 'dry'
+];
+
 require_once __DIR__ . '/commandLine.inc';
 require_once __DIR__ . '/importImages.inc';
 $processed = $added = $ignored = $skipped = $overwritten = $failed = 0;
index daec7b6..5722344 100644 (file)
@@ -30,7 +30,8 @@ class ImportSites extends Maintenance {
        public function execute() {
                $file = $this->getArg( 0 );
 
-               $importer = new SiteImporter( SiteSQLStore::newInstance() );
+               $siteStore = \MediaWiki\MediaWikiServices::getInstance()->getSiteStore();
+               $importer = new SiteImporter( $siteStore );
                $importer->setExceptionCallback( [ $this, 'reportException' ] );
 
                $importer->importFromFile( $file );
index 5d48244..baa9c71 100644 (file)
@@ -21,6 +21,7 @@
  * @ingroup MaintenanceLanguage
  */
 
+$optionsWithArgs = [ 'lang', 'clang', 'mode' ];
 require_once __DIR__ . '/../commandLine.inc';
 $messagesDir = __DIR__ . '/../../languages/messages/';
 $runTest = false;
index bd9f9af..a8cbac1 100644 (file)
  * @ingroup MaintenanceLanguage
  */
 
+$optionsWithArgs = [
+       'lang', 'level', 'blacklist', 'whitelist', 'wikilang', 'output', 'prefix'
+];
+$optionsWithoutArgs = [
+       'help', 'links', 'noexif', 'easy', 'duplicate', 'all'
+];
 require_once __DIR__ . '/../commandLine.inc';
 require_once 'checkLanguage.inc';
 require_once 'languages.inc';
index eddfa26..46616db 100644 (file)
@@ -32,12 +32,12 @@ class Digit2Html extends Maintenance {
 
        # A list of unicode numerals is available at:
        # http://www.fileformat.info/info/unicode/category/Nd/list.htm
-       private $mLangs = array(
+       private $mLangs = [
                'Ar', 'As', 'Bh', 'Bo', 'Dz',
                'Fa', 'Gu', 'Hi', 'Km', 'Kn',
                'Ks', 'Lo', 'Ml', 'Mr', 'Ne',
                'New', 'Or', 'Pa', 'Pi', 'Sa'
-       );
+       ];
 
        public function __construct() {
                parent::__construct();
diff --git a/maintenance/language/generateUtf8Case.php b/maintenance/language/generateUtf8Case.php
deleted file mode 100644 (file)
index 961424d..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-/**
- * Generates Utf8Case.ser from the Unicode Character Database and
- * supplementary files.
- *
- * Copyright © 2004, 2008 Brion Vibber <brion@pobox.com>
- * https://www.mediawiki.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup MaintenanceLanguage
- */
-
-require_once __DIR__ . '/../Maintenance.php';
-
-/**
- * Generates Utf8Case.ser from the Unicode Character Database and
- * supplementary files.
- *
- * @ingroup MaintenanceLanguage
- */
-class GenerateUtf8Case extends Maintenance {
-
-       public function __construct() {
-               parent::__construct();
-               $this->addDescription( 'Generate Utf8Case.ser from the Unicode Character Database ' .
-                       'and supplementary files' );
-               $this->addOption( 'unicode-data-file', 'The local location of the data file ' .
-                       'from http://unicode.org/Public/UNIDATA/UnicodeData.txt', false, true );
-       }
-
-       public function getDbType() {
-               return Maintenance::DB_NONE;
-       }
-
-       public function execute() {
-               if ( !$this->hasOption( 'unicode-data-file' ) ) {
-                       $dataFile = 'UnicodeData.txt';
-                       if ( !file_exists( $dataFile ) ) {
-                               $this->error( "Unable to find UnicodeData.txt. Please specify " .
-                                       "its location with --unicode-data-file=<FILE>" );
-                               exit( 1 );
-                       }
-               } else {
-                       $dataFile = $this->getOption( 'unicode-data-file' );
-                       if ( !file_exists( $dataFile ) ) {
-                               $this->error( 'Unable to find the specified data file.' );
-                               exit( 1 );
-                       }
-               }
-
-               $file = fopen( $dataFile, 'r' );
-               if ( !$file ) {
-                       $this->error( 'Unable to open the data file.' );
-                       exit( 1 );
-               }
-
-               // For the file format, see http://www.unicode.org/reports/tr44/
-               $fieldNames = [
-                       'Code',
-                       'Name',
-                       'General_Category',
-                       'Canonical_Combining_Class',
-                       'Bidi_Class',
-                       'Decomposition_Type_Mapping',
-                       'Numeric_Type_Value_6',
-                       'Numeric_Type_Value_7',
-                       'Numeric_Type_Value_8',
-                       'Bidi_Mirrored',
-                       'Unicode_1_Name',
-                       'ISO_Comment',
-                       'Simple_Uppercase_Mapping',
-                       'Simple_Lowercase_Mapping',
-                       'Simple_Titlecase_Mapping'
-               ];
-
-               $upper = [];
-               $lower = [];
-
-               $lineNum = 0;
-               while ( false !== ( $line = fgets( $file ) ) ) {
-                       ++$lineNum;
-
-                       # Strip comments
-                       $line = trim( substr( $line, 0, strcspn( $line, '#' ) ) );
-                       if ( $line === '' ) {
-                               continue;
-                       }
-
-                       # Split fields
-                       $numberedData = explode( ';', $line );
-                       $data = [];
-                       foreach ( $fieldNames as $number => $name ) {
-                               $data[$name] = $numberedData[$number];
-                       }
-
-                       $source = UtfNormal\Utils::hexSequenceToUtf8( $data['Code'] );
-                       if ( $data['Simple_Uppercase_Mapping'] ) {
-                               $upper[$source] = UtfNormal\Utils::hexSequenceToUtf8( $data['Simple_Uppercase_Mapping'] );
-                       }
-                       if ( $data['Simple_Lowercase_Mapping'] ) {
-                               $lower[$source] = UtfNormal\Utils::hexSequenceToUtf8( $data['Simple_Lowercase_Mapping'] );
-                       }
-               }
-
-               global $IP;
-               file_put_contents( "$IP/serialized/Utf8Case.ser", serialize( [
-                       'wikiUpperChars' => $upper,
-                       'wikiLowerChars' => $lower,
-               ] ) );
-       }
-}
-
-$maintClass = 'GenerateUtf8Case';
-require_once RUN_MAINTENANCE_IF_MAIN;
index ca94473..7202952 100644 (file)
@@ -27,6 +27,7 @@
  * https://www.mediawiki.org/wiki/Localisation_statistics
  */
 $optionsWithArgs = [ 'output' ];
+$optionsWithoutArgs = [ 'help' ];
 
 require_once __DIR__ . '/../commandLine.inc';
 require_once 'languages.inc';
index 999f25c..abe08e4 100755 (executable)
@@ -248,7 +248,8 @@ def translate(text, conv_table):
 
 def manualWordsTable(path, conv_table, reconv_table):
     fp = open(path, 'r', encoding='U8')
-    reconv_table = {}
+    reconv_table = reconv_table.copy()
+    out_table = {}
     wordlist = [line.split('#')[0].strip() for line in fp]
     wordlist = list(set(wordlist))
     wordlist.sort(key=lambda w: (len(w), w), reverse=True)
@@ -257,9 +258,9 @@ def manualWordsTable(path, conv_table, reconv_table):
         new_word = translate(word, conv_table)
         rcv_word = translate(word, reconv_table)
         if word != rcv_word:
-            reconv_table[word] = word
-        reconv_table[new_word] = word
-    return reconv_table
+            reconv_table[word] = out_table[word] = word
+        reconv_table[new_word] = out_table[new_word] = word
+    return out_table
 
 
 def defaultWordsTable(src_wordlist, src_tomany, char_conv_table,
@@ -417,17 +418,17 @@ def main():
 namespace MediaWiki\Languages\Data;
 
 class ZhConversion {
-public static $zh2Hant = array(\n'''
+public static $zh2Hant = [\n'''
     php += PHPArray(toHant) \
-        + '\n);\n\npublic static $zh2Hans = array(\n' \
+        + '\n];\n\npublic static $zh2Hans = [\n' \
         + PHPArray(toHans) \
-        + '\n);\n\npublic static $zh2TW = array(\n' \
+        + '\n];\n\npublic static $zh2TW = [\n' \
         + PHPArray(toTW) \
-        + '\n);\n\npublic static $zh2HK = array(\n' \
+        + '\n];\n\npublic static $zh2HK = [\n' \
         + PHPArray(toHK) \
-        + '\n);\n\npublic static $zh2CN = array(\n' \
+        + '\n];\n\npublic static $zh2CN = [\n' \
         + PHPArray(toCN) \
-        + '\n);\n}\n'
+        + '\n];\n}\n'
 
     if pyversion[:1] in ['2']:
         f = open(os.path.join('..', '..', '..', 'languages', 'data', 'ZhConversion.php'), 'wb', encoding='utf8')
index 944e20e..915c699 100644 (file)
@@ -37,6 +37,7 @@
 鹽份 盐分
 組份 组分
 成份 成分
+成份股      成份股
 本份 本分
 本本份份   本本分分
 恰如其份   恰如其分
 散佈著      散布着
 遍佈著      遍布着
 遍布著      遍布着
+記錄著      记录着
+紀錄著      纪录着
+收錄著      收录着
 三十六著   三十六着
 走為上著   走为上着
 記憶體      内存
 區域網路   局域网络
 巨集 宏
 掃瞄器      扫描仪
-寬頻 宽带
 資料庫      数据库
 母音 元音
 印表機      打印机
 寮國 老挝
 貢寮 贡寮 #分詞用
 蘇利南      苏里南
+奈洛比      内罗毕
 莫三比克   莫桑比克
 賴索托      莱索托
 尚比亞      赞比亚
 提比里西   第比利斯
 巴斯拉      巴士拉
 杜拜 迪拜
+坚杜拜      坚杜拜
+堅杜拜      坚杜拜
 賽普勒斯   塞浦路斯
 荷姆茲      霍尔木兹
 加薩走廊   加沙地带
 密西根      密歇根
 紐澤西      新泽西
 蒙特婁      蒙特利尔
-滿地可      蒙特利尔
 千里達及托巴哥  特立尼达和多巴哥
 千里達      特立尼达
 托巴哥      多巴哥
index 457457a..f76d875 100644 (file)
@@ -55,7 +55,6 @@
 布光 佈光
 布局 佈局
 布防 佈防
-布施 佈施
 布满 佈滿
 布滿 佈滿
 布告 佈告
 占整 佔整
 占局部      佔局部
 日占 日佔
+擇日占星   擇日占星
+择日占星   擇日占星
 美占 美佔
 英占 英佔
 德占 德佔
 小时里      小時裏
 体里 體裏
 柜里 櫃裏
+告里 告裏
 电影里      電影裏
 广播里      廣播裏
 电视里      電視裏
 散佈著      散佈着
 遍佈著      遍佈着
 遍布著      遍佈着
+記錄著      記錄着
+紀錄著      紀錄着
+收錄著      收錄着
 三十六著   三十六着
 走為上著   走為上着
 鬧著 鬧着
 寮國 老撾
 貢寮 貢寮 #分詞用
 肯尼亚      肯雅
+奈洛比      內羅畢
 莫三比克   莫桑比克
 賴索托      萊索托
 尚比亞      贊比亞
 爱荷华      艾奧瓦
 得克萨斯   德克薩斯
 蒙特婁      蒙特利爾
-滿地可      蒙特利爾
 紐賓士域   紐賓士域
 默多克      梅鐸
 梅鐸 梅鐸
index ddd6f9d..12431b3 100644 (file)
 字库 字型檔
 字段 欄位
 存盘 存檔
-界面 介面
 控件 控制項
 盘片 碟片
 硬盘 硬碟
 服务器      伺服器
 局域网      區域網
 局域网络   區域網路
-宽带 寬頻
 数据库      資料庫
 打印机      印表機
 打印機      印表機
 老挝 寮國
 老撾 寮國
 肯尼亚      肯亞
+内罗毕      奈洛比
+內羅畢      奈洛比
 苏里南      蘇利南
 莫桑比克   莫三比克
 莱索托      賴索托
 得克薩斯   德克薩斯
 蒙特利尔   蒙特婁
 蒙特利爾   蒙特婁
-滿地可      蒙特婁
 麦克尔      麥可
 迈克尔      麥可
 魯賓斯·巴里切羅        魯本·巴瑞切羅
index 2bc8945..5c6a70b 100644 (file)
@@ -75,7 +75,6 @@
 馬占山      馬占山
 闫怀礼      閆懷禮
 薴烯 薴烯
-后豐 后豐
 于謙 于謙
 詩云 詩云
 云為 云為
 涂澤民      涂澤民
 涂長望      涂長望
 涂敏恆      涂敏恆
+后豐 后豐
 艷后 艷后
 廢后 廢后
 后髮座      后髮座
 賢后 賢后
 呂后 呂后
 蟻后 蟻后
+陳有后      陳有后
+天神之后   天神之后
+豔后 豔后
+后綜 后綜
+葉陽后      葉陽后
+后庄 后庄
+後庄 後庄
+后蒼 后蒼
 馬格里布   馬格里布
 佳里鎮      佳里鎮
 有只採      有只採
 复苏 復甦
 苹果 蘋果
 苹果干      蘋果乾
-后庄 后庄
-後庄 後庄
 龜山庄      龜山庄
 寶山庄      寶山庄
 員山庄      員山庄
 鮮于 鮮于
 賦范 賦范
 茅于軾      茅于軾
-陳有后      陳有后
-天神之后   天神之后
-豔后 豔后
-后綜 后綜
-葉陽后      葉陽后
 壽天里      壽天里
 貴子里      貴子里
 東湖里      東湖里
 水里鳳林   水里鳳林
 水里濁水溪        水里濁水溪
 洞里薩      洞里薩
+愛河里花子        愛河里花子
 划不來      划不來
 划來划去   划來划去
 划動 划動
 升平 昇平
 升阳 昇陽
 陈升 陳昇
+尔冬升      爾冬陞
 南宮适      南宮适
 舊庄 舊庄
 拿破仑      拿破崙
 扑冬 撲鼕
 冬冬鼓      鼕鼕鼓
 苧麻 苧麻
+张柏芝      張栢芝
index 03c42d9..c9d78b7 100644 (file)
@@ -323,6 +323,7 @@ U+06ED9滙|U+06C47汇|
 U+06EDB滛|U+06DEB淫|
 U+06EF7滷|U+05364卤|
 U+06F44潄|U+06F31漱|
+U+06F55潕|U+23C98𣲘|
 U+06F59潙|U+06CA9沩|
 U+06F81澁|U+06DA9涩|
 U+06F90澐|U+06C84沄|
@@ -618,6 +619,7 @@ U+08E5F蹟|U+08FF9迹|
 U+08E60蹠|U+08DD6跖|
 U+08E67蹧|U+07CDF糟|
 U+08E75蹵|U+08E74蹴|
+U+08E98躘|U+28001𨀁|
 U+08EAD躭|U+0803D耽|
 U+08EB3躳|U+08EAC躬|
 U+08EB6躶|U+088F8裸|
index 309bd5d..492a99d 100644 (file)
 數罪併罰
 催併
 狂併潮
+合併
+併為一體
+併為一家
+併吞
+並吞下
 提摩太後書
 裏海
 不採
 髮釵
 髮飾
 髮紗
+髮簪
 髮上指冠
 髮上沖冠
 髮乳
 髮已霜白
 髮油
 髮為血之本
-髮網
+髮網
 髮踊沖冠
 髮際
 黃髮
 美髮業
 美髮沙龍
 美容美髮
+程十髮
 模范棒棒堂
 模范三軍
 模范七棒
 複分解
 複合 #因複合詞頻遠高於復合
 複方
+複穗
 撥穀
 扁擬穀盜蟲
 不穀
 鹹批
 鹹濕
 鹹豬
+甜鹹
+鹹甜
+甜、鹹
+鹹、甜
 錦綉花園
 籲天
 勃鬱
 儒略曆
 伊斯蘭曆
 酒麴
-爾冬陞
 澹臺
 拜託
 委託
 筑陽
 南筑
 悲筑
-批准
-核准
+批准
+核准
 為準
 準直
 擺鐘
 看錶
 看表面
 鐵鐘
-看下鐘
-看下錶
-瞅下鐘
-瞅下錶
-拿下鐘
-拿下錶
 鐘不敲不響
 對準鐘
 對準鐘錶
 錶慢
 響鐘
 鐘敲
-大本鐘敲
-大笨鐘敲
 世紀鐘錶
 世紀鐘
 錶王
 鐘頂
 鐘紐
 鐘座
-他鐘
 寺鐘
 座鐘
 大笨鐘
 遊牧
 遊蕩
 遊刃
+遊廊
+遊春
 遊美學務
 黑奴籲天錄
 林郁方
 挑大樑
 扛大樑
 后豐
-製得
-限制
-控制
-製取
 心臟
 肝臟
 脾臟
 于敏中
 註:# 不作“注:”
 劃為# 不作“划為”
-併為一體
-併為一家
 一個# 避免“個裡”的錯誤
 兩個
 二個
 節目裡
 場裡
 世紀裡
-亞美尼亞曆
 注釋
 月面
 路面
 體裡
 櫃裡
 片裡
+告裡
 電影裡
 廣播裡
 電視裡
 逆風後
 順風後
 大風後
+賭后
+山仔后
+甲后路
+劉芸后
+謝華后
+趙惠后
+昭惠后
+周惠后
+孝惠后
+趙威后
+聖后
+陳有后
+惠文后
+葉陽后
+后蒼
 馬格里布
 伊里布
 劃入
 黎吉雲
 代表
 水無怜奈
-賭后
-山仔后
-甲后路
-劉芸后
-謝華后
-趙惠后
-昭惠后
-周惠后
-孝惠后
-趙威后
-聖后
-陳有后
-惠文后
-葉陽后
 于冠華
 于雲鶴
 于忠肅集
 億周後
 幾周後
 多周後
-前往
 后瑞站
 帝后臺
+紅后假說
+尊后
+前往
 新井里美
 樗里子
 伊達里子
 王田里
 小井里
 西井里
-尊后
+碧河里
+愛河里花子
 叶志穗
 叶不二子
 于立成
 後天
 學家
 游離
-紅后假說
 書面
 不只
 湧水
 陽穀
 太醜
 御製
-合併
 聖人曆
 電影後
 封為后
 僱車
 僱船
 米糰
+集團
 謹愿
 瞎矇
 里舖
 電子製表
 製毒
 製販
+製得
+製取
 譯製
 遏制 #以下分詞用
 管制
 抑制
 控制
 限制
+強制
 體徵
 綜合徵
 价川
 0齣
 0出現
 0出線
-第一齣
-第二齣
-第三齣
-第四齣
-第五齣
-第六齣
-第七齣
-第八齣
-第九齣
-第一出現
-第一出線
-第二出線
-第三出局
-第四出局
-第五出局
 這齣
 這出現
 這出乎
 秀發生
 秀發起
 秀發展
+留發生
+留發行
+留發展
 縮短發
 簡短發
 短發生
+頭發現
+蛋白發
 古人有云
 昔人有云
 云敞
index 07cb389..09a41ad 100644 (file)
 六齣
 弔兒郎當
 髮小
-髮網
 修鍊
 麵線
 繫上
 防颱
 慾望
 剋星
+挂
+掛
+陸遊
+徵人
+髮針
+供製
+并吞
+併吞下
+髮網
index 0fff823..784ba0e 100644 (file)
  * @ingroup Maintenance
  */
 
-/** */
+$optionsWithArgs = [ 'cache' ];
+$optionsWithoutArgs = [
+       'debug', 'help'
+];
 require_once __DIR__ . '/commandLine.inc';
 
-$options = getopt( '', [ 'debug', 'help', 'cache:' ] );
-
 $debug = isset( $options['debug'] );
 $help = isset( $options['help'] );
 $cache = isset( $options['cache'] ) ? $options['cache'] : null;
index c4dfd8f..60f94a5 100644 (file)
@@ -70,7 +70,7 @@ class McTest extends Maintenance {
                                $server # output channel
                        );
 
-                       $mcc = new MemCachedClientforWiki( [
+                       $mcc = new MemcachedClient( [
                                'persistant' => true,
                                'timeout' => $wgMemCachedTimeout
                        ] );
index 46d5474..a650aa0 100644 (file)
@@ -81,7 +81,12 @@ class MergeMessageFileList extends Maintenance {
                # Now find out files in a directory
                if ( $this->hasOption( 'extensions-dir' ) ) {
                        $extdir = $this->getOption( 'extensions-dir' );
-                       $entries = scandir( $extdir );
+                       # Allow multiple directories to be passed with ":" as delimiter
+                       $extdirs = explode( ':', $extdir );
+                       $entries = [];
+                       foreach ( $extdirs as $extdir ) {
+                               $entries = array_merge( $entries, scandir( $extdir ) );
+                       }
                        foreach ( $entries as $extname ) {
                                if ( $extname == '.' || $extname == '..' || !is_dir( "$extdir/$extname" ) ) {
                                        continue;
diff --git a/maintenance/mssql/archives/patch-watchlist-wl_id.sql b/maintenance/mssql/archives/patch-watchlist-wl_id.sql
new file mode 100644 (file)
index 0000000..b71f817
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE /*_*/watchlist ADD wl_id INT IDENTITY;
+ALTER TABLE /*_*/watchlist ADD CONSTRAINT pk_watchlist PRIMARY KEY(wl_id)
index 0e58563..86bd735 100644 (file)
@@ -847,6 +847,7 @@ CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp
 
 
 CREATE TABLE /*_*/watchlist (
+  wl_id int NOT NULL PRIMARY KEY IDENTITY,
   -- Key to user.user_id
   wl_user int NOT NULL REFERENCES /*_*/mwuser(user_id) ON DELETE CASCADE,
 
index 6d2a553..55f361c 100644 (file)
@@ -583,7 +583,7 @@ class NamespaceConflictChecker extends Maintenance {
                $wikiPage = new WikiPage( $sourceTitle );
                $wikiPage->loadPageData( 'fromdbmaster' );
 
-               $destId = $newTitle->getArticleId();
+               $destId = $newTitle->getArticleID();
                $this->beginTransaction( $this->db, __METHOD__ );
                $this->db->update( 'revision',
                        // SET
diff --git a/maintenance/oracle/archives/patch-watchlist-wl_id.sql b/maintenance/oracle/archives/patch-watchlist-wl_id.sql
new file mode 100644 (file)
index 0000000..4f7180d
--- /dev/null
@@ -0,0 +1,6 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.watchlist ADD (
+wl_id NUMBER NOT NULL,
+);
+ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_pk PRIMARY KEY (wl_id);
index 9a70b87..27c3030 100644 (file)
@@ -436,11 +436,13 @@ CREATE INDEX &mw_prefix.recentchanges_i06 ON &mw_prefix.recentchanges (rc_namesp
 CREATE INDEX &mw_prefix.recentchanges_i07 ON &mw_prefix.recentchanges (rc_user_text, rc_timestamp);
 
 CREATE TABLE &mw_prefix.watchlist (
+  wl_id                     NUMBER     NOT NULL,
   wl_user                   NUMBER     NOT NULL,
   wl_namespace              NUMBER    DEFAULT 0 NOT NULL,
   wl_title                  VARCHAR2(255)        NOT NULL,
   wl_notificationtimestamp  TIMESTAMP(6) WITH TIME ZONE
 );
+ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_pk PRIMARY KEY (wl_id);
 ALTER TABLE &mw_prefix.watchlist ADD CONSTRAINT &mw_prefix.watchlist_fk1 FOREIGN KEY (wl_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
 CREATE UNIQUE INDEX &mw_prefix.watchlist_u01 ON &mw_prefix.watchlist (wl_user, wl_namespace, wl_title);
 CREATE INDEX &mw_prefix.watchlist_i01 ON &mw_prefix.watchlist (wl_namespace, wl_title);
index effed56..17a8d2e 100644 (file)
@@ -73,7 +73,7 @@ class CLIParser extends Maintenance {
 
        public function execute() {
                $this->initParser();
-               print $this->render( $this->WikiText() );
+               print $this->render( $this->Wikitext() );
        }
 
        /**
index c9f049b..61cb198 100644 (file)
@@ -18,6 +18,7 @@ DROP SEQUENCE IF EXISTS ipblocks_ipb_id_seq CASCADE;
 DROP SEQUENCE IF EXISTS filearchive_fa_id_seq CASCADE;
 DROP SEQUENCE IF EXISTS uploadstash_us_id_seq CASCADE;
 DROP SEQUENCE IF EXISTS recentchanges_rc_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS watchlist_wl_id_seq CASCADE;
 DROP SEQUENCE IF EXISTS logging_log_id_seq CASCADE;
 DROP SEQUENCE IF EXISTS job_job_id_seq CASCADE;
 DROP SEQUENCE IF EXISTS category_cat_id_seq CASCADE;
@@ -447,7 +448,9 @@ CREATE INDEX new_name_timestamp ON recentchanges (rc_new, rc_namespace, rc_times
 CREATE INDEX rc_ip              ON recentchanges (rc_ip);
 
 
+CREATE SEQUENCE watchlist_wl_id_seq;
 CREATE TABLE watchlist (
+  wl_id                     INTEGER     NOT NULL  PRIMARY KEY DEFAULT nextval('watchlist_wl_id_seq'),
   wl_user                   INTEGER     NOT NULL  REFERENCES mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
   wl_namespace              SMALLINT    NOT NULL  DEFAULT 0,
   wl_title                  TEXT        NOT NULL,
index 4f478ac..aa5d69d 100644 (file)
@@ -21,6 +21,7 @@
  * @ingroup Maintenance
  */
 
+$optionsWithoutArgs = [ 'verbose' ];
 require_once __DIR__ . '/commandLine.inc';
 
 $wgHooks['BeforeParserFetchTemplateAndtitle'][] = 'PPFuzzTester::templateHook';
index 044bafd..230e86d 100644 (file)
@@ -38,7 +38,7 @@ class RebuildSitesCache extends Maintenance {
 
        public function execute() {
                $sitesCacheFileBuilder = new SitesCacheFileBuilder(
-                       new DBSiteStore(),
+                       \MediaWiki\MediaWikiServices::getInstance()->getSiteLookup(),
                        $this->getCacheFile()
                );
 
index 88767de..bdbb347 100644 (file)
@@ -68,9 +68,16 @@ class RefreshImageMetadata extends Maintenance {
                $this->addOption( 'start', 'Name of file to start with', false, true );
                $this->addOption( 'end', 'Name of file to end with', false, true );
 
+               $this->addOption(
+                       'mediatype',
+                       'Only refresh files with this media type, e.g. BITMAP, UNKNOWN etc.',
+                       false,
+                       true
+               );
                $this->addOption(
                        'mime',
-                       '(Inefficient!) Only refresh files with this MIME type. Can accept wild-card image/*',
+                       "Only refresh files with this MIME type. Can accept wild-card 'image/*'. "
+                               . "Potentially inefficient unless 'mediatype' is also specified",
                        false,
                        true
                );
@@ -197,6 +204,7 @@ class RefreshImageMetadata extends Maintenance {
 
                $end = $this->getOption( 'end', false );
                $mime = $this->getOption( 'mime', false );
+               $mediatype = $this->getOption( 'mediatype', false );
                $like = $this->getOption( 'metadata-contains', false );
 
                if ( $end !== false ) {
@@ -209,6 +217,9 @@ class RefreshImageMetadata extends Maintenance {
                                $conds['img_minor_mime'] = $minor;
                        }
                }
+               if ( $mediatype !== false ) {
+                       $conds['img_media_type'] = $mediatype;
+               }
                if ( $like ) {
                        $conds[] = 'img_metadata ' . $dbw->buildLike( $dbw->anyString(), $like, $dbw->anyString() );
                }
index 816e8a4..8d0873f 100644 (file)
@@ -34,6 +34,9 @@ class ResetUserEmail extends Maintenance {
                $this->addDescription( "Resets a user's email" );
                $this->addArg( 'user', 'Username or user ID, if starts with #', true );
                $this->addArg( 'email', 'Email to assign' );
+
+               $this->addOption( 'no-reset-password', 'Don\'t reset the user\'s password', false, false );
+
                parent::__construct();
        }
 
@@ -57,8 +60,11 @@ class ResetUserEmail extends Maintenance {
                $user->setEmail( $email );
                $user->setEmailAuthenticationTimestamp( wfTimestampNow() );
                $user->saveSettings();
-               // Kick whomever is currently controlling the account off
-               $user->setPassword( PasswordFactory::generateRandomPasswordString( 128 ) );
+
+               if ( !$this->hasOption( 'no-reset-password' ) ) {
+                       // Kick whomever is currently controlling the account off
+                       $user->setPassword( PasswordFactory::generateRandomPasswordString( 128 ) );
+               }
        }
 }
 
index 2d4e82a..454c506 100644 (file)
@@ -128,7 +128,7 @@ class SqliteMaintenance extends Maintenance {
        }
 
        private function checkSyntax() {
-               if ( !Sqlite::IsPresent() ) {
+               if ( !Sqlite::isPresent() ) {
                        $this->error( "Error: SQLite support not found\n" );
                }
                $files = [ $this->getOption( 'check-syntax' ) ];
diff --git a/maintenance/sqlite/archives/patch-watchlist-wl_id.sql b/maintenance/sqlite/archives/patch-watchlist-wl_id.sql
new file mode 100644 (file)
index 0000000..771f9b7
--- /dev/null
@@ -0,0 +1,23 @@
+DROP TABLE IF EXISTS /*_*/watchlist_tmp;
+
+CREATE TABLE /*$wgDBprefix*/watchlist_tmp (
+  wl_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  wl_user INTEGER  NOT NULL,
+  wl_namespace INTEGER NOT NULL default 0,
+  wl_title TEXT  NOT NULL default '',
+  wl_notificationtimestamp BLOB
+);
+
+INSERT OR IGNORE INTO /*_*/watchlist_tmp (
+    wl_user, wl_namespace, wl_title, wl_notificationtimestamp )
+    SELECT
+    wl_user, wl_namespace, wl_title, wl_notificationtimestamp
+    FROM /*_*/watchlist;
+
+DROP TABLE /*_*/watchlist;
+
+ALTER TABLE /*_*/watchlist_tmp RENAME TO /*_*/watchlist;
+
+CREATE UNIQUE INDEX /*i*/wl_user ON /*_*/watchlist (wl_user, wl_namespace, wl_title);
+CREATE INDEX /*i*/namespace_title ON /*_*/watchlist (wl_namespace, wl_title);
+CREATE INDEX /*i*/wl_user_notificationtimestamp ON /*_*/watchlist (wl_user, wl_notificationtimestamp);
index 9da3909..d69e5b9 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 if ( !defined( 'MEDIAWIKI' ) ) {
+       $optionsWithoutArgs = [ 'fix' ];
        require_once __DIR__ . '/../commandLine.inc';
 
        $cs = new CheckStorage;
index 8ea5d58..0ea52ca 100644 (file)
@@ -319,7 +319,7 @@ class FixBug20757 extends Maintenance {
                        if ( $path == "" ) {
                                return false;
                        }
-                       $text = ExternalStore::fetchFromUrl( $url );
+                       $text = ExternalStore::fetchFromURL( $url );
                }
                if ( !in_array( 'object', $flags ) ) {
                        return false;
index 776b72f..80dc7f9 100644 (file)
@@ -24,6 +24,7 @@
 define( 'REPORTING_INTERVAL', 1 );
 
 if ( !defined( 'MEDIAWIKI' ) ) {
+       $optionsWithArgs = [ 'e', 's' ];
        require_once __DIR__ . '/../commandLine.inc';
        require_once 'resolveStubs.php';
 
index 743b9be..89aeb9c 100644 (file)
@@ -619,8 +619,8 @@ CREATE INDEX /*i*/cl_sortkey ON /*_*/categorylinks (cl_to,cl_type,cl_sortkey,cl_
 -- Used by the API (and some extensions)
 CREATE INDEX /*i*/cl_timestamp ON /*_*/categorylinks (cl_to,cl_timestamp);
 
--- FIXME: Not used, delete this
-CREATE INDEX /*i*/cl_collation ON /*_*/categorylinks (cl_collation);
+-- Used when updating collation (e.g. updateCollation.php)
+CREATE INDEX /*i*/cl_collation_ext ON /*_*/categorylinks (cl_collation, cl_to, cl_type, cl_from);
 
 --
 -- Track all existing categories.  Something is a category if 1) it has an en-
@@ -1139,6 +1139,7 @@ CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp
 
 
 CREATE TABLE /*_*/watchlist (
+  wl_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
   -- Key to user.user_id
   wl_user int unsigned NOT NULL,
 
index ed8dfa9..775fa7b 100755 (executable)
@@ -83,6 +83,13 @@ class UpdateMediaWiki extends Maintenance {
                                "ABORTING (see https://bugs.php.net/bug.php?id=45996).\n",
                                true );
                }
+
+               if ( !function_exists( 'mb_strlen' ) ) {
+                       $this->error(
+                               "MediaWiki now requires the mbstring PHP extension, your system doesn't have it.\n"
+                               . "ABORTING.\n",
+                               true );
+               }
        }
 
        function execute() {
@@ -127,7 +134,7 @@ class UpdateMediaWiki extends Maintenance {
                        $this->compatChecks();
                } else {
                        $this->output( "Skipping compatibility checks, proceed at your own risk (Ctrl+C to abort)\n" );
-                       wfCountdown( 5 );
+                       wfCountDown( 5 );
                }
 
                // Check external dependencies are up to date
@@ -168,7 +175,7 @@ class UpdateMediaWiki extends Maintenance {
                        $updates[] = 'stats';
                }
 
-               $updater = DatabaseUpdater::newForDb( $db, $shared, $this );
+               $updater = DatabaseUpdater::newForDB( $db, $shared, $this );
                $updater->doUpdates( $updates );
 
                foreach ( $updater->getPostDatabaseUpdateMaintenance() as $maint ) {
index af666b0..186feb2 100644 (file)
@@ -33,7 +33,7 @@ require_once __DIR__ . '/Maintenance.php';
  * @ingroup Maintenance
  */
 class UpdateCollation extends Maintenance {
-       const BATCH_SIZE = 10000; // Number of rows to process in one batch
+       const BATCH_SIZE = 100; // Number of rows to process in one batch
        const SYNC_INTERVAL = 20; // Wait for slaves after this many batches
 
        public $sizeHistogram = [];
@@ -85,10 +85,18 @@ TEXT
                // but this will raise an exception, breaking all category pages
                $collation->getFirstLetter( 'MediaWiki' );
 
+               // Locally at least, (my local is a rather old version of mysql)
+               // mysql seems to filesort if there is both an equality
+               // (but not for an inequality) condition on cl_collation in the
+               // WHERE and it is also the first item in the ORDER BY.
+               if ( $this->hasOption( 'previous-collation' ) ) {
+                       $orderBy = 'cl_to, cl_type, cl_from';
+               } else {
+                       $orderBy = 'cl_collation, cl_to, cl_type, cl_from';
+               }
                $options = [
                        'LIMIT' => self::BATCH_SIZE,
-                       'ORDER BY' => 'cl_from, cl_to',
-                       'STRAIGHT_JOIN',
+                       'ORDER BY' => $orderBy,
                ];
 
                if ( $force || $dryRun ) {
@@ -124,16 +132,24 @@ TEXT
                        }
                        $this->output( "Fixing collation for $count rows.\n" );
                }
-
                $count = 0;
                $batchCount = 0;
                $batchConds = [];
                do {
                        $this->output( "Selecting next " . self::BATCH_SIZE . " rows..." );
+
+                       // cl_type must be selected as a number for proper paging because
+                       // enums suck.
+                       if ( $dbw->getType() === 'mysql' ) {
+                               $clType = 'cl_type+0 AS "cl_type_numeric"';
+                       } else {
+                               $clType = 'cl_type';
+                       }
                        $res = $dbw->select(
                                [ 'categorylinks', 'page' ],
                                [ 'cl_from', 'cl_to', 'cl_sortkey_prefix', 'cl_collation',
-                                       'cl_sortkey', 'page_namespace', 'page_title'
+                                       'cl_sortkey', $clType,
+                                       'page_namespace', 'page_title'
                                ],
                                array_merge( $collationConds, $batchConds, [ 'cl_from = page_id' ] ),
                                __METHOD__,
@@ -217,18 +233,28 @@ TEXT
 
        /**
         * Return an SQL expression selecting rows which sort above the given row,
-        * assuming an ordering of cl_from, cl_to
+        * assuming an ordering of cl_collation, cl_to, cl_type, cl_from
         * @param stdClass $row
         * @param DatabaseBase $dbw
         * @return string
         */
        function getBatchCondition( $row, $dbw ) {
-               $fields = [ 'cl_from', 'cl_to' ];
+               if ( $this->hasOption( 'previous-collation' ) ) {
+                       $fields = [ 'cl_to', 'cl_type', 'cl_from' ];
+               } else {
+                       $fields = [ 'cl_collation', 'cl_to', 'cl_type', 'cl_from' ];
+               }
                $first = true;
                $cond = false;
                $prefix = false;
                foreach ( $fields as $field ) {
-                       $encValue = $dbw->addQuotes( $row->$field );
+                       if ( $dbw->getType() === 'mysql' && $field === 'cl_type' ) {
+                               // Range conditions with enums are weird in mysql
+                               // This must be a numeric literal, or it won't work.
+                               $encValue = intval( $row->cl_type_numeric );
+                       } else {
+                               $encValue = $dbw->addQuotes( $row->$field );
+                       }
                        $inequality = "$field > $encValue";
                        $equality = "$field = $encValue";
                        if ( $first ) {
index 8a895f2..cdb7d9f 100644 (file)
@@ -61,7 +61,7 @@ class UpdateSearchIndex extends Maintenance {
        }
 
        public function execute() {
-               $posFile = $this->getOption( 'p', 'searchUpdate.' . wfWikiId() . '.pos' );
+               $posFile = $this->getOption( 'p', 'searchUpdate.' . wfWikiID() . '.pos' );
                $end = $this->getOption( 'e', wfTimestampNow() );
                if ( $this->hasOption( 's' ) ) {
                        $start = $this->getOption( 's' );
index cecfa9d..8bfb94d 100644 (file)
@@ -8,17 +8,17 @@
   "devDependencies": {
     "grunt": "0.4.5",
     "grunt-cli": "0.1.13",
-    "grunt-banana-checker": "0.4.0",
-    "grunt-contrib-copy": "0.8.2",
+    "grunt-banana-checker": "0.5.0",
+    "grunt-contrib-copy": "1.0.0",
     "grunt-contrib-jshint": "1.0.0",
-    "grunt-contrib-watch": "0.6.1",
-    "grunt-jscs": "2.7.0",
+    "grunt-contrib-watch": "1.0.0",
+    "grunt-jscs": "2.8.0",
     "grunt-jsonlint": "1.0.7",
-    "grunt-karma": "0.12.1",
-    "karma": "0.13.19",
+    "grunt-karma": "0.12.2",
+    "karma": "0.13.22",
     "karma-chrome-launcher": "0.2.2",
     "karma-firefox-launcher": "0.1.7",
     "karma-qunit": "0.1.9",
-    "qunitjs": "1.18.0"
+    "qunitjs": "1.22.0"
   }
 }
index 38c7aaa..edce2ea 100644 (file)
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -26,9 +26,9 @@
        <rule ref="Generic.ControlStructures.InlineControlStructure.NotAllowed">
                <severity>0</severity>
        </rule>
-       <exclude-pattern>node_modules</exclude-pattern>
-       <exclude-pattern>vendor</exclude-pattern>
-       <exclude-pattern>extensions</exclude-pattern>
-       <exclude-pattern>skins</exclude-pattern>
+       <exclude-pattern>node_modules/</exclude-pattern>
+       <exclude-pattern>vendor/</exclude-pattern>
+       <exclude-pattern type="relative">^extensions/</exclude-pattern>
+       <exclude-pattern type="relative">^skins/</exclude-pattern>
        <exclude-pattern>.git</exclude-pattern>
 </ruleset>
index bdf95a7..5cc5681 100644 (file)
@@ -436,6 +436,8 @@ return [
                        'ca' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js',
                        'cs' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js',
                        'da' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js',
+                       'de-at' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js',
+                       'de-ch' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js',
                        'de' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js',
                        'el' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js',
                        'en-au' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-AU.js',
@@ -482,8 +484,8 @@ return [
                        'sk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js',
                        'sl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js',
                        'sq' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js',
-                       'sr-sr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js',
-                       'sr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js',
+                       'sr-ec' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js',
+                       'sr-el' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js',
                        'sv' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js',
                        'ta' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js',
                        'th' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js',
@@ -797,8 +799,8 @@ return [
                        'sk' => 'resources/lib/moment/locale/sk.js',
                        'sl' => 'resources/lib/moment/locale/sl.js',
                        'sq' => 'resources/lib/moment/locale/sq.js',
-                       'sr' => 'resources/lib/moment/locale/sr.js',
                        'sr-ec' => 'resources/lib/moment/locale/sr-cyrl.js',
+                       'sr-el' => 'resources/lib/moment/locale/sr.js',
                        'sv' => 'resources/lib/moment/locale/sv.js',
                        'ta' => 'resources/lib/moment/locale/ta.js',
                        'th' => 'resources/lib/moment/locale/th.js',
@@ -811,6 +813,8 @@ return [
                        'vi' => 'resources/lib/moment/locale/vi.js',
                        'zh-cn' => 'resources/lib/moment/locale/zh-cn.js',
                        'zh-tw' => 'resources/lib/moment/locale/zh-tw.js',
+                       'zh-hans' => 'resources/lib/moment/locale/zh-cn.js',
+                       'zh-hant' => 'resources/lib/moment/locale/zh-tw.js',
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
@@ -1251,11 +1255,13 @@ return [
                        'api-error-unknown-error',
                        'api-error-uploaddisabled',
                        'api-error-verification-error',
+                       'api-error-was-deleted',
                        'fileexists',
                        'filepageexists',
                        'filename-bad-prefix',
                        'filename-thumb-name',
                        'badfilename',
+                       'protectedpagetext',
                        'api-error-blacklisted', // HACK
                ],
        ],
@@ -1332,7 +1338,6 @@ return [
                        'mediawiki.RegExp',
                        'mediawiki.notify',
                ],
-               'position' => 'top', // For $wgPreloadJavaScriptMwUtil
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.viewport' => [
@@ -1677,7 +1682,6 @@ return [
        'mediawiki.page.image.pagination' => [
                'scripts' => 'resources/src/mediawiki/page/image-pagination.js',
                'dependencies' => [
-                       'mediawiki.Uri',
                        'mediawiki.util',
                        'jquery.spinner',
                ],
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js
new file mode 100644 (file)
index 0000000..456c3a0
--- /dev/null
@@ -0,0 +1,22 @@
+/* Austrian German initialisation for the jQuery UI date picker plugin. */
+jQuery(function($){
+       $.datepicker.regional['de-AT'] = {
+               closeText: 'schließen',
+               prevText: '&#x3C;zurück',
+               nextText: 'Vor&#x3E;',
+               currentText: 'heute',
+               monthNames: ['Jänner','Februar','März','April','Mai','Juni',
+               'Juli','August','September','Oktober','November','Dezember'],
+               monthNamesShort: ['Jän','Feb','Mär','Apr','Mai','Jun',
+               'Jul','Aug','Sep','Okt','Nov','Dez'],
+               dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
+               dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+               dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+               weekHeader: 'KW',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['de-AT']);
+});
diff --git a/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js b/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js
new file mode 100644 (file)
index 0000000..60cbc29
--- /dev/null
@@ -0,0 +1,22 @@
+/* Swiss Standard German initialisation for the jQuery UI date picker plugin. */
+jQuery(function($){
+       $.datepicker.regional['de-CH'] = {
+               closeText: 'schliessen',
+               prevText: '&#x3C;zurück',
+               nextText: 'Vor&#x3E;',
+               currentText: 'heute',
+               monthNames: ['Januar','Februar','März','April','Mai','Juni',
+               'Juli','August','September','Oktober','November','Dezember'],
+               monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
+               'Jul','Aug','Sep','Okt','Nov','Dez'],
+               dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
+               dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+               dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+               weekHeader: 'KW',
+               dateFormat: 'dd.mm.yy',
+               firstDay: 1,
+               isRTL: false,
+               showMonthAfterYear: false,
+               yearSuffix: ''};
+       $.datepicker.setDefaults($.datepicker.regional['de-CH']);
+});
diff --git a/resources/lib/oojs-ui/i18n/azb.json b/resources/lib/oojs-ui/i18n/azb.json
new file mode 100644 (file)
index 0000000..313122c
--- /dev/null
@@ -0,0 +1,11 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Sadiqr"
+               ]
+       },
+       "ooui-dialog-message-reject": "وازگئچ",
+       "ooui-dialog-process-continue": "داوام ائت",
+       "ooui-selectfile-button-select": "بیر فایل سئچ",
+       "ooui-selectfile-placeholder": "هئچ فایل سئچیلمه‌ییب"
+}
index ff915b0..d8c99aa 100644 (file)
@@ -6,9 +6,24 @@
                        "Assele",
                        "Haqmar",
                        "Sagan",
-                       "Рустам Нурыев"
+                       "Рустам Нурыев",
+                       "Азат Хәлилов"
                ]
        },
-       "ooui-outline-control-move-down": "Аҫҡа күсерергә",
-       "ooui-outline-control-move-up": "Өҫкә күсерергә"
+       "ooui-outline-control-move-down": "Элементты аҫҡа күсерергә",
+       "ooui-outline-control-move-up": "Элементты өҫкә күсерергә",
+       "ooui-outline-control-remove": "Биттәрҙе юйырға",
+       "ooui-toolbar-more": "Тағы",
+       "ooui-toolgroup-expand": "Күберәк",
+       "ooui-toolgroup-collapse": "Аҙыраҡ",
+       "ooui-dialog-message-accept": "Тамам",
+       "ooui-dialog-message-reject": "Кире алырға",
+       "ooui-dialog-process-error": "Нимәлер килеп сыҡманы.",
+       "ooui-dialog-process-dismiss": "Йәшерергә",
+       "ooui-dialog-process-retry": "Ҡабатлап ҡарарға.",
+       "ooui-dialog-process-continue": "Дауам итергә",
+       "ooui-selectfile-button-select": "Файлды һайлағыҙ",
+       "ooui-selectfile-not-supported": "Файл һайлау хупланмай.",
+       "ooui-selectfile-placeholder": "Файл һайланмаған",
+       "ooui-selectfile-dragdrop-placeholder": "Файлды бында күсерегеҙ"
 }
index 573096f..ce007fc 100644 (file)
@@ -7,7 +7,8 @@
                        "Siddhartha Ghai",
                        "Goelujjwal",
                        "Ankita-ks",
-                       "Param Mudgal"
+                       "Param Mudgal",
+                       "Sfic"
                ]
        },
        "ooui-outline-control-move-down": "प्रविष्टि नीचे ले जाएँ",
@@ -22,6 +23,8 @@
        "ooui-dialog-process-dismiss": "ख़ारिज करें",
        "ooui-dialog-process-retry": "पुनः प्रयास करें",
        "ooui-dialog-process-continue": "जारी रखें",
+       "ooui-selectfile-button-select": "फ़ाइल चुनें",
        "ooui-selectfile-not-supported": "फ़ाइल का चयन समर्थित नहीं है",
-       "ooui-selectfile-placeholder": "कोई फाइल चुनी नही गई हेै"
+       "ooui-selectfile-placeholder": "कोई फाइल चुनी नही गई हेै",
+       "ooui-selectfile-dragdrop-placeholder": "फ़ाइल यहाँ डालें"
 }
index ddfcac2..31df169 100644 (file)
@@ -17,7 +17,7 @@
        "ooui-toolbar-more": "მეტი",
        "ooui-toolgroup-expand": "მეტი",
        "ooui-toolgroup-collapse": "რამდენიმე",
-       "ooui-dialog-message-accept": "á\83\99á\83\90á\83 á\83\92á\83\98",
+       "ooui-dialog-message-accept": "á\83\93á\83\98á\83\90á\83®",
        "ooui-dialog-message-reject": "გაუქმება",
        "ooui-dialog-process-error": "მოხდა რაღაც შეცდომა",
        "ooui-dialog-process-dismiss": "დამალვა",
diff --git a/resources/lib/oojs-ui/i18n/khw.json b/resources/lib/oojs-ui/i18n/khw.json
new file mode 100644 (file)
index 0000000..f0ce207
--- /dev/null
@@ -0,0 +1,12 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Rachitrali"
+               ]
+       },
+       "ooui-toolbar-more": "مزید",
+       "ooui-toolgroup-expand": "مزید",
+       "ooui-toolgroup-collapse": "ای کما",
+       "ooui-dialog-message-accept": "ٹھیک شیر",
+       "ooui-dialog-message-reject": "کھینسل"
+}
index 7fdf532..d94118d 100644 (file)
@@ -4,6 +4,12 @@
                        "Luuva"
                ]
        },
+       "ooui-outline-control-move-down": "Hāng-bo̍k sóa ē-té",
+       "ooui-outline-control-move-up": "Hāng-bo̍k sóa téng-bīn",
+       "ooui-outline-control-remove": "Sóa cháu hāng-bo̍k",
+       "ooui-toolbar-more": "Khah chē",
+       "ooui-toolgroup-expand": "Khah chē",
+       "ooui-toolgroup-collapse": "Khah kiám",
        "ooui-dialog-message-accept": "Liáu-kái",
        "ooui-dialog-message-reject": "Chhú-siau",
        "ooui-dialog-process-error": "Ū mi̍h bô hó-sè",
index 1e1b05d..1e4bb55 100644 (file)
@@ -17,6 +17,8 @@
        "ooui-dialog-process-dismiss": "Сап",
        "ooui-dialog-process-retry": "Хатылаан көр",
        "ooui-dialog-process-continue": "Салгыы",
+       "ooui-selectfile-button-select": "Билэни тал",
        "ooui-selectfile-not-supported": "Билэни талыы өйөммөт",
-       "ooui-selectfile-placeholder": "Биир да билэ талыллыбатах"
+       "ooui-selectfile-placeholder": "Биир да билэ талыллыбатах",
+       "ooui-selectfile-dragdrop-placeholder": "Билэни манна сыҕарыт"
 }
index f70efe1..027b7be 100644 (file)
@@ -32,6 +32,6 @@
        "ooui-dialog-process-continue": "繼續",
        "ooui-selectfile-button-select": "選擇一個檔案",
        "ooui-selectfile-not-supported": "無法支援所選擇的檔案",
-       "ooui-selectfile-placeholder": "未選擇檔案",
+       "ooui-selectfile-placeholder": "未選擇檔案",
        "ooui-selectfile-dragdrop-placeholder": "拖曳檔案到此處"
 }
index d297933..4bd0429 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:49Z
+ * Date: 2016-04-07T15:12:41Z
  */
 ( function ( OO ) {
 
index 8b92d89..1d13c69 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-element-hidden {
        display: none !important;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
 }
+.oo-ui-floatableElement-hidden {
+       display: none;
+}
 .oo-ui-iconElement .oo-ui-iconElement-icon,
 .oo-ui-iconElement.oo-ui-iconElement-icon {
        background-size: contain;
 .oo-ui-decoratedOptionWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
        opacity: 0.2;
 }
-.oo-ui-radioSelectWidget {
-       padding: 0.75em 0 0.5em 0;
-}
 .oo-ui-radioOptionWidget {
        cursor: default;
        padding: 0;
 }
 .oo-ui-dropdownInputWidget select {
        width: 100%;
-       resize: none;
+       cursor: pointer;
        -webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
 .oo-ui-textInputWidget textarea {
        overflow: auto;
 }
-.oo-ui-textInputWidget input[type="search"] {
+.oo-ui-textInputWidget [type="search"] {
        -webkit-appearance: texfield;
 }
-.oo-ui-textInputWidget input[type="search"]::-ms-clear {
+.oo-ui-textInputWidget [type="search"]::-ms-clear {
        display: none;
 }
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-decoration,
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-cancel-button,
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-results-button,
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-results-decoration {
+.oo-ui-textInputWidget [type="search"]::-webkit-search-decoration,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-cancel-button,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-results-button,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-results-decoration {
        display: none;
 }
 .oo-ui-textInputWidget > .oo-ui-iconElement-icon,
index 6ff352c..074c1b2 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-element-hidden {
        display: none !important;
@@ -69,7 +69,7 @@
 }
 .oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus {
        box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.2);
-       outline: none;
+       outline: 0;
 }
 .oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button .oo-ui-indicatorElement-indicator {
        margin-right: 0;
 }
 .oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:hover,
 .oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:focus {
-       outline: none;
+       outline: 0;
 }
 .oo-ui-buttonElement-framed > input.oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
        color: #347bff;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
-       background-color: rgba(52, 123, 255, 0.1);
-       border-color: rgba(31, 73, 153, 0.5);
+       background-color: #ebf2ff;
+       border-color: #859dcc;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
        box-shadow: inset 0 0 0 1px #1f4999;
        color: #347bff;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
-       background-color: rgba(52, 123, 255, 0.1);
-       border-color: rgba(31, 73, 153, 0.5);
+       background-color: #ebf2ff;
+       border-color: #859dcc;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
        box-shadow: inset 0 0 0 1px #1f4999;
        color: #d11d13;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
-       background-color: rgba(209, 29, 19, 0.1);
-       border-color: rgba(115, 16, 10, 0.5);
+       background-color: #fbe8e7;
+       border-color: #b77c79;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
        box-shadow: inset 0 0 0 1px #73100a;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
 }
+.oo-ui-floatableElement-hidden {
+       display: none;
+}
 .oo-ui-iconElement .oo-ui-iconElement-icon,
 .oo-ui-iconElement.oo-ui-iconElement-icon {
        background-size: contain;
        font: inherit;
        vertical-align: middle;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"] {
+.oo-ui-checkboxInputWidget [type="checkbox"] {
        opacity: 0;
        z-index: 1;
        position: relative;
        height: 1.6em;
        max-width: none;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"] + span {
+.oo-ui-checkboxInputWidget [type="checkbox"] + span {
        -webkit-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
           -moz-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
                transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
                box-sizing: border-box;
        position: absolute;
        left: 0;
-       border-radius: 2px;
        width: 1.6em;
        height: 1.6em;
-       background-color: white;
-       border: 1px solid #777777;
+       background-color: #ffffff;
        background-image: url("themes/mediawiki/images/icons/check-constructive-deprecated.png");
        background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-constructive-deprecated.svg");
        background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-constructive-deprecated.svg");
        background-position: center center;
        background-origin: border-box;
        background-size: 0 0;
+       border: 1px solid #777777;
+       border-radius: 2px;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:checked + span {
+.oo-ui-checkboxInputWidget [type="checkbox"]:checked + span {
        background-size: 100% 100%;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:active + span {
+.oo-ui-checkboxInputWidget [type="checkbox"]:active + span {
        background-color: #cccccc;
        border-color: #cccccc;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:focus + span {
+.oo-ui-checkboxInputWidget [type="checkbox"]:focus + span {
        border-width: 2px;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:focus:hover + span,
-.oo-ui-checkboxInputWidget input[type="checkbox"]:hover + span {
+.oo-ui-checkboxInputWidget [type="checkbox"]:focus:hover + span,
+.oo-ui-checkboxInputWidget [type="checkbox"]:hover + span {
        border-bottom-width: 3px;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:disabled {
+.oo-ui-checkboxInputWidget [type="checkbox"]:disabled {
        cursor: default;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:disabled + span {
+.oo-ui-checkboxInputWidget [type="checkbox"]:disabled + span {
        background-color: #dddddd;
        border-color: #dddddd;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:disabled:checked + span {
+.oo-ui-checkboxInputWidget [type="checkbox"]:disabled:checked + span {
        background-image: url("themes/mediawiki/images/icons/check-invert.png");
        background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-invert.svg");
        background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-invert.svg");
 }
 .oo-ui-dropdownInputWidget select {
        width: 100%;
-       resize: none;
+       cursor: pointer;
        -webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
 .oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:hover,
 .oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:focus {
        border-color: #aaaaaa;
-       outline: none;
+       outline: 0;
 }
 .oo-ui-dropdownInputWidget.oo-ui-widget-disabled select {
        color: #cccccc;
        font: inherit;
        vertical-align: middle;
 }
-.oo-ui-radioInputWidget input[type="radio"] {
+.oo-ui-radioInputWidget [type="radio"] {
        opacity: 0;
        z-index: 1;
        position: relative;
        height: 1.6em;
        max-width: none;
 }
-.oo-ui-radioInputWidget input[type="radio"] + span {
+.oo-ui-radioInputWidget [type="radio"] + span {
        -webkit-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
           -moz-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
                transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
                box-sizing: border-box;
        position: absolute;
        left: 0;
-       border-radius: 100%;
        width: 1.6em;
        height: 1.6em;
-       background: white;
-       border: 1px solid #777777;
+       background-color: #ffffff;
        background-image: url("themes/mediawiki/images/icons/circle-constructive-deprecated.png");
        background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-constructive-deprecated.svg");
        background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-constructive-deprecated.svg");
        background-position: center center;
        background-origin: border-box;
        background-size: 0 0;
+       border: 1px solid #777777;
+       border-radius: 100%;
 }
-.oo-ui-radioInputWidget input[type="radio"]:checked + span {
+.oo-ui-radioInputWidget [type="radio"]:checked + span {
        background-size: 100% 100%;
 }
-.oo-ui-radioInputWidget input[type="radio"]:active + span {
+.oo-ui-radioInputWidget [type="radio"]:active + span {
        background-color: #cccccc;
        border-color: #cccccc;
 }
-.oo-ui-radioInputWidget input[type="radio"]:focus + span {
+.oo-ui-radioInputWidget [type="radio"]:focus + span {
        border-width: 2px;
 }
-.oo-ui-radioInputWidget input[type="radio"]:focus:hover + span,
-.oo-ui-radioInputWidget input[type="radio"]:hover + span {
+.oo-ui-radioInputWidget [type="radio"]:focus:hover + span,
+.oo-ui-radioInputWidget [type="radio"]:hover + span {
        border-bottom-width: 3px;
 }
-.oo-ui-radioInputWidget input[type="radio"]:disabled {
+.oo-ui-radioInputWidget [type="radio"]:disabled {
        cursor: default;
 }
-.oo-ui-radioInputWidget input[type="radio"]:disabled + span {
+.oo-ui-radioInputWidget [type="radio"]:disabled + span {
        background-color: #dddddd;
        border-color: #dddddd;
 }
-.oo-ui-radioInputWidget input[type="radio"]:disabled:checked + span {
+.oo-ui-radioInputWidget [type="radio"]:disabled:checked + span {
        background-image: url("themes/mediawiki/images/icons/circle-invert.png");
        background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-invert.svg");
        background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-invert.svg");
 .oo-ui-radioSelectInputWidget .oo-ui-fieldLayout {
        margin-bottom: 0;
 }
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body {
+       padding: 0.25em 0;
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body .oo-ui-labelElement-label {
+       line-height: 1.5em;
+}
 .oo-ui-textInputWidget {
        position: relative;
        vertical-align: middle;
 .oo-ui-textInputWidget textarea {
        overflow: auto;
 }
-.oo-ui-textInputWidget input[type="search"] {
+.oo-ui-textInputWidget [type="search"] {
        -webkit-appearance: texfield;
 }
-.oo-ui-textInputWidget input[type="search"]::-ms-clear {
+.oo-ui-textInputWidget [type="search"]::-ms-clear {
        display: none;
 }
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-decoration,
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-cancel-button,
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-results-button,
-.oo-ui-textInputWidget input[type="search"]::-webkit-search-results-decoration {
+.oo-ui-textInputWidget [type="search"]::-webkit-search-decoration,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-cancel-button,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-results-button,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-results-decoration {
        display: none;
 }
 .oo-ui-textInputWidget > .oo-ui-iconElement-icon,
 }
 .oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
 .oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
-       outline: none;
+       outline: 0;
        border-color: #347bff;
        box-shadow: inset 0 0 0 0.1em #347bff;
 }
index f587a39..a05193e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:49Z
+ * Date: 2016-04-07T15:12:41Z
  */
 ( function ( OO ) {
 
@@ -260,6 +260,58 @@ OO.ui.debounce = function ( func, wait, immediate ) {
        };
 };
 
+/**
+ * Returns a function, that, when invoked, will only be triggered at most once
+ * during a given window of time. If called again during that window, it will
+ * wait until the window ends and then trigger itself again.
+ *
+ * As it's not knowable to the caller whether the function will actually run
+ * when the wrapper is called, return values from the function are entirely
+ * discarded.
+ *
+ * @param {Function} func
+ * @param {number} wait
+ * @return {Function}
+ */
+OO.ui.throttle = function ( func, wait ) {
+       var context, args, timeout,
+               previous = 0,
+               run = function () {
+                       timeout = null;
+                       previous = OO.ui.now();
+                       func.apply( context, args );
+               };
+       return function () {
+               // Check how long it's been since the last time the function was
+               // called, and whether it's more or less than the requested throttle
+               // period. If it's less, run the function immediately. If it's more,
+               // set a timeout for the remaining time -- but don't replace an
+               // existing timeout, since that'd indefinitely prolong the wait.
+               var remaining = wait - ( OO.ui.now() - previous );
+               context = this;
+               args = arguments;
+               if ( remaining <= 0 ) {
+                       // Note: unless wait was ridiculously large, this means we'll
+                       // automatically run the first time the function was called in a
+                       // given period. (If you provide a wait period larger than the
+                       // current Unix timestamp, you *deserve* unexpected behavior.)
+                       clearTimeout( timeout );
+                       run();
+               } else if ( !timeout ) {
+                       timeout = setTimeout( run, remaining );
+               }
+       };
+};
+
+/**
+ * A (possibly faster) way to get the current timestamp as an integer
+ *
+ * @return {number} Current timestamp
+ */
+OO.ui.now = Date.now || function () {
+       return new Date().getTime();
+};
+
 /**
  * Proxy for `node.addEventListener( eventName, handler, true )`.
  *
@@ -685,7 +737,7 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
                                infused.$element.removeData( 'ooui-infused-children' );
                                return infused;
                        }
-                       if ( value.html ) {
+                       if ( value.html !== undefined ) {
                                return new OO.ui.HtmlSnippet( value.html );
                        }
                }
@@ -2000,6 +2052,16 @@ OO.ui.mixin.GroupElement = function OoUiMixinGroupElement( config ) {
        this.setGroupElement( config.$group || $( '<div>' ) );
 };
 
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the set of selected items changes.
+ *
+ * @param {OO.ui.Element[]} items Items currently in the group
+ */
+
 /* Methods */
 
 /**
@@ -2191,6 +2253,7 @@ OO.ui.mixin.GroupElement.prototype.addItems = function ( items, index ) {
                this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
        }
 
+       this.emit( 'change', this.getItems() );
        return this;
 };
 
@@ -2227,6 +2290,7 @@ OO.ui.mixin.GroupElement.prototype.removeItems = function ( items ) {
                }
        }
 
+       this.emit( 'change', this.getItems() );
        return this;
 };
 
@@ -2258,6 +2322,7 @@ OO.ui.mixin.GroupElement.prototype.clearItems = function () {
                item.$element.detach();
        }
 
+       this.emit( 'change', this.getItems() );
        this.items = [];
        return this;
 };
@@ -2736,9 +2801,7 @@ OO.ui.mixin.LabelElement.prototype.setLabelElement = function ( $label ) {
  */
 OO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {
        label = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;
-       label = ( ( typeof label === 'string' && label.length ) || label instanceof jQuery || label instanceof OO.ui.HtmlSnippet ) ? label : null;
-
-       this.$element.toggleClass( 'oo-ui-labelElement', !!label );
+       label = ( ( typeof label === 'string' || label instanceof jQuery ) && label.length ) || ( label instanceof OO.ui.HtmlSnippet && label.toString().length ) ? label : null;
 
        if ( this.label !== label ) {
                if ( this.$label ) {
@@ -2748,6 +2811,8 @@ OO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {
                this.emit( 'labelChange' );
        }
 
+       this.$element.toggleClass( 'oo-ui-labelElement', !!this.label );
+
        return this;
 };
 
@@ -3054,7 +3119,7 @@ OO.ui.mixin.TitledElement = function OoUiMixinTitledElement( config ) {
        this.title = null;
 
        // Initialization
-       this.setTitle( config.title || this.constructor.static.title );
+       this.setTitle( config.title !== undefined ? config.title : this.constructor.static.title );
        this.setTitledElement( config.$titled || this.$element );
 };
 
@@ -4052,6 +4117,9 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () {
                ccWidth + ccOffset.left :
                ( scOffset.left + scrollLeft + scWidth ) - ccOffset.left;
        desiredHeight = ( scOffset.top + scrollTop + scHeight ) - ccOffset.top;
+       // It should never be desirable to exceed the dimensions of the browser viewport... right?
+       desiredWidth = Math.min( desiredWidth, document.documentElement.clientWidth );
+       desiredHeight = Math.min( desiredHeight, document.documentElement.clientHeight );
        allotedWidth = Math.ceil( desiredWidth - extraWidth );
        allotedHeight = Math.ceil( desiredHeight - extraHeight );
        naturalWidth = this.$clippable.prop( 'scrollWidth' );
@@ -6563,22 +6631,19 @@ OO.ui.mixin.FloatableElement.prototype.togglePositioning = function ( positionin
 
                closestScrollableOfContainer = OO.ui.Element.static.getClosestScrollableContainer( this.$floatableContainer[ 0 ] );
                closestScrollableOfFloatable = OO.ui.Element.static.getClosestScrollableContainer( this.$floatable[ 0 ] );
-               if ( closestScrollableOfContainer !== closestScrollableOfFloatable ) {
-                       // If the scrollable is the root, we have to listen to scroll events
-                       // on the window because of browser inconsistencies (or do we? someone should verify this)
-                       if ( $( closestScrollableOfContainer ).is( 'html, body' ) ) {
-                               closestScrollableOfContainer = OO.ui.Element.static.getWindow( closestScrollableOfContainer );
-                       }
+               this.needsCustomPosition = closestScrollableOfContainer !== closestScrollableOfFloatable;
+               // If the scrollable is the root, we have to listen to scroll events
+               // on the window because of browser inconsistencies.
+               if ( $( closestScrollableOfContainer ).is( 'html, body' ) ) {
+                       closestScrollableOfContainer = OO.ui.Element.static.getWindow( closestScrollableOfContainer );
                }
 
                if ( positioning ) {
                        this.$floatableWindow = $( this.getElementWindow() );
                        this.$floatableWindow.on( 'resize', this.onFloatableWindowResizeHandler );
 
-                       if ( closestScrollableOfContainer !== closestScrollableOfFloatable ) {
-                               this.$floatableClosestScrollable = $( closestScrollableOfContainer );
-                               this.$floatableClosestScrollable.on( 'scroll', this.onFloatableScrollHandler );
-                       }
+                       this.$floatableClosestScrollable = $( closestScrollableOfContainer );
+                       this.$floatableClosestScrollable.on( 'scroll', this.onFloatableScrollHandler );
 
                        // Initial position after visible
                        this.position();
@@ -6600,6 +6665,50 @@ OO.ui.mixin.FloatableElement.prototype.togglePositioning = function ( positionin
        return this;
 };
 
+/**
+ * Check whether the bottom edge of the given element is within the viewport of the given container.
+ *
+ * @private
+ * @param {jQuery} $element
+ * @param {jQuery} $container
+ * @return {boolean}
+ */
+OO.ui.mixin.FloatableElement.prototype.isElementInViewport = function ( $element, $container ) {
+       var elemRect, contRect,
+               topEdgeInBounds = false,
+               leftEdgeInBounds = false,
+               bottomEdgeInBounds = false,
+               rightEdgeInBounds = false;
+
+       elemRect = $element[ 0 ].getBoundingClientRect();
+       if ( $container[ 0 ] === window ) {
+               contRect = {
+                       top: 0,
+                       left: 0,
+                       right: document.documentElement.clientWidth,
+                       bottom: document.documentElement.clientHeight
+               };
+       } else {
+               contRect = $container[ 0 ].getBoundingClientRect();
+       }
+
+       if ( elemRect.top >= contRect.top && elemRect.top <= contRect.bottom ) {
+               topEdgeInBounds = true;
+       }
+       if ( elemRect.left >= contRect.left && elemRect.left <= contRect.right ) {
+               leftEdgeInBounds = true;
+       }
+       if ( elemRect.bottom >= contRect.top && elemRect.bottom <= contRect.bottom ) {
+               bottomEdgeInBounds = true;
+       }
+       if ( elemRect.right >= contRect.left && elemRect.right <= contRect.right ) {
+               rightEdgeInBounds = true;
+       }
+
+       // We only care that any part of the bottom edge is visible
+       return bottomEdgeInBounds && ( leftEdgeInBounds || rightEdgeInBounds );
+};
+
 /**
  * Position the floatable below its container.
  *
@@ -6614,6 +6723,17 @@ OO.ui.mixin.FloatableElement.prototype.position = function () {
                return this;
        }
 
+       if ( !this.isElementInViewport( this.$floatableContainer, this.$floatableClosestScrollable ) ) {
+               this.$floatable.addClass( 'oo-ui-floatableElement-hidden' );
+               return;
+       } else {
+               this.$floatable.removeClass( 'oo-ui-floatableElement-hidden' );
+       }
+
+       if ( !this.needsCustomPosition ) {
+               return;
+       }
+
        pos = OO.ui.Element.static.getRelativePosition( this.$floatableContainer, this.$floatable.offsetParent() );
 
        // Position under container
@@ -6745,7 +6865,8 @@ OO.ui.InputWidget = function OoUiInputWidget( config ) {
        OO.ui.InputWidget.parent.call( this, config );
 
        // Properties
-       this.$input = this.getInputElement( config );
+       // See #reusePreInfuseDOM about config.$input
+       this.$input = config.$input || this.getInputElement( config );
        this.value = '';
        this.inputFilter = config.inputFilter;
 
@@ -6801,9 +6922,11 @@ OO.ui.InputWidget.static.reusePreInfuseDOM = function ( node, config ) {
  */
 OO.ui.InputWidget.static.gatherPreInfuseState = function ( node, config ) {
        var state = OO.ui.InputWidget.parent.static.gatherPreInfuseState( node, config );
-       state.value = config.$input.val();
-       // Might be better in TabIndexedElement, but it's awkward to do there because mixins are awkward
-       state.focus = config.$input.is( ':focus' );
+       if ( config.$input && config.$input.length ) {
+               state.value = config.$input.val();
+               // Might be better in TabIndexedElement, but it's awkward to do there because mixins are awkward
+               state.focus = config.$input.is( ':focus' );
+       }
        return state;
 };
 
@@ -6829,9 +6952,8 @@ OO.ui.InputWidget.static.gatherPreInfuseState = function ( node, config ) {
  * @param {Object} config Configuration options
  * @return {jQuery} Input element
  */
-OO.ui.InputWidget.prototype.getInputElement = function ( config ) {
-       // See #reusePreInfuseDOM about config.$input
-       return config.$input || $( '<input>' );
+OO.ui.InputWidget.prototype.getInputElement = function () {
+       return $( '<input>' );
 };
 
 /**
@@ -7026,6 +7148,11 @@ OO.ui.ButtonInputWidget = function OoUiButtonInputWidget( config ) {
        // Configuration initialization
        config = $.extend( { type: 'button', useInputTag: false }, config );
 
+       // See InputWidget#reusePreInfuseDOM about config.$input
+       if ( config.$input ) {
+               config.$input.empty();
+       }
+
        // Properties (must be set before parent constructor, which calls #setValue)
        this.useInputTag = config.useInputTag;
 
@@ -7071,10 +7198,6 @@ OO.ui.ButtonInputWidget.static.supportsSimpleLabel = false;
  */
 OO.ui.ButtonInputWidget.prototype.getInputElement = function ( config ) {
        var type;
-       // See InputWidget#reusePreInfuseDOM about config.$input
-       if ( config.$input ) {
-               return config.$input.empty();
-       }
        type = [ 'button', 'submit', 'reset' ].indexOf( config.type ) !== -1 ? config.type : 'button';
        return $( '<' + ( config.useInputTag ? 'input' : 'button' ) + ' type="' + type + '">' );
 };
@@ -7089,22 +7212,20 @@ OO.ui.ButtonInputWidget.prototype.getInputElement = function ( config ) {
  * @chainable
  */
 OO.ui.ButtonInputWidget.prototype.setLabel = function ( label ) {
-       OO.ui.mixin.LabelElement.prototype.setLabel.call( this, label );
+       if ( typeof label === 'function' ) {
+               label = OO.ui.resolveMsg( label );
+       }
 
        if ( this.useInputTag ) {
-               if ( typeof label === 'function' ) {
-                       label = OO.ui.resolveMsg( label );
-               }
-               if ( label instanceof jQuery ) {
-                       label = label.text();
-               }
-               if ( !label ) {
+               // Discard non-plaintext labels
+               if ( typeof label !== 'string' ) {
                        label = '';
                }
+
                this.$input.val( label );
        }
 
-       return this;
+       return OO.ui.mixin.LabelElement.prototype.setLabel.call( this, label );
 };
 
 /**
@@ -7296,6 +7417,11 @@ OO.ui.DropdownInputWidget = function OoUiDropdownInputWidget( config ) {
        // Configuration initialization
        config = config || {};
 
+       // See InputWidget#reusePreInfuseDOM about config.$input
+       if ( config.$input ) {
+               config.$input.addClass( 'oo-ui-element-hidden' );
+       }
+
        // Properties (must be done before parent constructor which calls #setDisabled)
        this.dropdownWidget = new OO.ui.DropdownWidget( config.dropdown );
 
@@ -7326,11 +7452,7 @@ OO.mixinClass( OO.ui.DropdownInputWidget, OO.ui.mixin.TitledElement );
  * @inheritdoc
  * @protected
  */
-OO.ui.DropdownInputWidget.prototype.getInputElement = function ( config ) {
-       // See InputWidget#reusePreInfuseDOM about config.$input
-       if ( config.$input ) {
-               return config.$input.addClass( 'oo-ui-element-hidden' );
-       }
+OO.ui.DropdownInputWidget.prototype.getInputElement = function () {
        return $( '<input>' ).attr( 'type', 'hidden' );
 };
 
@@ -7601,6 +7723,16 @@ OO.ui.RadioSelectInputWidget.static.gatherPreInfuseState = function ( node, conf
        return state;
 };
 
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
+       config = OO.ui.RadioSelectInputWidget.parent.static.reusePreInfuseDOM( node, config );
+       // Cannot reuse the `<input type=radio>` set
+       delete config.$input;
+       return config;
+};
+
 /* Methods */
 
 /**
@@ -7805,7 +7937,7 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
                .append( this.$icon, this.$indicator );
        this.setReadOnly( !!config.readOnly );
        this.updateSearchIndicator();
-       if ( config.placeholder ) {
+       if ( config.placeholder !== undefined ) {
                this.$input.attr( 'placeholder', config.placeholder );
        }
        if ( config.maxLength !== undefined ) {
@@ -8573,7 +8705,8 @@ OO.ui.TextInputWidget.prototype.restorePreInfuseState = function ( state ) {
 OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) {
        // Configuration initialization
        config = $.extend( {
-               indicator: 'down'
+               indicator: 'down',
+               autocomplete: false
        }, config );
        // For backwards-compatibility with ComboBoxWidget config
        $.extend( config, config.input );
index c2bf522..5bd3ac7 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:49Z
+ * Date: 2016-04-07T15:12:41Z
  */
 ( function ( OO ) {
 
@@ -49,11 +49,15 @@ OO.ui.MediaWikiTheme.prototype.getElementClasses = function ( element ) {
                isFramed = element.supports( [ 'isFramed' ] ) && element.isFramed();
                isActive = element.supports( [ 'isActive' ] ) && element.isActive();
                if (
-                       ( isFramed && ( isActive || element.isDisabled() || element.hasFlag( 'primary' ) ) ) ||
-                       ( !isFramed && element.hasFlag( 'primary' ) )
+                       ( isFramed && ( isActive || element.isDisabled() || element.hasFlag( 'primary' ) ) )
                ) {
+                       // Button with a dark background, use white icon
                        variants.invert = true;
+               } else if ( !isFramed && element.isDisabled() ) {
+                       // Frameless disabled button, always use black icon regardless of flags
+                       variants.invert = false;
                } else {
+                       // Any other kind of button, use the right colored icon if available
                        variants.progressive = element.hasFlag( 'progressive' );
                        variants.constructive = element.hasFlag( 'constructive' );
                        variants.destructive = element.hasFlag( 'destructive' );
index 0ea3006..d2e25a0 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-popupTool .oo-ui-popupWidget-popup,
 .oo-ui-popupTool .oo-ui-popupWidget-anchor {
index 90b7f83..35a7ef3 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-popupTool .oo-ui-popupWidget-popup,
 .oo-ui-popupTool .oo-ui-popupWidget-anchor {
index 6fddd25..7d22b8f 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:49Z
+ * Date: 2016-04-07T15:12:41Z
  */
 ( function ( OO ) {
 
index 2d60c08..cd7cbd5 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-draggableElement-handle,
 .oo-ui-draggableElement-handle.oo-ui-widget {
        position: relative;
        overflow: hidden;
 }
-.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button > input[type="file"] {
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button > [type="file"] {
        position: absolute;
        margin: 0;
        top: 0;
        cursor: pointer;
        padding-top: 100px;
 }
-.oo-ui-selectFileWidget-selectButton.oo-ui-widget-disabled > .oo-ui-buttonElement-button > input[type="file"] {
+.oo-ui-selectFileWidget-selectButton.oo-ui-widget-disabled > .oo-ui-buttonElement-button > [type="file"] {
        display: none;
 }
 .oo-ui-selectFileWidget-info {
        width: 5.5em;
 }
 .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
-       border: none;
+       border: 0;
        background: none;
        display: block;
        height: 100%;
        border-bottom-left-radius: 0;
        border-left-width: 0;
 }
-.oo-ui-numberInputWidget .oo-ui-textInputWidget input {
+.oo-ui-numberInputWidget-buttoned .oo-ui-textInputWidget input {
        border-radius: 0;
 }
index 165a6c2..5a905db 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-draggableElement-handle,
 .oo-ui-draggableElement-handle.oo-ui-widget {
 }
 .oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus {
        border-color: #347bff;
-       outline: none;
+       outline: 0;
 }
 .oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus.oo-ui-toggleWidget-on {
        border-color: #347bff;
        box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
 }
 .oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
-       background: #dddddd;
+       background-color: #dddddd;
        border-color: #dddddd;
        outline: 0;
 }
 .oo-ui-toggleSwitchWidget.oo-ui-widget-disabled .oo-ui-toggleSwitchWidget-grip {
-       background: #ffffff;
+       background-color: #ffffff;
 }
 .oo-ui-progressBarWidget {
        max-width: 50em;
        overflow: hidden;
 }
 .oo-ui-progressBarWidget-bar {
+       background-color: #dddddd;
        height: 1em;
-       background: #dddddd;
        -webkit-transition: width 200ms, margin-left 200ms;
           -moz-transition: width 200ms, margin-left 200ms;
                transition: width 200ms, margin-left 200ms;
        position: relative;
        overflow: hidden;
 }
-.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button > input[type="file"] {
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button > [type="file"] {
        position: absolute;
        margin: 0;
        top: 0;
        cursor: pointer;
        padding-top: 100px;
 }
-.oo-ui-selectFileWidget-selectButton.oo-ui-widget-disabled > .oo-ui-buttonElement-button > input[type="file"] {
+.oo-ui-selectFileWidget-selectButton.oo-ui-widget-disabled > .oo-ui-buttonElement-button > [type="file"] {
        display: none;
 }
 .oo-ui-selectFileWidget-info {
        width: 5.5em;
 }
 .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
-       border: none;
+       border: 0;
        background: none;
        display: block;
        height: 100%;
        right: 2em;
 }
 .oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop .oo-ui-selectFileWidget-dropTarget {
-       background-color: rgba(52, 123, 255, 0.1);
+       background-color: #ebf2ff;
 }
 .oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
 .oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
        vertical-align: middle;
 }
 .oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-capsuleMultiSelectWidget-content > input:focus {
-       outline: none;
+       outline: 0;
 }
 .oo-ui-capsuleMultiSelectWidget.oo-ui-indicatorElement .oo-ui-capsuleMultiSelectWidget-handle {
        padding-right: 2.4875em;
        overflow: hidden;
 }
 .oo-ui-capsuleItemWidget:focus {
-       outline: none;
+       outline: 0;
        border-color: #347bff;
 }
 .oo-ui-capsuleItemWidget.oo-ui-widget-disabled {
        border-bottom-left-radius: 0;
        border-left-width: 0;
 }
-.oo-ui-numberInputWidget .oo-ui-textInputWidget input {
+.oo-ui-numberInputWidget-buttoned .oo-ui-textInputWidget input {
        border-radius: 0;
 }
index 04137da..ec215f1 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:49Z
+ * Date: 2016-04-07T15:12:41Z
  */
 ( function ( OO ) {
 
@@ -5048,6 +5048,7 @@ OO.ui.SearchWidget.prototype.getResults = function () {
  * @cfg {number} [max=Infinity] Maximum allowed value
  * @cfg {number} [step=1] Delta when using the buttons or up/down arrow keys
  * @cfg {number|null} [pageStep] Delta when using the page-up/page-down keys. Defaults to 10 times #step.
+ * @cfg {boolean} [showButtons=true] Whether to show the plus and minus buttons.
  */
 OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
        // Configuration initialization
@@ -5056,7 +5057,8 @@ OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
                min: -Infinity,
                max: Infinity,
                step: 1,
-               pageStep: null
+               pageStep: null,
+               showButtons: true
        }, config );
 
        // Parent constructor
@@ -5069,28 +5071,30 @@ OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
                },
                config.input
        ) );
-       this.minusButton = new OO.ui.ButtonWidget( $.extend(
-               {
-                       disabled: this.isDisabled(),
-                       tabIndex: -1
-               },
-               config.minusButton,
-               {
-                       classes: [ 'oo-ui-numberInputWidget-minusButton' ],
-                       label: '−'
-               }
-       ) );
-       this.plusButton = new OO.ui.ButtonWidget( $.extend(
-               {
-                       disabled: this.isDisabled(),
-                       tabIndex: -1
-               },
-               config.plusButton,
-               {
-                       classes: [ 'oo-ui-numberInputWidget-plusButton' ],
-                       label: '+'
-               }
-       ) );
+       if ( config.showButtons ) {
+               this.minusButton = new OO.ui.ButtonWidget( $.extend(
+                       {
+                               disabled: this.isDisabled(),
+                               tabIndex: -1
+                       },
+                       config.minusButton,
+                       {
+                               classes: [ 'oo-ui-numberInputWidget-minusButton' ],
+                               label: '−'
+                       }
+               ) );
+               this.plusButton = new OO.ui.ButtonWidget( $.extend(
+                       {
+                               disabled: this.isDisabled(),
+                               tabIndex: -1
+                       },
+                       config.plusButton,
+                       {
+                               classes: [ 'oo-ui-numberInputWidget-plusButton' ],
+                               label: '+'
+                       }
+               ) );
+       }
 
        // Events
        this.input.connect( this, {
@@ -5101,12 +5105,14 @@ OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
                keydown: this.onKeyDown.bind( this ),
                'wheel mousewheel DOMMouseScroll': this.onWheel.bind( this )
        } );
-       this.plusButton.connect( this, {
-               click: [ 'onButtonClick', +1 ]
-       } );
-       this.minusButton.connect( this, {
-               click: [ 'onButtonClick', -1 ]
-       } );
+       if ( config.showButtons ) {
+               this.plusButton.connect( this, {
+                       click: [ 'onButtonClick', +1 ]
+               } );
+               this.minusButton.connect( this, {
+                       click: [ 'onButtonClick', -1 ]
+               } );
+       }
 
        // Initialization
        this.setIsInteger( !!config.isInteger );
@@ -5114,12 +5120,14 @@ OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
        this.setStep( config.step, config.pageStep );
 
        this.$field = $( '<div>' ).addClass( 'oo-ui-numberInputWidget-field' )
-               .append(
-                       this.minusButton.$element,
-                       this.input.$element,
-                       this.plusButton.$element
-               );
+               .append( this.input.$element );
        this.$element.addClass( 'oo-ui-numberInputWidget' ).append( this.$field );
+       if ( config.showButtons ) {
+               this.$field
+                       .prepend( this.minusButton.$element )
+                       .append( this.plusButton.$element );
+               this.$element.addClass( 'oo-ui-numberInputWidget-buttoned' );
+       }
        this.input.setValidation( this.validateNumber.bind( this ) );
 };
 
index 68659d3..dce6905 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-actionWidget.oo-ui-pendingElement-pending {
        background-image: /* @embed */ url(themes/apex/images/textures/pending.gif);
@@ -21,7 +21,7 @@
                box-sizing: border-box;
 }
 .oo-ui-window-content:focus {
-       outline: none;
+       outline: 0;
 }
 .oo-ui-window-head,
 .oo-ui-window-foot {
 .oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
        top: 1em;
        bottom: 1em;
+       max-height: 100%;
+       max-height: calc(100% - 2em);
        border: 1px solid #cccccc;
        border-radius: 0.5em;
        box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
index e1e5b51..747f8e9 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:53Z
+ * Date: 2016-04-07T15:12:44Z
  */
 .oo-ui-window {
        background: transparent;
@@ -17,7 +17,7 @@
                box-sizing: border-box;
 }
 .oo-ui-window-content:focus {
-       outline: none;
+       outline: 0;
 }
 .oo-ui-window-head,
 .oo-ui-window-foot {
 .oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
        top: 1em;
        bottom: 1em;
+       max-height: 100%;
+       max-height: calc(100% - 2em);
        border: 1px solid #aaaaaa;
        border-radius: 2px;
        box-shadow: 0 0.15em 0 0 rgba(0, 0, 0, 0.15);
index dbd50ed..9fd96f0 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.16.2
+ * OOjs UI v0.16.5
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2016 OOjs UI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2016-03-08T21:46:49Z
+ * Date: 2016-04-07T15:12:41Z
  */
 ( function ( OO ) {
 
@@ -2060,9 +2060,9 @@ OO.ui.Window.prototype.updateSize = function () {
  * @param {string|number} [dim.width] Width
  * @param {string|number} [dim.minWidth] Minimum width
  * @param {string|number} [dim.maxWidth] Maximum width
- * @param {string|number} [dim.width] Height, omit to set based on height of contents
- * @param {string|number} [dim.minWidth] Minimum height
- * @param {string|number} [dim.maxWidth] Maximum height
+ * @param {string|number} [dim.height] Height, omit to set based on height of contents
+ * @param {string|number} [dim.minHeight] Minimum height
+ * @param {string|number} [dim.maxHeight] Maximum height
  * @chainable
  */
 OO.ui.Window.prototype.setDimensions = function ( dim ) {
index c565256..394ec85 100644 (file)
@@ -2,6 +2,10 @@
        "prefix": "oo-ui-icon",
        "intro": "@import '../../../../src/styles/common';",
        "images": {
+               "articles": { "file": {
+                       "ltr": "images/icons/articles-ltr.svg",
+                       "rtl": "images/icons/articles-rtl.svg"
+               } },
                "articleRedirect": { "file": {
                        "ltr": "images/icons/articleRedirect-ltr.svg",
                        "rtl": "images/icons/articleRedirect-rtl.svg"
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.png
new file mode 100644 (file)
index 0000000..7dc6987
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.svg b/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.svg
new file mode 100644 (file)
index 0000000..9dd3404
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+    <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.png
new file mode 100644 (file)
index 0000000..9a7ce13
Binary files /dev/null and b/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.svg b/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.svg
new file mode 100644 (file)
index 0000000..b57dae2
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+    <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</svg>
index 0c5f6f9..c04573f 100644 (file)
                        "ltr": "images/icons/article-ltr.svg",
                        "rtl": "images/icons/article-rtl.svg"
                } },
+               "articles": { "file": {
+                       "ltr": "images/icons/articles-ltr.svg",
+                       "rtl": "images/icons/articles-rtl.svg"
+               } },
                "articleCheck": { "file": {
                        "ltr": "images/icons/articleCheck-ltr.svg",
                        "rtl": "images/icons/articleCheck-rtl.svg"
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.png
new file mode 100644 (file)
index 0000000..edfe406
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.svg
new file mode 100644 (file)
index 0000000..8397962
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+    <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+    <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.png
new file mode 100644 (file)
index 0000000..7dc6987
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.svg
new file mode 100644 (file)
index 0000000..9dd3404
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+    <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.png
new file mode 100644 (file)
index 0000000..153d534
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.svg
new file mode 100644 (file)
index 0000000..12432a2
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+    <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+    <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.png
new file mode 100644 (file)
index 0000000..9a7ce13
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.svg
new file mode 100644 (file)
index 0000000..b57dae2
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+    <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</svg>
index a146530..a35e9d1 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.png differ
index 072276b..b90f031 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
     <g id="close">
-        <path id="cross" d="M17.4 9.1c.8-.8.8-2 0-2.8L12 11.8 7.4 7.2 6 8.6l4.6 4.6-4 4c-.8.8-.8 2 0 2.8l5.4-5.4 4.6 4.6 1.4-1.4-4.6-4.6z"/>
+        <path id="cross" d="M17.4 8.1c.8-.8.8-2 0-2.8L12 10.8 7.4 6.2 6 7.6l4.6 4.6-4 4c-.8.8-.8 2 0 2.8l5.4-5.4 4.6 4.6 1.4-1.4-4.6-4.6z"/>
     </g>
 </svg>
index d768fc3..b6a42b8 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.png differ
index 1427670..c269316 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
     <g id="close">
-        <path id="cross" d="M17.4 9.1c.8-.8.8-2 0-2.8L12 11.8 7.4 7.2 6 8.6l4.6 4.6-4 4c-.8.8-.8 2 0 2.8l5.4-5.4 4.6 4.6 1.4-1.4-4.6-4.6z"/>
+        <path id="cross" d="M17.4 8.1c.8-.8.8-2 0-2.8L12 10.8 7.4 6.2 6 7.6l4.6 4.6-4 4c-.8.8-.8 2 0 2.8l5.4-5.4 4.6 4.6 1.4-1.4-4.6-4.6z"/>
     </g>
 </svg>
index f484f62..16462a2 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.png differ
index 19ddef6..34afc43 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
     <g id="close">
-        <path id="cross" d="M6.6 9.1c-.8-.8-.8-2 0-2.8l5.4 5.5 4.6-4.6L18 8.6l-4.6 4.6 4 4c.8.8.8 2 0 2.8L12 14.6l-4.6 4.6L6 17.8l4.6-4.6z"/>
+        <path id="cross" d="M6.6 8.1c-.8-.8-.8-2 0-2.8l5.4 5.5 4.6-4.6L18 7.6l-4.6 4.6 4 4c.8.8.8 2 0 2.8L12 13.6l-4.6 4.6L6 16.8l4.6-4.6z"/>
     </g>
 </svg>
index 504c534..e3e2417 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.png and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.png differ
index 6e0ca93..36e58ec 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
     <g id="close">
-        <path id="cross" d="M6.6 9.1c-.8-.8-.8-2 0-2.8l5.4 5.5 4.6-4.6L18 8.6l-4.6 4.6 4 4c.8.8.8 2 0 2.8L12 14.6l-4.6 4.6L6 17.8l4.6-4.6z"/>
+        <path id="cross" d="M6.6 8.1c-.8-.8-.8-2 0-2.8l5.4 5.5 4.6-4.6L18 7.6l-4.6 4.6 4 4c.8.8.8 2 0 2.8L12 13.6l-4.6 4.6L6 16.8l4.6-4.6z"/>
     </g>
 </svg>
index f1dcd4e..8c78b67 100644 (file)
@@ -1,27 +1,27 @@
 /*!
- * QUnit 1.18.0
- * http://qunitjs.com/
+ * QUnit 1.22.0
+ * https://qunitjs.com/
  *
  * Copyright jQuery Foundation and other contributors
  * Released under the MIT license
- * http://jquery.org/license
+ * https://jquery.org/license
  *
- * Date: 2015-04-03T10:23Z
+ * Date: 2016-02-23T15:57Z
  */
 
 /** Font Family and Sizes */
 
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
        font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
 }
 
-#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
 #qunit-tests { font-size: smaller; }
 
 
 /** Resets */
 
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
        margin: 0;
        padding: 0;
 }
        overflow: hidden;
 }
 
+#qunit-filteredTest {
+       padding: 0.5em 1em 0.5em 1em;
+       background-color: #F4FF77;
+       color: #366097;
+}
+
 #qunit-userAgent {
        padding: 0.5em 1em 0.5em 1em;
        background-color: #2B81AF;
        display: list-item;
 }
 
+#qunit-tests.hidepass {
+       position: relative;
+}
+
 #qunit-tests.hidepass li.running,
 #qunit-tests.hidepass li.pass {
        visibility: hidden;
        position: absolute;
-       width:   0px;
-       height:  0px;
+       width:   0;
+       height:  0;
        padding: 0;
        border:  0;
        margin:  0;
        border-radius: 5px;
 }
 
+.qunit-source {
+       margin: 0.6em 0 0.3em;
+}
+
 .qunit-collapsed {
        display: none;
 }
index f3542ca..84873ae 100644 (file)
 /*!
- * QUnit 1.18.0
- * http://qunitjs.com/
+ * QUnit 1.22.0
+ * https://qunitjs.com/
  *
  * Copyright jQuery Foundation and other contributors
  * Released under the MIT license
- * http://jquery.org/license
+ * https://jquery.org/license
  *
- * Date: 2015-04-03T10:23Z
+ * Date: 2016-02-23T15:57Z
  */
 
-(function( window ) {
+(function( global ) {
 
-var QUnit,
-       config,
-       onErrorFnPrev,
-       loggingCallbacks = {},
-       fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" ),
-       toString = Object.prototype.toString,
-       hasOwn = Object.prototype.hasOwnProperty,
-       // Keep a local reference to Date (GH-283)
-       Date = window.Date,
-       now = Date.now || function() {
-               return new Date().getTime();
-       },
-       globalStartCalled = false,
-       runStarted = false,
-       setTimeout = window.setTimeout,
-       clearTimeout = window.clearTimeout,
-       defined = {
-               document: window.document !== undefined,
-               setTimeout: window.setTimeout !== undefined,
-               sessionStorage: (function() {
-                       var x = "qunit-test-string";
-                       try {
-                               sessionStorage.setItem( x, x );
-                               sessionStorage.removeItem( x );
-                               return true;
-                       } catch ( e ) {
-                               return false;
+var QUnit = {};
+
+var Date = global.Date;
+var now = Date.now || function() {
+       return new Date().getTime();
+};
+
+var setTimeout = global.setTimeout;
+var clearTimeout = global.clearTimeout;
+
+// Store a local window from the global to allow direct references.
+var window = global.window;
+
+var defined = {
+       document: window && window.document !== undefined,
+       setTimeout: setTimeout !== undefined,
+       sessionStorage: (function() {
+               var x = "qunit-test-string";
+               try {
+                       sessionStorage.setItem( x, x );
+                       sessionStorage.removeItem( x );
+                       return true;
+               } catch ( e ) {
+                       return false;
+               }
+       }() )
+};
+
+var fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" );
+var globalStartCalled = false;
+var runStarted = false;
+
+var toString = Object.prototype.toString,
+       hasOwn = Object.prototype.hasOwnProperty;
+
+// returns a new Array with the elements that are in a but not in b
+function diff( a, b ) {
+       var i, j,
+               result = a.slice();
+
+       for ( i = 0; i < result.length; i++ ) {
+               for ( j = 0; j < b.length; j++ ) {
+                       if ( result[ i ] === b[ j ] ) {
+                               result.splice( i, 1 );
+                               i--;
+                               break;
                        }
-               }())
-       },
-       /**
-        * Provides a normalized error string, correcting an issue
-        * with IE 7 (and prior) where Error.prototype.toString is
-        * not properly implemented
-        *
-        * Based on http://es5.github.com/#x15.11.4.4
-        *
-        * @param {String|Error} error
-        * @return {String} error message
-        */
-       errorString = function( error ) {
-               var name, message,
-                       errorString = error.toString();
-               if ( errorString.substring( 0, 7 ) === "[object" ) {
-                       name = error.name ? error.name.toString() : "Error";
-                       message = error.message ? error.message.toString() : "";
-                       if ( name && message ) {
-                               return name + ": " + message;
-                       } else if ( name ) {
-                               return name;
-                       } else if ( message ) {
-                               return message;
+               }
+       }
+       return result;
+}
+
+// from jquery.js
+function inArray( elem, array ) {
+       if ( array.indexOf ) {
+               return array.indexOf( elem );
+       }
+
+       for ( var i = 0, length = array.length; i < length; i++ ) {
+               if ( array[ i ] === elem ) {
+                       return i;
+               }
+       }
+
+       return -1;
+}
+
+/**
+ * Makes a clone of an object using only Array or Object as base,
+ * and copies over the own enumerable properties.
+ *
+ * @param {Object} obj
+ * @return {Object} New object with only the own properties (recursively).
+ */
+function objectValues ( obj ) {
+       var key, val,
+               vals = QUnit.is( "array", obj ) ? [] : {};
+       for ( key in obj ) {
+               if ( hasOwn.call( obj, key ) ) {
+                       val = obj[ key ];
+                       vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
+               }
+       }
+       return vals;
+}
+
+function extend( a, b, undefOnly ) {
+       for ( var prop in b ) {
+               if ( hasOwn.call( b, prop ) ) {
+
+                       // Avoid "Member not found" error in IE8 caused by messing with window.constructor
+                       // This block runs on every environment, so `global` is being used instead of `window`
+                       // to avoid errors on node.
+                       if ( prop !== "constructor" || a !== global ) {
+                               if ( b[ prop ] === undefined ) {
+                                       delete a[ prop ];
+                               } else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) {
+                                       a[ prop ] = b[ prop ];
+                               }
+                       }
+               }
+       }
+
+       return a;
+}
+
+function objectType( obj ) {
+       if ( typeof obj === "undefined" ) {
+               return "undefined";
+       }
+
+       // Consider: typeof null === object
+       if ( obj === null ) {
+               return "null";
+       }
+
+       var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ),
+               type = match && match[ 1 ];
+
+       switch ( type ) {
+               case "Number":
+                       if ( isNaN( obj ) ) {
+                               return "nan";
+                       }
+                       return "number";
+               case "String":
+               case "Boolean":
+               case "Array":
+               case "Set":
+               case "Map":
+               case "Date":
+               case "RegExp":
+               case "Function":
+               case "Symbol":
+                       return type.toLowerCase();
+       }
+       if ( typeof obj === "object" ) {
+               return "object";
+       }
+}
+
+// Safe object type checking
+function is( type, obj ) {
+       return QUnit.objectType( obj ) === type;
+}
+
+var getUrlParams = function() {
+       var i, param, name, value;
+       var urlParams = {};
+       var location = window.location;
+       var params = location.search.slice( 1 ).split( "&" );
+       var length = params.length;
+
+       for ( i = 0; i < length; i++ ) {
+               if ( params[ i ] ) {
+                       param = params[ i ].split( "=" );
+                       name = decodeURIComponent( param[ 0 ] );
+
+                       // allow just a key to turn on a flag, e.g., test.html?noglobals
+                       value = param.length === 1 ||
+                               decodeURIComponent( param.slice( 1 ).join( "=" ) ) ;
+                       if ( urlParams[ name ] ) {
+                               urlParams[ name ] = [].concat( urlParams[ name ], value );
                        } else {
-                               return "Error";
+                               urlParams[ name ] = value;
                        }
-               } else {
-                       return errorString;
                }
-       },
-       /**
-        * Makes a clone of an object using only Array or Object as base,
-        * and copies over the own enumerable properties.
-        *
-        * @param {Object} obj
-        * @return {Object} New object with only the own properties (recursively).
-        */
-       objectValues = function( obj ) {
-               var key, val,
-                       vals = QUnit.is( "array", obj ) ? [] : {};
-               for ( key in obj ) {
-                       if ( hasOwn.call( obj, key ) ) {
-                               val = obj[ key ];
-                               vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
+       }
+
+       return urlParams;
+};
+
+// Doesn't support IE6 to IE9, it will return undefined on these browsers
+// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
+function extractStacktrace( e, offset ) {
+       offset = offset === undefined ? 4 : offset;
+
+       var stack, include, i;
+
+       if ( e.stack ) {
+               stack = e.stack.split( "\n" );
+               if ( /^error$/i.test( stack[ 0 ] ) ) {
+                       stack.shift();
+               }
+               if ( fileName ) {
+                       include = [];
+                       for ( i = offset; i < stack.length; i++ ) {
+                               if ( stack[ i ].indexOf( fileName ) !== -1 ) {
+                                       break;
+                               }
+                               include.push( stack[ i ] );
+                       }
+                       if ( include.length ) {
+                               return include.join( "\n" );
                        }
                }
-               return vals;
-       };
+               return stack[ offset ];
+
+       // Support: Safari <=6 only
+       } else if ( e.sourceURL ) {
+
+               // exclude useless self-reference for generated Error objects
+               if ( /qunit.js$/.test( e.sourceURL ) ) {
+                       return;
+               }
+
+               // for actual exceptions, this is useful
+               return e.sourceURL + ":" + e.line;
+       }
+}
+
+function sourceFromStacktrace( offset ) {
+       var error = new Error();
+
+       // Support: Safari <=7 only, IE <=10 - 11 only
+       // Not all browsers generate the `stack` property for `new Error()`, see also #636
+       if ( !error.stack ) {
+               try {
+                       throw error;
+               } catch ( err ) {
+                       error = err;
+               }
+       }
 
-QUnit = {};
+       return extractStacktrace( error, offset );
+}
 
 /**
  * Config object: Maintain internal state
  * Later exposed as QUnit.config
  * `config` initialized at top of scope
  */
-config = {
+var config = {
        // The queue of tests to run
        queue: [],
 
@@ -110,15 +257,19 @@ config = {
        // by default, modify document.title when suite is done
        altertitle: true,
 
+       // HTML Reporter: collapse every test except the first failing test
+       // If false, all failing tests will be expanded
+       collapse: true,
+
        // by default, scroll to top of the page when suite is done
        scrolltop: true,
 
-       // when enabled, all tests must call expect()
-       requireExpects: false,
-
        // depth up-to which object will be dumped
        maxDepth: 5,
 
+       // when enabled, all tests must call expect()
+       requireExpects: false,
+
        // add checkboxes that are persisted in the query-string
        // when enabled, the id is set to `true` as a `QUnit.config` property
        urlConfig: [
@@ -131,7 +282,7 @@ config = {
                        id: "noglobals",
                        label: "Check for Globals",
                        tooltip: "Enabling this will test if any test introduces new properties on the " +
-                               "`window` object. Stored as query-strings."
+                               "global object (`window` in Browsers). Stored as query-strings."
                },
                {
                        id: "notrycatch",
@@ -144,6 +295,9 @@ config = {
        // Set of all modules.
        modules: [],
 
+       // Stack of nested modules
+       moduleStack: [],
+
        // The first unnamed module
        currentModule: {
                name: "",
@@ -153,75 +307,162 @@ config = {
        callbacks: {}
 };
 
+var urlParams = defined.document ? getUrlParams() : {};
+
 // Push a loose unnamed module to the modules collection
 config.modules.push( config.currentModule );
 
-// Initialize more QUnit.config and QUnit.urlParams
-(function() {
-       var i, current,
-               location = window.location || { search: "", protocol: "file:" },
-               params = location.search.slice( 1 ).split( "&" ),
-               length = params.length,
-               urlParams = {};
+if ( urlParams.filter === true ) {
+       delete urlParams.filter;
+}
 
-       if ( params[ 0 ] ) {
-               for ( i = 0; i < length; i++ ) {
-                       current = params[ i ].split( "=" );
-                       current[ 0 ] = decodeURIComponent( current[ 0 ] );
+// String search anywhere in moduleName+testName
+config.filter = urlParams.filter;
 
-                       // allow just a key to turn on a flag, e.g., test.html?noglobals
-                       current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
-                       if ( urlParams[ current[ 0 ] ] ) {
-                               urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] );
-                       } else {
-                               urlParams[ current[ 0 ] ] = current[ 1 ];
+config.testId = [];
+if ( urlParams.testId ) {
+       // Ensure that urlParams.testId is an array
+       urlParams.testId = decodeURIComponent( urlParams.testId ).split( "," );
+       for (var i = 0; i < urlParams.testId.length; i++ ) {
+               config.testId.push( urlParams.testId[ i ] );
+       }
+}
+
+var loggingCallbacks = {};
+
+// Register logging callbacks
+function registerLoggingCallbacks( obj ) {
+       var i, l, key,
+               callbackNames = [ "begin", "done", "log", "testStart", "testDone",
+                       "moduleStart", "moduleDone" ];
+
+       function registerLoggingCallback( key ) {
+               var loggingCallback = function( callback ) {
+                       if ( objectType( callback ) !== "function" ) {
+                               throw new Error(
+                                       "QUnit logging methods require a callback function as their first parameters."
+                               );
                        }
+
+                       config.callbacks[ key ].push( callback );
+               };
+
+               // DEPRECATED: This will be removed on QUnit 2.0.0+
+               // Stores the registered functions allowing restoring
+               // at verifyLoggingCallbacks() if modified
+               loggingCallbacks[ key ] = loggingCallback;
+
+               return loggingCallback;
+       }
+
+       for ( i = 0, l = callbackNames.length; i < l; i++ ) {
+               key = callbackNames[ i ];
+
+               // Initialize key collection of logging callback
+               if ( objectType( config.callbacks[ key ] ) === "undefined" ) {
+                       config.callbacks[ key ] = [];
                }
+
+               obj[ key ] = registerLoggingCallback( key );
        }
+}
+
+function runLoggingCallbacks( key, args ) {
+       var i, l, callbacks;
 
-       if ( urlParams.filter === true ) {
-               delete urlParams.filter;
+       callbacks = config.callbacks[ key ];
+       for ( i = 0, l = callbacks.length; i < l; i++ ) {
+               callbacks[ i ]( args );
        }
+}
+
+// DEPRECATED: This will be removed on 2.0.0+
+// This function verifies if the loggingCallbacks were modified by the user
+// If so, it will restore it, assign the given callback and print a console warning
+function verifyLoggingCallbacks() {
+       var loggingCallback, userCallback;
 
-       QUnit.urlParams = urlParams;
+       for ( loggingCallback in loggingCallbacks ) {
+               if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {
 
-       // String search anywhere in moduleName+testName
-       config.filter = urlParams.filter;
+                       userCallback = QUnit[ loggingCallback ];
 
-       if ( urlParams.maxDepth ) {
-               config.maxDepth = parseInt( urlParams.maxDepth, 10 ) === -1 ?
-                       Number.POSITIVE_INFINITY :
-                       urlParams.maxDepth;
-       }
+                       // Restore the callback function
+                       QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];
 
-       config.testId = [];
-       if ( urlParams.testId ) {
+                       // Assign the deprecated given callback
+                       QUnit[ loggingCallback ]( userCallback );
 
-               // Ensure that urlParams.testId is an array
-               urlParams.testId = decodeURIComponent( urlParams.testId ).split( "," );
-               for ( i = 0; i < urlParams.testId.length; i++ ) {
-                       config.testId.push( urlParams.testId[ i ] );
+                       if ( global.console && global.console.warn ) {
+                               global.console.warn(
+                                       "QUnit." + loggingCallback + " was replaced with a new value.\n" +
+                                       "Please, check out the documentation on how to apply logging callbacks.\n" +
+                                       "Reference: https://api.qunitjs.com/category/callbacks/"
+                               );
+                       }
                }
        }
+}
 
-       // Figure out if we're running the tests from a server or not
-       QUnit.isLocal = location.protocol === "file:";
+( function() {
+       if ( !defined.document ) {
+               return;
+       }
 
-       // Expose the current QUnit version
-       QUnit.version = "1.18.0";
-}());
+       // `onErrorFnPrev` initialized at top of scope
+       // Preserve other handlers
+       var onErrorFnPrev = window.onerror;
+
+       // Cover uncaught exceptions
+       // Returning true will suppress the default browser handler,
+       // returning false will let it run.
+       window.onerror = function( error, filePath, linerNr ) {
+               var ret = false;
+               if ( onErrorFnPrev ) {
+                       ret = onErrorFnPrev( error, filePath, linerNr );
+               }
+
+               // Treat return value as window.onerror itself does,
+               // Only do our handling if not suppressed.
+               if ( ret !== true ) {
+                       if ( QUnit.config.current ) {
+                               if ( QUnit.config.current.ignoreGlobalErrors ) {
+                                       return true;
+                               }
+                               QUnit.pushFailure( error, filePath + ":" + linerNr );
+                       } else {
+                               QUnit.test( "global failure", extend(function() {
+                                       QUnit.pushFailure( error, filePath + ":" + linerNr );
+                               }, { validTest: true } ) );
+                       }
+                       return false;
+               }
+
+               return ret;
+       };
+} )();
+
+QUnit.urlParams = urlParams;
+
+// Figure out if we're running the tests from a server or not
+QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" );
+
+// Expose the current QUnit version
+QUnit.version = "1.22.0";
 
-// Root QUnit object.
-// `QUnit` initialized at top of scope
 extend( QUnit, {
 
        // call on start of module test to prepend name to all tests
-       module: function( name, testEnvironment ) {
-               var currentModule = {
-                       name: name,
-                       testEnvironment: testEnvironment,
-                       tests: []
-               };
+       module: function( name, testEnvironment, executeNow ) {
+               var module, moduleFns;
+               var currentModule = config.currentModule;
+
+               if ( arguments.length === 2 ) {
+                       if ( testEnvironment instanceof Function ) {
+                               executeNow = testEnvironment;
+                               testEnvironment = undefined;
+                       }
+               }
 
                // DEPRECATED: handles setup/teardown functions,
                // beforeEach and afterEach should be used instead
@@ -234,46 +475,61 @@ extend( QUnit, {
                        delete testEnvironment.teardown;
                }
 
-               config.modules.push( currentModule );
-               config.currentModule = currentModule;
-       },
+               module = createModule();
 
-       // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
-       asyncTest: function( testName, expected, callback ) {
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
-               }
+               moduleFns = {
+                       beforeEach: setHook( module, "beforeEach" ),
+                       afterEach: setHook( module, "afterEach" )
+               };
 
-               QUnit.test( testName, expected, callback, true );
-       },
+               if ( executeNow instanceof Function ) {
+                       config.moduleStack.push( module );
+                       setCurrentModule( module );
+                       executeNow.call( module.testEnvironment, moduleFns );
+                       config.moduleStack.pop();
+                       module = module.parentModule || currentModule;
+               }
+
+               setCurrentModule( module );
+
+               function createModule() {
+                       var parentModule = config.moduleStack.length ?
+                               config.moduleStack.slice( -1 )[ 0 ] : null;
+                       var moduleName = parentModule !== null ?
+                               [ parentModule.name, name ].join( " > " ) : name;
+                       var module = {
+                               name: moduleName,
+                               parentModule: parentModule,
+                               tests: []
+                       };
 
-       test: function( testName, expected, callback, async ) {
-               var test;
+                       var env = {};
+                       if ( parentModule ) {
+                               extend( env, parentModule.testEnvironment );
+                               delete env.beforeEach;
+                               delete env.afterEach;
+                       }
+                       extend( env, testEnvironment );
+                       module.testEnvironment = env;
 
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
+                       config.modules.push( module );
+                       return module;
                }
 
-               test = new Test({
-                       testName: testName,
-                       expected: expected,
-                       async: async,
-                       callback: callback
-               });
+               function setCurrentModule( module ) {
+                       config.currentModule = module;
+               }
 
-               test.queue();
        },
 
-       skip: function( testName ) {
-               var test = new Test({
-                       testName: testName,
-                       skip: true
-               });
+       // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
+       asyncTest: asyncTest,
 
-               test.queue();
-       },
+       test: test,
+
+       skip: skip,
+
+       only: only,
 
        // DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0.
        // In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior.
@@ -301,6 +557,17 @@ extend( QUnit, {
                        // If a test is running, adjust its semaphore
                        config.current.semaphore -= count || 1;
 
+                       // If semaphore is non-numeric, throw error
+                       if ( isNaN( config.current.semaphore ) ) {
+                               config.current.semaphore = 0;
+
+                               QUnit.pushFailure(
+                                       "Called start() with a non-numeric decrement.",
+                                       sourceFromStacktrace( 2 )
+                               );
+                               return;
+                       }
+
                        // Don't start until equal number of stop-calls
                        if ( config.current.semaphore > 0 ) {
                                return;
@@ -337,43 +604,9 @@ extend( QUnit, {
 
        config: config,
 
-       // Safe object type checking
-       is: function( type, obj ) {
-               return QUnit.objectType( obj ) === type;
-       },
-
-       objectType: function( obj ) {
-               if ( typeof obj === "undefined" ) {
-                       return "undefined";
-               }
-
-               // Consider: typeof null === object
-               if ( obj === null ) {
-                       return "null";
-               }
-
-               var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ),
-                       type = match && match[ 1 ] || "";
+       is: is,
 
-               switch ( type ) {
-                       case "Number":
-                               if ( isNaN( obj ) ) {
-                                       return "nan";
-                               }
-                               return "number";
-                       case "String":
-                       case "Boolean":
-                       case "Array":
-                       case "Date":
-                       case "RegExp":
-                       case "Function":
-                               return type.toLowerCase();
-               }
-               if ( typeof obj === "object" ) {
-                       return "object";
-               }
-               return undefined;
-       },
+       objectType: objectType,
 
        extend: extend,
 
@@ -395,174 +628,50 @@ extend( QUnit, {
                if ( config.autostart ) {
                        resumeProcessing();
                }
+       },
+
+       stack: function( offset ) {
+               offset = ( offset || 0 ) + 2;
+               return sourceFromStacktrace( offset );
        }
 });
 
-// Register logging callbacks
-(function() {
-       var i, l, key,
-               callbacks = [ "begin", "done", "log", "testStart", "testDone",
-                       "moduleStart", "moduleDone" ];
-
-       function registerLoggingCallback( key ) {
-               var loggingCallback = function( callback ) {
-                       if ( QUnit.objectType( callback ) !== "function" ) {
-                               throw new Error(
-                                       "QUnit logging methods require a callback function as their first parameters."
-                               );
-                       }
+registerLoggingCallbacks( QUnit );
 
-                       config.callbacks[ key ].push( callback );
-               };
+function begin() {
+       var i, l,
+               modulesLog = [];
 
-               // DEPRECATED: This will be removed on QUnit 2.0.0+
-               // Stores the registered functions allowing restoring
-               // at verifyLoggingCallbacks() if modified
-               loggingCallbacks[ key ] = loggingCallback;
+       // If the test run hasn't officially begun yet
+       if ( !config.started ) {
 
-               return loggingCallback;
-       }
+               // Record the time of the test run's beginning
+               config.started = now();
 
-       for ( i = 0, l = callbacks.length; i < l; i++ ) {
-               key = callbacks[ i ];
+               verifyLoggingCallbacks();
 
-               // Initialize key collection of logging callback
-               if ( QUnit.objectType( config.callbacks[ key ] ) === "undefined" ) {
-                       config.callbacks[ key ] = [];
+               // Delete the loose unnamed module if unused.
+               if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) {
+                       config.modules.shift();
                }
 
-               QUnit[ key ] = registerLoggingCallback( key );
-       }
-})();
-
-// `onErrorFnPrev` initialized at top of scope
-// Preserve other handlers
-onErrorFnPrev = window.onerror;
-
-// Cover uncaught exceptions
-// Returning true will suppress the default browser handler,
-// returning false will let it run.
-window.onerror = function( error, filePath, linerNr ) {
-       var ret = false;
-       if ( onErrorFnPrev ) {
-               ret = onErrorFnPrev( error, filePath, linerNr );
-       }
-
-       // Treat return value as window.onerror itself does,
-       // Only do our handling if not suppressed.
-       if ( ret !== true ) {
-               if ( QUnit.config.current ) {
-                       if ( QUnit.config.current.ignoreGlobalErrors ) {
-                               return true;
-                       }
-                       QUnit.pushFailure( error, filePath + ":" + linerNr );
-               } else {
-                       QUnit.test( "global failure", extend(function() {
-                               QUnit.pushFailure( error, filePath + ":" + linerNr );
-                       }, { validTest: true } ) );
+               // Avoid unnecessary information by not logging modules' test environments
+               for ( i = 0, l = config.modules.length; i < l; i++ ) {
+                       modulesLog.push({
+                               name: config.modules[ i ].name,
+                               tests: config.modules[ i ].tests
+                       });
                }
-               return false;
-       }
-
-       return ret;
-};
-
-function done() {
-       var runtime, passed;
-
-       config.autorun = true;
 
-       // Log the last module results
-       if ( config.previousModule ) {
-               runLoggingCallbacks( "moduleDone", {
-                       name: config.previousModule.name,
-                       tests: config.previousModule.tests,
-                       failed: config.moduleStats.bad,
-                       passed: config.moduleStats.all - config.moduleStats.bad,
-                       total: config.moduleStats.all,
-                       runtime: now() - config.moduleStats.started
+               // The test run is officially beginning now
+               runLoggingCallbacks( "begin", {
+                       totalTests: Test.count,
+                       modules: modulesLog
                });
        }
-       delete config.previousModule;
-
-       runtime = now() - config.started;
-       passed = config.stats.all - config.stats.bad;
-
-       runLoggingCallbacks( "done", {
-               failed: config.stats.bad,
-               passed: passed,
-               total: config.stats.all,
-               runtime: runtime
-       });
-}
-
-// Doesn't support IE6 to IE9, it will return undefined on these browsers
-// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
-function extractStacktrace( e, offset ) {
-       offset = offset === undefined ? 4 : offset;
-
-       var stack, include, i;
-
-       if ( e.stack ) {
-               stack = e.stack.split( "\n" );
-               if ( /^error$/i.test( stack[ 0 ] ) ) {
-                       stack.shift();
-               }
-               if ( fileName ) {
-                       include = [];
-                       for ( i = offset; i < stack.length; i++ ) {
-                               if ( stack[ i ].indexOf( fileName ) !== -1 ) {
-                                       break;
-                               }
-                               include.push( stack[ i ] );
-                       }
-                       if ( include.length ) {
-                               return include.join( "\n" );
-                       }
-               }
-               return stack[ offset ];
-
-       // Support: Safari <=6 only
-       } else if ( e.sourceURL ) {
-
-               // exclude useless self-reference for generated Error objects
-               if ( /qunit.js$/.test( e.sourceURL ) ) {
-                       return;
-               }
-
-               // for actual exceptions, this is useful
-               return e.sourceURL + ":" + e.line;
-       }
-}
-
-function sourceFromStacktrace( offset ) {
-       var error = new Error();
-
-       // Support: Safari <=7 only, IE <=10 - 11 only
-       // Not all browsers generate the `stack` property for `new Error()`, see also #636
-       if ( !error.stack ) {
-               try {
-                       throw error;
-               } catch ( err ) {
-                       error = err;
-               }
-       }
-
-       return extractStacktrace( error, offset );
-}
-
-function synchronize( callback, last ) {
-       if ( QUnit.objectType( callback ) === "array" ) {
-               while ( callback.length ) {
-                       synchronize( callback.shift() );
-               }
-               return;
-       }
-       config.queue.push( callback );
 
-       if ( config.autorun && !config.blocking ) {
-               process( last );
-       }
+       config.blocking = false;
+       process( true );
 }
 
 function process( last ) {
@@ -592,40 +701,21 @@ function process( last ) {
        }
 }
 
-function begin() {
-       var i, l,
-               modulesLog = [];
-
-       // If the test run hasn't officially begun yet
-       if ( !config.started ) {
-
-               // Record the time of the test run's beginning
-               config.started = now();
-
-               verifyLoggingCallbacks();
-
-               // Delete the loose unnamed module if unused.
-               if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) {
-                       config.modules.shift();
-               }
-
-               // Avoid unnecessary information by not logging modules' test environments
-               for ( i = 0, l = config.modules.length; i < l; i++ ) {
-                       modulesLog.push({
-                               name: config.modules[ i ].name,
-                               tests: config.modules[ i ].tests
-                       });
-               }
+function pauseProcessing() {
+       config.blocking = true;
 
-               // The test run is officially beginning now
-               runLoggingCallbacks( "begin", {
-                       totalTests: Test.count,
-                       modules: modulesLog
-               });
+       if ( config.testTimeout && defined.setTimeout ) {
+               clearTimeout( config.timeout );
+               config.timeout = setTimeout(function() {
+                       if ( config.current ) {
+                               config.current.semaphore = 0;
+                               QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
+                       } else {
+                               throw new Error( "Test timed out" );
+                       }
+                       resumeProcessing();
+               }, config.testTimeout );
        }
-
-       config.blocking = false;
-       process( true );
 }
 
 function resumeProcessing() {
@@ -648,143 +738,47 @@ function resumeProcessing() {
        }
 }
 
-function pauseProcessing() {
-       config.blocking = true;
-
-       if ( config.testTimeout && defined.setTimeout ) {
-               clearTimeout( config.timeout );
-               config.timeout = setTimeout(function() {
-                       if ( config.current ) {
-                               config.current.semaphore = 0;
-                               QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
-                       } else {
-                               throw new Error( "Test timed out" );
-                       }
-                       resumeProcessing();
-               }, config.testTimeout );
-       }
-}
+function done() {
+       var runtime, passed;
 
-function saveGlobal() {
-       config.pollution = [];
+       config.autorun = true;
 
-       if ( config.noglobals ) {
-               for ( var key in window ) {
-                       if ( hasOwn.call( window, key ) ) {
-                               // in Opera sometimes DOM element ids show up here, ignore them
-                               if ( /^qunit-test-output/.test( key ) ) {
-                                       continue;
-                               }
-                               config.pollution.push( key );
-                       }
-               }
-       }
-}
-
-function checkPollution() {
-       var newGlobals,
-               deletedGlobals,
-               old = config.pollution;
-
-       saveGlobal();
-
-       newGlobals = diff( config.pollution, old );
-       if ( newGlobals.length > 0 ) {
-               QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) );
-       }
-
-       deletedGlobals = diff( old, config.pollution );
-       if ( deletedGlobals.length > 0 ) {
-               QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) );
-       }
-}
-
-// returns a new Array with the elements that are in a but not in b
-function diff( a, b ) {
-       var i, j,
-               result = a.slice();
-
-       for ( i = 0; i < result.length; i++ ) {
-               for ( j = 0; j < b.length; j++ ) {
-                       if ( result[ i ] === b[ j ] ) {
-                               result.splice( i, 1 );
-                               i--;
-                               break;
-                       }
-               }
+       // Log the last module results
+       if ( config.previousModule ) {
+               runLoggingCallbacks( "moduleDone", {
+                       name: config.previousModule.name,
+                       tests: config.previousModule.tests,
+                       failed: config.moduleStats.bad,
+                       passed: config.moduleStats.all - config.moduleStats.bad,
+                       total: config.moduleStats.all,
+                       runtime: now() - config.moduleStats.started
+               });
        }
-       return result;
-}
-
-function extend( a, b, undefOnly ) {
-       for ( var prop in b ) {
-               if ( hasOwn.call( b, prop ) ) {
+       delete config.previousModule;
 
-                       // Avoid "Member not found" error in IE8 caused by messing with window.constructor
-                       if ( !( prop === "constructor" && a === window ) ) {
-                               if ( b[ prop ] === undefined ) {
-                                       delete a[ prop ];
-                               } else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) {
-                                       a[ prop ] = b[ prop ];
-                               }
-                       }
-               }
-       }
+       runtime = now() - config.started;
+       passed = config.stats.all - config.stats.bad;
 
-       return a;
+       runLoggingCallbacks( "done", {
+               failed: config.stats.bad,
+               passed: passed,
+               total: config.stats.all,
+               runtime: runtime
+       });
 }
 
-function runLoggingCallbacks( key, args ) {
-       var i, l, callbacks;
-
-       callbacks = config.callbacks[ key ];
-       for ( i = 0, l = callbacks.length; i < l; i++ ) {
-               callbacks[ i ]( args );
+function setHook( module, hookName ) {
+       if ( module.testEnvironment === undefined ) {
+               module.testEnvironment = {};
        }
-}
-
-// DEPRECATED: This will be removed on 2.0.0+
-// This function verifies if the loggingCallbacks were modified by the user
-// If so, it will restore it, assign the given callback and print a console warning
-function verifyLoggingCallbacks() {
-       var loggingCallback, userCallback;
-
-       for ( loggingCallback in loggingCallbacks ) {
-               if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {
-
-                       userCallback = QUnit[ loggingCallback ];
-
-                       // Restore the callback function
-                       QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];
 
-                       // Assign the deprecated given callback
-                       QUnit[ loggingCallback ]( userCallback );
-
-                       if ( window.console && window.console.warn ) {
-                               window.console.warn(
-                                       "QUnit." + loggingCallback + " was replaced with a new value.\n" +
-                                       "Please, check out the documentation on how to apply logging callbacks.\n" +
-                                       "Reference: http://api.qunitjs.com/category/callbacks/"
-                               );
-                       }
-               }
-       }
+       return function( callback ) {
+               module.testEnvironment[ hookName ] = callback;
+       };
 }
 
-// from jquery.js
-function inArray( elem, array ) {
-       if ( array.indexOf ) {
-               return array.indexOf( elem );
-       }
-
-       for ( var i = 0, length = array.length; i < length; i++ ) {
-               if ( array[ i ] === elem ) {
-                       return i;
-               }
-       }
-
-       return -1;
-}
+var focused = false;
+var priorityCount = 0;
 
 function Test( settings ) {
        var i, l;
@@ -858,9 +852,11 @@ Test.prototype = {
 
                config.current = this;
 
+               if ( this.module.testEnvironment ) {
+                       delete this.module.testEnvironment.beforeEach;
+                       delete this.module.testEnvironment.afterEach;
+               }
                this.testEnvironment = extend( {}, this.module.testEnvironment );
-               delete this.testEnvironment.beforeEach;
-               delete this.testEnvironment.afterEach;
 
                this.started = now();
                runLoggingCallbacks( "testStart", {
@@ -886,14 +882,12 @@ Test.prototype = {
                this.callbackStarted = now();
 
                if ( config.notrycatch ) {
-                       promise = this.callback.call( this.testEnvironment, this.assert );
-                       this.resolvePromise( promise );
+                       runTest( this );
                        return;
                }
 
                try {
-                       promise = this.callback.call( this.testEnvironment, this.assert );
-                       this.resolvePromise( promise );
+                       runTest( this );
                } catch ( e ) {
                        this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " +
                                this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
@@ -906,6 +900,11 @@ Test.prototype = {
                                QUnit.start();
                        }
                }
+
+               function runTest( test ) {
+                       promise = test.callback.call( test.testEnvironment, test.assert );
+                       test.resolvePromise( promise );
+               }
        },
 
        after: function() {
@@ -918,16 +917,19 @@ Test.prototype = {
                return function runHook() {
                        config.current = test;
                        if ( config.notrycatch ) {
-                               promise = hook.call( test.testEnvironment, test.assert );
-                               test.resolvePromise( promise, hookName );
+                               callHook();
                                return;
                        }
                        try {
-                               promise = hook.call( test.testEnvironment, test.assert );
-                               test.resolvePromise( promise, hookName );
+                               callHook();
                        } catch ( error ) {
                                test.pushFailure( hookName + " failed on " + test.testName + ": " +
-                                       ( error.message || error ), extractStacktrace( error, 0 ) );
+                               ( error.message || error ), extractStacktrace( error, 0 ) );
+                       }
+
+                       function callHook() {
+                               promise = hook.call( test.testEnvironment, test.assert );
+                               test.resolvePromise( promise, hookName );
                        }
                };
        },
@@ -936,16 +938,20 @@ Test.prototype = {
        hooks: function( handler ) {
                var hooks = [];
 
-               // Hooks are ignored on skipped tests
-               if ( this.skip ) {
-                       return hooks;
+               function processHooks( test, module ) {
+                       if ( module.parentModule ) {
+                               processHooks( test, module.parentModule );
+                       }
+                       if ( module.testEnvironment &&
+                               QUnit.objectType( module.testEnvironment[ handler ] ) === "function" ) {
+                               hooks.push( test.queueHook( module.testEnvironment[ handler ], handler ) );
+                       }
                }
 
-               if ( this.module.testEnvironment &&
-                               QUnit.objectType( this.module.testEnvironment[ handler ] ) === "function" ) {
-                       hooks.push( this.queueHook( this.module.testEnvironment[ handler ], handler ) );
+               // Hooks are ignored on skipped tests
+               if ( !this.skip ) {
+                       processHooks( this, this.module );
                }
-
                return hooks;
        },
 
@@ -990,6 +996,9 @@ Test.prototype = {
                        assertions: this.assertions,
                        testId: this.testId,
 
+                       // Source of Test
+                       source: this.stack,
+
                        // DEPRECATED: this property will be removed in 2.0.0, use runtime instead
                        duration: this.runtime
                });
@@ -1003,7 +1012,7 @@ Test.prototype = {
        },
 
        queue: function() {
-               var bad,
+               var priority,
                        test = this;
 
                if ( !this.valid() ) {
@@ -1019,7 +1028,6 @@ Test.prototype = {
                                },
 
                                test.hooks( "beforeEach" ),
-
                                function() {
                                        test.run();
                                },
@@ -1035,32 +1043,30 @@ Test.prototype = {
                        ]);
                }
 
-               // `bad` initialized at top of scope
-               // defer when previous test run passed, if storage is available
-               bad = QUnit.config.reorder && defined.sessionStorage &&
+               // Prioritize previously failed tests, detected from sessionStorage
+               priority = QUnit.config.reorder && defined.sessionStorage &&
                                +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );
 
-               if ( bad ) {
-                       run();
-               } else {
-                       synchronize( run, true );
-               }
+               return synchronize( run, priority );
        },
 
-       push: function( result, actual, expected, message ) {
+       pushResult: function( resultInfo ) {
+
+               // resultInfo = { result, actual, expected, message, negative }
                var source,
                        details = {
                                module: this.module.name,
                                name: this.testName,
-                               result: result,
-                               message: message,
-                               actual: actual,
-                               expected: expected,
+                               result: resultInfo.result,
+                               message: resultInfo.message,
+                               actual: resultInfo.actual,
+                               expected: resultInfo.expected,
                                testId: this.testId,
+                               negative: resultInfo.negative || false,
                                runtime: now() - this.started
                        };
 
-               if ( !result ) {
+               if ( !resultInfo.result ) {
                        source = sourceFromStacktrace();
 
                        if ( source ) {
@@ -1071,13 +1077,13 @@ Test.prototype = {
                runLoggingCallbacks( "log", details );
 
                this.assertions.push({
-                       result: !!result,
-                       message: message
+                       result: !!resultInfo.result,
+                       message: resultInfo.message
                });
        },
 
        pushFailure: function( message, source, actual ) {
-               if ( !this instanceof Test ) {
+               if ( !( this instanceof Test ) ) {
                        throw new Error( "pushFailure() assertion outside test context, was " +
                                sourceFromStacktrace( 2 ) );
                }
@@ -1113,7 +1119,7 @@ Test.prototype = {
                                QUnit.stop();
                                then.call(
                                        promise,
-                                       QUnit.start,
+                                       function() { QUnit.start(); },
                                        function( error ) {
                                                message = "Promise rejected " +
                                                        ( !phase ? "during" : phase.replace( /Each$/, "" ) ) +
@@ -1132,10 +1138,21 @@ Test.prototype = {
        },
 
        valid: function() {
-               var include,
-                       filter = config.filter && config.filter.toLowerCase(),
+               var filter = config.filter,
+                       regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec( filter ),
                        module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(),
-                       fullName = ( this.module.name + ": " + this.testName ).toLowerCase();
+                       fullName = ( this.module.name + ": " + this.testName );
+
+               function testInModuleChain( testModule ) {
+                       var testModuleName = testModule.name ? testModule.name.toLowerCase() : null;
+                       if ( testModuleName === module ) {
+                               return true;
+                       } else if ( testModule.parentModule ) {
+                               return testInModuleChain( testModule.parentModule );
+                       } else {
+                               return false;
+                       }
+               }
 
                // Internally-generated tests are always valid
                if ( this.callback && this.callback.validTest ) {
@@ -1146,7 +1163,7 @@ Test.prototype = {
                        return false;
                }
 
-               if ( module && ( !this.module.name || this.module.name.toLowerCase() !== module ) ) {
+               if ( module && !testInModuleChain( this.module ) ) {
                        return false;
                }
 
@@ -1154,7 +1171,23 @@ Test.prototype = {
                        return true;
                }
 
-               include = filter.charAt( 0 ) !== "!";
+               return regexFilter ?
+                       this.regexFilter( !!regexFilter[1], regexFilter[2], regexFilter[3], fullName ) :
+                       this.stringFilter( filter, fullName );
+       },
+
+       regexFilter: function( exclude, pattern, flags, fullName ) {
+               var regex = new RegExp( pattern, flags );
+               var match = regex.test( fullName );
+
+               return match !== exclude;
+       },
+
+       stringFilter: function( filter, fullName ) {
+               filter = filter.toLowerCase();
+               fullName = fullName.toLowerCase();
+
+               var include = filter.charAt( 0 ) !== "!";
                if ( !include ) {
                        filter = filter.slice( 1 );
                }
@@ -1167,7 +1200,6 @@ Test.prototype = {
                // Otherwise, do the opposite
                return !include;
        }
-
 };
 
 // Resets the test setup. Useful for tests that modify the DOM.
@@ -1180,7 +1212,7 @@ QUnit.reset = function() {
 
        // Return on non-browser environments
        // This is necessary to not break on node tests
-       if ( typeof window === "undefined" ) {
+       if ( !defined.document ) {
                return;
        }
 
@@ -1228,6 +1260,129 @@ function generateHash( module, testName ) {
        return hex.slice( -8 );
 }
 
+function synchronize( callback, priority ) {
+       var last = !priority;
+
+       if ( QUnit.objectType( callback ) === "array" ) {
+               while ( callback.length ) {
+                       synchronize( callback.shift() );
+               }
+               return;
+       }
+
+       if ( priority ) {
+               config.queue.splice( priorityCount++, 0, callback );
+       } else {
+               config.queue.push( callback );
+       }
+
+       if ( config.autorun && !config.blocking ) {
+               process( last );
+       }
+}
+
+function saveGlobal() {
+       config.pollution = [];
+
+       if ( config.noglobals ) {
+               for ( var key in global ) {
+                       if ( hasOwn.call( global, key ) ) {
+
+                               // in Opera sometimes DOM element ids show up here, ignore them
+                               if ( /^qunit-test-output/.test( key ) ) {
+                                       continue;
+                               }
+                               config.pollution.push( key );
+                       }
+               }
+       }
+}
+
+function checkPollution() {
+       var newGlobals,
+               deletedGlobals,
+               old = config.pollution;
+
+       saveGlobal();
+
+       newGlobals = diff( config.pollution, old );
+       if ( newGlobals.length > 0 ) {
+               QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) );
+       }
+
+       deletedGlobals = diff( old, config.pollution );
+       if ( deletedGlobals.length > 0 ) {
+               QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) );
+       }
+}
+
+// Will be exposed as QUnit.asyncTest
+function asyncTest( testName, expected, callback ) {
+       if ( arguments.length === 2 ) {
+               callback = expected;
+               expected = null;
+       }
+
+       QUnit.test( testName, expected, callback, true );
+}
+
+// Will be exposed as QUnit.test
+function test( testName, expected, callback, async ) {
+       if ( focused )  { return; }
+
+       var newTest;
+
+       if ( arguments.length === 2 ) {
+               callback = expected;
+               expected = null;
+       }
+
+       newTest = new Test({
+               testName: testName,
+               expected: expected,
+               async: async,
+               callback: callback
+       });
+
+       newTest.queue();
+}
+
+// Will be exposed as QUnit.skip
+function skip( testName ) {
+       if ( focused )  { return; }
+
+       var test = new Test({
+               testName: testName,
+               skip: true
+       });
+
+       test.queue();
+}
+
+// Will be exposed as QUnit.only
+function only( testName, expected, callback, async ) {
+       var newTest;
+
+       if ( focused )  { return; }
+
+       QUnit.config.queue.length = 0;
+       focused = true;
+
+       if ( arguments.length === 2 ) {
+               callback = expected;
+               expected = null;
+       }
+
+       newTest = new Test({
+               testName: testName,
+               expected: expected,
+               async: async,
+               callback: callback
+       });
+
+       newTest.queue();
+}
+
 function Assert( testContext ) {
        this.test = testContext;
 }
@@ -1245,30 +1400,55 @@ QUnit.assert = Assert.prototype = {
                }
        },
 
-       // Increment this Test's semaphore counter, then return a single-use function that
+       // Increment this Test's semaphore counter, then return a function that
        // decrements that counter a maximum of once.
-       async: function() {
+       async: function( count ) {
                var test = this.test,
-                       popped = false;
+                       popped = false,
+                       acceptCallCount = count;
+
+               if ( typeof acceptCallCount === "undefined" ) {
+                       acceptCallCount = 1;
+               }
 
                test.semaphore += 1;
                test.usedAsync = true;
                pauseProcessing();
 
                return function done() {
-                       if ( !popped ) {
-                               test.semaphore -= 1;
-                               popped = true;
-                               resumeProcessing();
-                       } else {
-                               test.pushFailure( "Called the callback returned from `assert.async` more than once",
+
+                       if ( popped ) {
+                               test.pushFailure( "Too many calls to the `assert.async` callback",
                                        sourceFromStacktrace( 2 ) );
+                               return;
+                       }
+                       acceptCallCount -= 1;
+                       if ( acceptCallCount > 0 ) {
+                               return;
                        }
+
+                       test.semaphore -= 1;
+                       popped = true;
+                       resumeProcessing();
                };
        },
 
        // Exports test.push() to the user API
-       push: function( /* result, actual, expected, message */ ) {
+       // Alias of pushResult.
+       push: function( result, actual, expected, message, negative ) {
+               var currentAssert = this instanceof Assert ? this : QUnit.config.current.assert;
+               return currentAssert.pushResult( {
+                       result: result,
+                       actual: actual,
+                       expected: expected,
+                       message: message,
+                       negative: negative
+               } );
+       },
+
+       pushResult: function( resultInfo ) {
+
+               // resultInfo = { result, actual, expected, message, negative }
                var assert = this,
                        currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current;
 
@@ -1291,57 +1471,112 @@ QUnit.assert = Assert.prototype = {
                if ( !( assert instanceof Assert ) ) {
                        assert = currentTest.assert;
                }
-               return assert.test.push.apply( assert.test, arguments );
+
+               return assert.test.pushResult( resultInfo );
        },
 
        ok: function( result, message ) {
                message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " +
                        QUnit.dump.parse( result ) );
-               this.push( !!result, result, true, message );
+               this.pushResult( {
+                       result: !!result,
+                       actual: result,
+                       expected: true,
+                       message: message
+               } );
        },
 
        notOk: function( result, message ) {
                message = message || ( !result ? "okay" : "failed, expected argument to be falsy, was: " +
                        QUnit.dump.parse( result ) );
-               this.push( !result, result, false, message );
+               this.pushResult( {
+                       result: !result,
+                       actual: result,
+                       expected: false,
+                       message: message
+               } );
        },
 
        equal: function( actual, expected, message ) {
                /*jshint eqeqeq:false */
-               this.push( expected == actual, actual, expected, message );
+               this.pushResult( {
+                       result: expected == actual,
+                       actual: actual,
+                       expected: expected,
+                       message: message
+               } );
        },
 
        notEqual: function( actual, expected, message ) {
                /*jshint eqeqeq:false */
-               this.push( expected != actual, actual, expected, message );
+               this.pushResult( {
+                       result: expected != actual,
+                       actual: actual,
+                       expected: expected,
+                       message: message,
+                       negative: true
+               } );
        },
 
        propEqual: function( actual, expected, message ) {
                actual = objectValues( actual );
                expected = objectValues( expected );
-               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
+               this.pushResult( {
+                       result: QUnit.equiv( actual, expected ),
+                       actual: actual,
+                       expected: expected,
+                       message: message
+               } );
        },
 
        notPropEqual: function( actual, expected, message ) {
                actual = objectValues( actual );
                expected = objectValues( expected );
-               this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
+               this.pushResult( {
+                       result: !QUnit.equiv( actual, expected ),
+                       actual: actual,
+                       expected: expected,
+                       message: message,
+                       negative: true
+               } );
        },
 
        deepEqual: function( actual, expected, message ) {
-               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
+               this.pushResult( {
+                       result: QUnit.equiv( actual, expected ),
+                       actual: actual,
+                       expected: expected,
+                       message: message
+               } );
        },
 
        notDeepEqual: function( actual, expected, message ) {
-               this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
+               this.pushResult( {
+                       result: !QUnit.equiv( actual, expected ),
+                       actual: actual,
+                       expected: expected,
+                       message: message,
+                       negative: true
+               } );
        },
 
        strictEqual: function( actual, expected, message ) {
-               this.push( expected === actual, actual, expected, message );
+               this.pushResult( {
+                       result: expected === actual,
+                       actual: actual,
+                       expected: expected,
+                       message: message
+               } );
        },
 
        notStrictEqual: function( actual, expected, message ) {
-               this.push( expected !== actual, actual, expected, message );
+               this.pushResult( {
+                       result: expected !== actual,
+                       actual: actual,
+                       expected: expected,
+                       message: message,
+                       negative: true
+               } );
        },
 
        "throws": function( block, expected, message ) {
@@ -1397,233 +1632,280 @@ QUnit.assert = Assert.prototype = {
                        }
                }
 
-               currentTest.assert.push( ok, actual, expectedOutput, message );
+               currentTest.assert.pushResult( {
+                       result: ok,
+                       actual: actual,
+                       expected: expectedOutput,
+                       message: message
+               } );
        }
 };
 
-// Provide an alternative to assert.throws(), for enviroments that consider throws a reserved word
+// Provide an alternative to assert.throws(), for environments that consider throws a reserved word
 // Known to us are: Closure Compiler, Narwhal
 (function() {
        /*jshint sub:true */
        Assert.prototype.raises = Assert.prototype[ "throws" ];
 }());
 
+function errorString( error ) {
+       var name, message,
+               resultErrorString = error.toString();
+       if ( resultErrorString.substring( 0, 7 ) === "[object" ) {
+               name = error.name ? error.name.toString() : "Error";
+               message = error.message ? error.message.toString() : "";
+               if ( name && message ) {
+                       return name + ": " + message;
+               } else if ( name ) {
+                       return name;
+               } else if ( message ) {
+                       return message;
+               } else {
+                       return "Error";
+               }
+       } else {
+               return resultErrorString;
+       }
+}
+
 // Test for equality any JavaScript type.
 // Author: Philippe Rathé <prathe@gmail.com>
 QUnit.equiv = (function() {
 
-       // Call the o related callback with the given arguments.
-       function bindCallbacks( o, callbacks, args ) {
-               var prop = QUnit.objectType( o );
-               if ( prop ) {
-                       if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {
-                               return callbacks[ prop ].apply( callbacks, args );
-                       } else {
-                               return callbacks[ prop ]; // or undefined
-                       }
-               }
-       }
+       // Stack to decide between skip/abort functions
+       var callers = [];
 
-       // the real equiv function
-       var innerEquiv,
+       // Stack to avoiding loops from circular referencing
+       var parents = [];
+       var parentsB = [];
 
-               // stack to decide between skip/abort functions
-               callers = [],
+       var getProto = Object.getPrototypeOf || function( obj ) {
 
-               // stack to avoiding loops from circular referencing
-               parents = [],
-               parentsB = [],
+               /*jshint proto: true */
+               return obj.__proto__;
+       };
 
-               getProto = Object.getPrototypeOf || function( obj ) {
-                       /* jshint camelcase: false, proto: true */
-                       return obj.__proto__;
-               },
-               callbacks = (function() {
+       function useStrictEquality( b, a ) {
 
-                       // for string, boolean, number and null
-                       function useStrictEquality( b, a ) {
+               // To catch short annotation VS 'new' annotation of a declaration. e.g.:
+               // `var i = 1;`
+               // `var j = new Number(1);`
+               if ( typeof a === "object" ) {
+                       a = a.valueOf();
+               }
+               if ( typeof b === "object" ) {
+                       b = b.valueOf();
+               }
 
-                               /*jshint eqeqeq:false */
-                               if ( b instanceof a.constructor || a instanceof b.constructor ) {
+               return a === b;
+       }
 
-                                       // to catch short annotation VS 'new' annotation of a
-                                       // declaration
-                                       // e.g. var i = 1;
-                                       // var j = new Number(1);
-                                       return a == b;
-                               } else {
-                                       return a === b;
-                               }
-                       }
+       function compareConstructors( a, b ) {
+               var protoA = getProto( a );
+               var protoB = getProto( b );
+
+               // Comparing constructors is more strict than using `instanceof`
+               if ( a.constructor === b.constructor ) {
+                       return true;
+               }
 
-                       return {
-                               "string": useStrictEquality,
-                               "boolean": useStrictEquality,
-                               "number": useStrictEquality,
-                               "null": useStrictEquality,
-                               "undefined": useStrictEquality,
+               // Ref #851
+               // If the obj prototype descends from a null constructor, treat it
+               // as a null prototype.
+               if ( protoA && protoA.constructor === null ) {
+                       protoA = null;
+               }
+               if ( protoB && protoB.constructor === null ) {
+                       protoB = null;
+               }
 
-                               "nan": function( b ) {
-                                       return isNaN( b );
-                               },
+               // Allow objects with no prototype to be equivalent to
+               // objects with Object as their constructor.
+               if ( ( protoA === null && protoB === Object.prototype ) ||
+                               ( protoB === null && protoA === Object.prototype ) ) {
+                       return true;
+               }
 
-                               "date": function( b, a ) {
-                                       return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();
-                               },
+               return false;
+       }
 
-                               "regexp": function( b, a ) {
-                                       return QUnit.objectType( b ) === "regexp" &&
+       function getRegExpFlags( regexp ) {
+               return "flags" in regexp ? regexp.flags : regexp.toString().match( /[gimuy]*$/ )[ 0 ];
+       }
 
-                                               // the regex itself
-                                               a.source === b.source &&
+       var callbacks = {
+               "string": useStrictEquality,
+               "boolean": useStrictEquality,
+               "number": useStrictEquality,
+               "null": useStrictEquality,
+               "undefined": useStrictEquality,
+               "symbol": useStrictEquality,
+               "date": useStrictEquality,
 
-                                               // and its modifiers
-                                               a.global === b.global &&
+               "nan": function() {
+                       return true;
+               },
 
-                                               // (gmi) ...
-                                               a.ignoreCase === b.ignoreCase &&
-                                               a.multiline === b.multiline &&
-                                               a.sticky === b.sticky;
-                               },
+               "regexp": function( b, a ) {
+                       return a.source === b.source &&
 
-                               // - skip when the property is a method of an instance (OOP)
-                               // - abort otherwise,
-                               // initial === would have catch identical references anyway
-                               "function": function() {
-                                       var caller = callers[ callers.length - 1 ];
-                                       return caller !== Object && typeof caller !== "undefined";
-                               },
+                               // Include flags in the comparison
+                               getRegExpFlags( a ) === getRegExpFlags( b );
+               },
 
-                               "array": function( b, a ) {
-                                       var i, j, len, loop, aCircular, bCircular;
+               // - skip when the property is a method of an instance (OOP)
+               // - abort otherwise,
+               // initial === would have catch identical references anyway
+               "function": function() {
+                       var caller = callers[ callers.length - 1 ];
+                       return caller !== Object && typeof caller !== "undefined";
+               },
 
-                                       // b could be an object literal here
-                                       if ( QUnit.objectType( b ) !== "array" ) {
-                                               return false;
-                                       }
+               "array": function( b, a ) {
+                       var i, j, len, loop, aCircular, bCircular;
 
-                                       len = a.length;
-                                       if ( len !== b.length ) {
-                                               // safe and faster
-                                               return false;
-                                       }
+                       len = a.length;
+                       if ( len !== b.length ) {
+                               // safe and faster
+                               return false;
+                       }
 
-                                       // track reference to avoid circular references
-                                       parents.push( a );
-                                       parentsB.push( b );
-                                       for ( i = 0; i < len; i++ ) {
-                                               loop = false;
-                                               for ( j = 0; j < parents.length; j++ ) {
-                                                       aCircular = parents[ j ] === a[ i ];
-                                                       bCircular = parentsB[ j ] === b[ i ];
-                                                       if ( aCircular || bCircular ) {
-                                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
-                                                                       loop = true;
-                                                               } else {
-                                                                       parents.pop();
-                                                                       parentsB.pop();
-                                                                       return false;
-                                                               }
-                                                       }
-                                               }
-                                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
+                       // Track reference to avoid circular references
+                       parents.push( a );
+                       parentsB.push( b );
+                       for ( i = 0; i < len; i++ ) {
+                               loop = false;
+                               for ( j = 0; j < parents.length; j++ ) {
+                                       aCircular = parents[ j ] === a[ i ];
+                                       bCircular = parentsB[ j ] === b[ i ];
+                                       if ( aCircular || bCircular ) {
+                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
+                                                       loop = true;
+                                               } else {
                                                        parents.pop();
                                                        parentsB.pop();
                                                        return false;
                                                }
                                        }
+                               }
+                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
                                        parents.pop();
                                        parentsB.pop();
-                                       return true;
-                               },
+                                       return false;
+                               }
+                       }
+                       parents.pop();
+                       parentsB.pop();
+                       return true;
+               },
 
-                               "object": function( b, a ) {
+               "set": function( b, a ) {
+                       var aArray, bArray;
 
-                                       /*jshint forin:false */
-                                       var i, j, loop, aCircular, bCircular,
-                                               // Default to true
-                                               eq = true,
-                                               aProperties = [],
-                                               bProperties = [];
+                       aArray = [];
+                       a.forEach( function( v ) {
+                               aArray.push( v );
+                       });
+                       bArray = [];
+                       b.forEach( function( v ) {
+                               bArray.push( v );
+                       });
 
-                                       // comparing constructors is more strict than using
-                                       // instanceof
-                                       if ( a.constructor !== b.constructor ) {
+                       return innerEquiv( bArray, aArray );
+               },
 
-                                               // Allow objects with no prototype to be equivalent to
-                                               // objects with Object as their constructor.
-                                               if ( !( ( getProto( a ) === null && getProto( b ) === Object.prototype ) ||
-                                                       ( getProto( b ) === null && getProto( a ) === Object.prototype ) ) ) {
-                                                       return false;
-                                               }
-                                       }
+               "map": function( b, a ) {
+                       var aArray, bArray;
 
-                                       // stack constructor before traversing properties
-                                       callers.push( a.constructor );
-
-                                       // track reference to avoid circular references
-                                       parents.push( a );
-                                       parentsB.push( b );
-
-                                       // be strict: don't ensure hasOwnProperty and go deep
-                                       for ( i in a ) {
-                                               loop = false;
-                                               for ( j = 0; j < parents.length; j++ ) {
-                                                       aCircular = parents[ j ] === a[ i ];
-                                                       bCircular = parentsB[ j ] === b[ i ];
-                                                       if ( aCircular || bCircular ) {
-                                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
-                                                                       loop = true;
-                                                               } else {
-                                                                       eq = false;
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
-                                               aProperties.push( i );
-                                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
+                       aArray = [];
+                       a.forEach( function( v, k ) {
+                               aArray.push( [ k, v ] );
+                       });
+                       bArray = [];
+                       b.forEach( function( v, k ) {
+                               bArray.push( [ k, v ] );
+                       });
+
+                       return innerEquiv( bArray, aArray );
+               },
+
+               "object": function( b, a ) {
+                       var i, j, loop, aCircular, bCircular;
+
+                       // Default to true
+                       var eq = true;
+                       var aProperties = [];
+                       var bProperties = [];
+
+                       if ( compareConstructors( a, b ) === false ) {
+                               return false;
+                       }
+
+                       // Stack constructor before traversing properties
+                       callers.push( a.constructor );
+
+                       // Track reference to avoid circular references
+                       parents.push( a );
+                       parentsB.push( b );
+
+                       // Be strict: don't ensure hasOwnProperty and go deep
+                       for ( i in a ) {
+                               loop = false;
+                               for ( j = 0; j < parents.length; j++ ) {
+                                       aCircular = parents[ j ] === a[ i ];
+                                       bCircular = parentsB[ j ] === b[ i ];
+                                       if ( aCircular || bCircular ) {
+                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
+                                                       loop = true;
+                                               } else {
                                                        eq = false;
                                                        break;
                                                }
                                        }
+                               }
+                               aProperties.push( i );
+                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
+                                       eq = false;
+                                       break;
+                               }
+                       }
 
-                                       parents.pop();
-                                       parentsB.pop();
-                                       callers.pop(); // unstack, we are done
+                       parents.pop();
+                       parentsB.pop();
 
-                                       for ( i in b ) {
-                                               bProperties.push( i ); // collect b's properties
-                                       }
+                       // Unstack, we are done
+                       callers.pop();
 
-                                       // Ensures identical properties name
-                                       return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
-                               }
-                       };
-               }());
+                       for ( i in b ) {
 
-       innerEquiv = function() { // can take multiple arguments
-               var args = [].slice.apply( arguments );
-               if ( args.length < 2 ) {
-                       return true; // end transition
+                               // Collect b's properties
+                               bProperties.push( i );
+                       }
+
+                       // Ensures identical properties name
+                       return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
                }
+       };
 
-               return ( (function( a, b ) {
-                       if ( a === b ) {
-                               return true; // catch the most you can
-                       } else if ( a === null || b === null || typeof a === "undefined" ||
-                                       typeof b === "undefined" ||
-                                       QUnit.objectType( a ) !== QUnit.objectType( b ) ) {
+       function typeEquiv( a, b ) {
+               var type = QUnit.objectType( a );
+               return QUnit.objectType( b ) === type && callbacks[ type ]( b, a );
+       }
 
-                               // don't lose time with error prone cases
-                               return false;
-                       } else {
-                               return bindCallbacks( a, callbacks, [ b, a ] );
-                       }
+       // The real equiv function
+       function innerEquiv( a, b ) {
 
-                       // apply transition with (1..n) arguments
-               }( args[ 0 ], args[ 1 ] ) ) &&
-                       innerEquiv.apply( this, args.splice( 1, args.length - 1 ) ) );
-       };
+               // We're done when there's nothing more to compare
+               if ( arguments.length < 2 ) {
+                       return true;
+               }
+
+               // Require type-specific equality
+               return ( a === b || typeEquiv( a, b ) ) &&
+
+                       // ...across all consecutive argument pairs
+                       ( arguments.length === 2 || innerEquiv.apply( this, [].slice.call( arguments, 1 ) ) );
+       }
 
        return innerEquiv;
 }());
@@ -1632,7 +1914,7 @@ QUnit.equiv = (function() {
 // http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
 QUnit.dump = (function() {
        function quote( str ) {
-               return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\"";
+               return "\"" + str.toString().replace( /\\/g, "\\\\" ).replace( /"/g, "\\\"" ) + "\"";
        }
        function literal( o ) {
                return o + "";
@@ -1839,1225 +2121,1255 @@ QUnit.dump = (function() {
                                                        }
                                                }
                                        }
-                                       ret += close;
+                                       ret += close;
+
+                                       // Show content of TextNode or CDATASection
+                                       if ( node.nodeType === 3 || node.nodeType === 4 ) {
+                                               ret += node.nodeValue;
+                                       }
+
+                                       return ret + open + "/" + tag + close;
+                               },
+
+                               // function calls it internally, it's the arguments part of the function
+                               functionArgs: function( fn ) {
+                                       var args,
+                                               l = fn.length;
+
+                                       if ( !l ) {
+                                               return "";
+                                       }
+
+                                       args = new Array( l );
+                                       while ( l-- ) {
+
+                                               // 97 is 'a'
+                                               args[ l ] = String.fromCharCode( 97 + l );
+                                       }
+                                       return " " + args.join( ", " ) + " ";
+                               },
+                               // object calls it internally, the key part of an item in a map
+                               key: quote,
+                               // function calls it internally, it's the content of the function
+                               functionCode: "[code]",
+                               // node calls it internally, it's a html attribute value
+                               attribute: quote,
+                               string: quote,
+                               date: quote,
+                               regexp: literal,
+                               number: literal,
+                               "boolean": literal
+                       },
+                       // if true, entities are escaped ( <, >, \t, space and \n )
+                       HTML: false,
+                       // indentation unit
+                       indentChar: "  ",
+                       // if true, items in a collection, are separated by a \n, else just a space.
+                       multiline: true
+               };
+
+       return dump;
+}());
+
+// back compat
+QUnit.jsDump = QUnit.dump;
+
+// Deprecated
+// Extend assert methods to QUnit for Backwards compatibility
+(function() {
+       var i,
+               assertions = Assert.prototype;
+
+       function applyCurrent( current ) {
+               return function() {
+                       var assert = new Assert( QUnit.config.current );
+                       current.apply( assert, arguments );
+               };
+       }
+
+       for ( i in assertions ) {
+               QUnit[ i ] = applyCurrent( assertions[ i ] );
+       }
+})();
+
+// For browser, export only select globals
+if ( defined.document ) {
+
+       (function() {
+               var i, l,
+                       keys = [
+                               "test",
+                               "module",
+                               "expect",
+                               "asyncTest",
+                               "start",
+                               "stop",
+                               "ok",
+                               "notOk",
+                               "equal",
+                               "notEqual",
+                               "propEqual",
+                               "notPropEqual",
+                               "deepEqual",
+                               "notDeepEqual",
+                               "strictEqual",
+                               "notStrictEqual",
+                               "throws",
+                               "raises"
+                       ];
+
+               for ( i = 0, l = keys.length; i < l; i++ ) {
+                       window[ keys[ i ] ] = QUnit[ keys[ i ] ];
+               }
+       })();
+
+       window.QUnit = QUnit;
+}
+
+// For nodejs
+if ( typeof module !== "undefined" && module && module.exports ) {
+       module.exports = QUnit;
+
+       // For consistency with CommonJS environments' exports
+       module.exports.QUnit = QUnit;
+}
+
+// For CommonJS with exports, but without module.exports, like Rhino
+if ( typeof exports !== "undefined" && exports ) {
+       exports.QUnit = QUnit;
+}
+
+if ( typeof define === "function" && define.amd ) {
+       define( function() {
+               return QUnit;
+       } );
+       QUnit.config.autostart = false;
+}
+
+/*
+ * This file is a modified version of google-diff-match-patch's JavaScript implementation
+ * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
+ * modifications are licensed as more fully set forth in LICENSE.txt.
+ *
+ * The original source of google-diff-match-patch is attributable and licensed as follows:
+ *
+ * Copyright 2006 Google Inc.
+ * https://code.google.com/p/google-diff-match-patch/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * More Info:
+ *  https://code.google.com/p/google-diff-match-patch/
+ *
+ * Usage: QUnit.diff(expected, actual)
+ *
+ */
+QUnit.diff = ( function() {
+       function DiffMatchPatch() {
+       }
+
+       //  DIFF FUNCTIONS
+
+       /**
+        * The data structure representing a diff is an array of tuples:
+        * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
+        * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
+        */
+       var DIFF_DELETE = -1,
+               DIFF_INSERT = 1,
+               DIFF_EQUAL = 0;
+
+       /**
+        * Find the differences between two texts.  Simplifies the problem by stripping
+        * any common prefix or suffix off the texts before diffing.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {boolean=} optChecklines Optional speedup flag. If present and false,
+        *     then don't run a line-level diff first to identify the changed areas.
+        *     Defaults to true, which does a faster, slightly less optimal diff.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines ) {
+               var deadline, checklines, commonlength,
+                       commonprefix, commonsuffix, diffs;
+
+               // The diff must be complete in up to 1 second.
+               deadline = ( new Date() ).getTime() + 1000;
+
+               // Check for null inputs.
+               if ( text1 === null || text2 === null ) {
+                       throw new Error( "Null input. (DiffMain)" );
+               }
+
+               // Check for equality (speedup).
+               if ( text1 === text2 ) {
+                       if ( text1 ) {
+                               return [
+                                       [ DIFF_EQUAL, text1 ]
+                               ];
+                       }
+                       return [];
+               }
+
+               if ( typeof optChecklines === "undefined" ) {
+                       optChecklines = true;
+               }
+
+               checklines = optChecklines;
+
+               // Trim off common prefix (speedup).
+               commonlength = this.diffCommonPrefix( text1, text2 );
+               commonprefix = text1.substring( 0, commonlength );
+               text1 = text1.substring( commonlength );
+               text2 = text2.substring( commonlength );
+
+               // Trim off common suffix (speedup).
+               commonlength = this.diffCommonSuffix( text1, text2 );
+               commonsuffix = text1.substring( text1.length - commonlength );
+               text1 = text1.substring( 0, text1.length - commonlength );
+               text2 = text2.substring( 0, text2.length - commonlength );
+
+               // Compute the diff on the middle block.
+               diffs = this.diffCompute( text1, text2, checklines, deadline );
+
+               // Restore the prefix and suffix.
+               if ( commonprefix ) {
+                       diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
+               }
+               if ( commonsuffix ) {
+                       diffs.push( [ DIFF_EQUAL, commonsuffix ] );
+               }
+               this.diffCleanupMerge( diffs );
+               return diffs;
+       };
+
+       /**
+        * Reduce the number of edits by eliminating operationally trivial equalities.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
+               var changes, equalities, equalitiesLength, lastequality,
+                       pointer, preIns, preDel, postIns, postDel;
+               changes = false;
+               equalities = []; // Stack of indices where equalities are found.
+               equalitiesLength = 0; // Keeping our own length var is faster in JS.
+               /** @type {?string} */
+               lastequality = null;
+               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+               pointer = 0; // Index of current position.
+               // Is there an insertion operation before the last equality.
+               preIns = false;
+               // Is there a deletion operation before the last equality.
+               preDel = false;
+               // Is there an insertion operation after the last equality.
+               postIns = false;
+               // Is there a deletion operation after the last equality.
+               postDel = false;
+               while ( pointer < diffs.length ) {
+
+                       // Equality found.
+                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) {
+                               if ( diffs[ pointer ][ 1 ].length < 4 && ( postIns || postDel ) ) {
+
+                                       // Candidate found.
+                                       equalities[ equalitiesLength++ ] = pointer;
+                                       preIns = postIns;
+                                       preDel = postDel;
+                                       lastequality = diffs[ pointer ][ 1 ];
+                               } else {
+
+                                       // Not a candidate, and can never become one.
+                                       equalitiesLength = 0;
+                                       lastequality = null;
+                               }
+                               postIns = postDel = false;
+
+                       // An insertion or deletion.
+                       } else {
+
+                               if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
+                                       postDel = true;
+                               } else {
+                                       postIns = true;
+                               }
+
+                               /*
+                                * Five types to be split:
+                                * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
+                                * <ins>A</ins>X<ins>C</ins><del>D</del>
+                                * <ins>A</ins><del>B</del>X<ins>C</ins>
+                                * <ins>A</del>X<ins>C</ins><del>D</del>
+                                * <ins>A</ins><del>B</del>X<del>C</del>
+                                */
+                               if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
+                                               ( ( lastequality.length < 2 ) &&
+                                               ( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
+
+                                       // Duplicate record.
+                                       diffs.splice(
+                                               equalities[ equalitiesLength - 1 ],
+                                               0,
+                                               [ DIFF_DELETE, lastequality ]
+                                       );
+
+                                       // Change second copy to insert.
+                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
+                                       equalitiesLength--; // Throw away the equality we just deleted;
+                                       lastequality = null;
+                                       if ( preIns && preDel ) {
+                                               // No changes made which could affect previous entry, keep going.
+                                               postIns = postDel = true;
+                                               equalitiesLength = 0;
+                                       } else {
+                                               equalitiesLength--; // Throw away the previous equality.
+                                               pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
+                                               postIns = postDel = false;
+                                       }
+                                       changes = true;
+                               }
+                       }
+                       pointer++;
+               }
+
+               if ( changes ) {
+                       this.diffCleanupMerge( diffs );
+               }
+       };
+
+       /**
+        * Convert a diff array into a pretty HTML report.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        * @param {integer} string to be beautified.
+        * @return {string} HTML representation.
+        */
+       DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
+               var op, data, x,
+                       html = [];
+               for ( x = 0; x < diffs.length; x++ ) {
+                       op = diffs[ x ][ 0 ]; // Operation (insert, delete, equal)
+                       data = diffs[ x ][ 1 ]; // Text of change.
+                       switch ( op ) {
+                       case DIFF_INSERT:
+                               html[ x ] = "<ins>" + data + "</ins>";
+                               break;
+                       case DIFF_DELETE:
+                               html[ x ] = "<del>" + data + "</del>";
+                               break;
+                       case DIFF_EQUAL:
+                               html[ x ] = "<span>" + data + "</span>";
+                               break;
+                       }
+               }
+               return html.join( "" );
+       };
+
+       /**
+        * Determine the common prefix of two strings.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {number} The number of characters common to the start of each
+        *     string.
+        */
+       DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
+               var pointermid, pointermax, pointermin, pointerstart;
+               // Quick check for common null cases.
+               if ( !text1 || !text2 || text1.charAt( 0 ) !== text2.charAt( 0 ) ) {
+                       return 0;
+               }
+               // Binary search.
+               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+               pointermin = 0;
+               pointermax = Math.min( text1.length, text2.length );
+               pointermid = pointermax;
+               pointerstart = 0;
+               while ( pointermin < pointermid ) {
+                       if ( text1.substring( pointerstart, pointermid ) ===
+                                       text2.substring( pointerstart, pointermid ) ) {
+                               pointermin = pointermid;
+                               pointerstart = pointermin;
+                       } else {
+                               pointermax = pointermid;
+                       }
+                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+               }
+               return pointermid;
+       };
+
+       /**
+        * Determine the common suffix of two strings.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {number} The number of characters common to the end of each string.
+        */
+       DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
+               var pointermid, pointermax, pointermin, pointerend;
+               // Quick check for common null cases.
+               if ( !text1 ||
+                               !text2 ||
+                               text1.charAt( text1.length - 1 ) !== text2.charAt( text2.length - 1 ) ) {
+                       return 0;
+               }
+               // Binary search.
+               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+               pointermin = 0;
+               pointermax = Math.min( text1.length, text2.length );
+               pointermid = pointermax;
+               pointerend = 0;
+               while ( pointermin < pointermid ) {
+                       if ( text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
+                                       text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
+                               pointermin = pointermid;
+                               pointerend = pointermin;
+                       } else {
+                               pointermax = pointermid;
+                       }
+                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+               }
+               return pointermid;
+       };
+
+       /**
+        * Find the differences between two texts.  Assumes that the texts do not
+        * have any common prefix or suffix.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {boolean} checklines Speedup flag.  If false, then don't run a
+        *     line-level diff first to identify the changed areas.
+        *     If true, then run a faster, slightly less optimal diff.
+        * @param {number} deadline Time when the diff should be complete by.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
+               var diffs, longtext, shorttext, i, hm,
+                       text1A, text2A, text1B, text2B,
+                       midCommon, diffsA, diffsB;
+
+               if ( !text1 ) {
+                       // Just add some text (speedup).
+                       return [
+                               [ DIFF_INSERT, text2 ]
+                       ];
+               }
+
+               if ( !text2 ) {
+                       // Just delete some text (speedup).
+                       return [
+                               [ DIFF_DELETE, text1 ]
+                       ];
+               }
+
+               longtext = text1.length > text2.length ? text1 : text2;
+               shorttext = text1.length > text2.length ? text2 : text1;
+               i = longtext.indexOf( shorttext );
+               if ( i !== -1 ) {
+                       // Shorter text is inside the longer text (speedup).
+                       diffs = [
+                               [ DIFF_INSERT, longtext.substring( 0, i ) ],
+                               [ DIFF_EQUAL, shorttext ],
+                               [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
+                       ];
+                       // Swap insertions for deletions if diff is reversed.
+                       if ( text1.length > text2.length ) {
+                               diffs[ 0 ][ 0 ] = diffs[ 2 ][ 0 ] = DIFF_DELETE;
+                       }
+                       return diffs;
+               }
+
+               if ( shorttext.length === 1 ) {
+                       // Single character string.
+                       // After the previous speedup, the character can't be an equality.
+                       return [
+                               [ DIFF_DELETE, text1 ],
+                               [ DIFF_INSERT, text2 ]
+                       ];
+               }
+
+               // Check to see if the problem can be split in two.
+               hm = this.diffHalfMatch( text1, text2 );
+               if ( hm ) {
+                       // A half-match was found, sort out the return data.
+                       text1A = hm[ 0 ];
+                       text1B = hm[ 1 ];
+                       text2A = hm[ 2 ];
+                       text2B = hm[ 3 ];
+                       midCommon = hm[ 4 ];
+                       // Send both pairs off for separate processing.
+                       diffsA = this.DiffMain( text1A, text2A, checklines, deadline );
+                       diffsB = this.DiffMain( text1B, text2B, checklines, deadline );
+                       // Merge the results.
+                       return diffsA.concat( [
+                               [ DIFF_EQUAL, midCommon ]
+                       ], diffsB );
+               }
+
+               if ( checklines && text1.length > 100 && text2.length > 100 ) {
+                       return this.diffLineMode( text1, text2, deadline );
+               }
+
+               return this.diffBisect( text1, text2, deadline );
+       };
+
+       /**
+        * Do the two texts share a substring which is at least half the length of the
+        * longer text?
+        * This speedup can produce non-minimal diffs.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {Array.<string>} Five element Array, containing the prefix of
+        *     text1, the suffix of text1, the prefix of text2, the suffix of
+        *     text2 and the common middle.  Or null if there was no match.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffHalfMatch = function( text1, text2 ) {
+               var longtext, shorttext, dmp,
+                       text1A, text2B, text2A, text1B, midCommon,
+                       hm1, hm2, hm;
+
+               longtext = text1.length > text2.length ? text1 : text2;
+               shorttext = text1.length > text2.length ? text2 : text1;
+               if ( longtext.length < 4 || shorttext.length * 2 < longtext.length ) {
+                       return null; // Pointless.
+               }
+               dmp = this; // 'this' becomes 'window' in a closure.
+
+               /**
+                * Does a substring of shorttext exist within longtext such that the substring
+                * is at least half the length of longtext?
+                * Closure, but does not reference any external variables.
+                * @param {string} longtext Longer string.
+                * @param {string} shorttext Shorter string.
+                * @param {number} i Start index of quarter length substring within longtext.
+                * @return {Array.<string>} Five element Array, containing the prefix of
+                *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
+                *     of shorttext and the common middle.  Or null if there was no match.
+                * @private
+                */
+               function diffHalfMatchI( longtext, shorttext, i ) {
+                       var seed, j, bestCommon, prefixLength, suffixLength,
+                               bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
+                       // Start with a 1/4 length substring at position i as a seed.
+                       seed = longtext.substring( i, i + Math.floor( longtext.length / 4 ) );
+                       j = -1;
+                       bestCommon = "";
+                       while ( ( j = shorttext.indexOf( seed, j + 1 ) ) !== -1 ) {
+                               prefixLength = dmp.diffCommonPrefix( longtext.substring( i ),
+                                       shorttext.substring( j ) );
+                               suffixLength = dmp.diffCommonSuffix( longtext.substring( 0, i ),
+                                       shorttext.substring( 0, j ) );
+                               if ( bestCommon.length < suffixLength + prefixLength ) {
+                                       bestCommon = shorttext.substring( j - suffixLength, j ) +
+                                               shorttext.substring( j, j + prefixLength );
+                                       bestLongtextA = longtext.substring( 0, i - suffixLength );
+                                       bestLongtextB = longtext.substring( i + prefixLength );
+                                       bestShorttextA = shorttext.substring( 0, j - suffixLength );
+                                       bestShorttextB = shorttext.substring( j + prefixLength );
+                               }
+                       }
+                       if ( bestCommon.length * 2 >= longtext.length ) {
+                               return [ bestLongtextA, bestLongtextB,
+                                       bestShorttextA, bestShorttextB, bestCommon
+                               ];
+                       } else {
+                               return null;
+                       }
+               }
+
+               // First check if the second quarter is the seed for a half-match.
+               hm1 = diffHalfMatchI( longtext, shorttext,
+                       Math.ceil( longtext.length / 4 ) );
+               // Check again based on the third quarter.
+               hm2 = diffHalfMatchI( longtext, shorttext,
+                       Math.ceil( longtext.length / 2 ) );
+               if ( !hm1 && !hm2 ) {
+                       return null;
+               } else if ( !hm2 ) {
+                       hm = hm1;
+               } else if ( !hm1 ) {
+                       hm = hm2;
+               } else {
+                       // Both matched.  Select the longest.
+                       hm = hm1[ 4 ].length > hm2[ 4 ].length ? hm1 : hm2;
+               }
+
+               // A half-match was found, sort out the return data.
+               text1A, text1B, text2A, text2B;
+               if ( text1.length > text2.length ) {
+                       text1A = hm[ 0 ];
+                       text1B = hm[ 1 ];
+                       text2A = hm[ 2 ];
+                       text2B = hm[ 3 ];
+               } else {
+                       text2A = hm[ 0 ];
+                       text2B = hm[ 1 ];
+                       text1A = hm[ 2 ];
+                       text1B = hm[ 3 ];
+               }
+               midCommon = hm[ 4 ];
+               return [ text1A, text1B, text2A, text2B, midCommon ];
+       };
+
+       /**
+        * Do a quick line-level diff on both strings, then rediff the parts for
+        * greater accuracy.
+        * This speedup can produce non-minimal diffs.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {number} deadline Time when the diff should be complete by.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffLineMode = function( text1, text2, deadline ) {
+               var a, diffs, linearray, pointer, countInsert,
+                       countDelete, textInsert, textDelete, j;
+               // Scan the text on a line-by-line basis first.
+               a = this.diffLinesToChars( text1, text2 );
+               text1 = a.chars1;
+               text2 = a.chars2;
+               linearray = a.lineArray;
+
+               diffs = this.DiffMain( text1, text2, false, deadline );
+
+               // Convert the diff back to original text.
+               this.diffCharsToLines( diffs, linearray );
+               // Eliminate freak matches (e.g. blank lines)
+               this.diffCleanupSemantic( diffs );
+
+               // Rediff any replacement blocks, this time character-by-character.
+               // Add a dummy entry at the end.
+               diffs.push( [ DIFF_EQUAL, "" ] );
+               pointer = 0;
+               countDelete = 0;
+               countInsert = 0;
+               textDelete = "";
+               textInsert = "";
+               while ( pointer < diffs.length ) {
+                       switch ( diffs[ pointer ][ 0 ] ) {
+                       case DIFF_INSERT:
+                               countInsert++;
+                               textInsert += diffs[ pointer ][ 1 ];
+                               break;
+                       case DIFF_DELETE:
+                               countDelete++;
+                               textDelete += diffs[ pointer ][ 1 ];
+                               break;
+                       case DIFF_EQUAL:
+                               // Upon reaching an equality, check for prior redundancies.
+                               if ( countDelete >= 1 && countInsert >= 1 ) {
+                                       // Delete the offending records and add the merged ones.
+                                       diffs.splice( pointer - countDelete - countInsert,
+                                               countDelete + countInsert );
+                                       pointer = pointer - countDelete - countInsert;
+                                       a = this.DiffMain( textDelete, textInsert, false, deadline );
+                                       for ( j = a.length - 1; j >= 0; j-- ) {
+                                               diffs.splice( pointer, 0, a[ j ] );
+                                       }
+                                       pointer = pointer + a.length;
+                               }
+                               countInsert = 0;
+                               countDelete = 0;
+                               textDelete = "";
+                               textInsert = "";
+                               break;
+                       }
+                       pointer++;
+               }
+               diffs.pop(); // Remove the dummy entry at the end.
+
+               return diffs;
+       };
+
+       /**
+        * Find the 'middle snake' of a diff, split the problem in two
+        * and return the recursively constructed diff.
+        * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {number} deadline Time at which to bail if not yet complete.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffBisect = function( text1, text2, deadline ) {
+               var text1Length, text2Length, maxD, vOffset, vLength,
+                       v1, v2, x, delta, front, k1start, k1end, k2start,
+                       k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
+               // Cache the text lengths to prevent multiple calls.
+               text1Length = text1.length;
+               text2Length = text2.length;
+               maxD = Math.ceil( ( text1Length + text2Length ) / 2 );
+               vOffset = maxD;
+               vLength = 2 * maxD;
+               v1 = new Array( vLength );
+               v2 = new Array( vLength );
+               // Setting all elements to -1 is faster in Chrome & Firefox than mixing
+               // integers and undefined.
+               for ( x = 0; x < vLength; x++ ) {
+                       v1[ x ] = -1;
+                       v2[ x ] = -1;
+               }
+               v1[ vOffset + 1 ] = 0;
+               v2[ vOffset + 1 ] = 0;
+               delta = text1Length - text2Length;
+               // If the total number of characters is odd, then the front path will collide
+               // with the reverse path.
+               front = ( delta % 2 !== 0 );
+               // Offsets for start and end of k loop.
+               // Prevents mapping of space beyond the grid.
+               k1start = 0;
+               k1end = 0;
+               k2start = 0;
+               k2end = 0;
+               for ( d = 0; d < maxD; d++ ) {
+                       // Bail out if deadline is reached.
+                       if ( ( new Date() ).getTime() > deadline ) {
+                               break;
+                       }
+
+                       // Walk the front path one step.
+                       for ( k1 = -d + k1start; k1 <= d - k1end; k1 += 2 ) {
+                               k1Offset = vOffset + k1;
+                               if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
+                                       x1 = v1[ k1Offset + 1 ];
+                               } else {
+                                       x1 = v1[ k1Offset - 1 ] + 1;
+                               }
+                               y1 = x1 - k1;
+                               while ( x1 < text1Length && y1 < text2Length &&
+                                       text1.charAt( x1 ) === text2.charAt( y1 ) ) {
+                                       x1++;
+                                       y1++;
+                               }
+                               v1[ k1Offset ] = x1;
+                               if ( x1 > text1Length ) {
+                                       // Ran off the right of the graph.
+                                       k1end += 2;
+                               } else if ( y1 > text2Length ) {
+                                       // Ran off the bottom of the graph.
+                                       k1start += 2;
+                               } else if ( front ) {
+                                       k2Offset = vOffset + delta - k1;
+                                       if ( k2Offset >= 0 && k2Offset < vLength && v2[ k2Offset ] !== -1 ) {
+                                               // Mirror x2 onto top-left coordinate system.
+                                               x2 = text1Length - v2[ k2Offset ];
+                                               if ( x1 >= x2 ) {
+                                                       // Overlap detected.
+                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
+                                               }
+                                       }
+                               }
+                       }
 
-                                       // Show content of TextNode or CDATASection
-                                       if ( node.nodeType === 3 || node.nodeType === 4 ) {
-                                               ret += node.nodeValue;
+                       // Walk the reverse path one step.
+                       for ( k2 = -d + k2start; k2 <= d - k2end; k2 += 2 ) {
+                               k2Offset = vOffset + k2;
+                               if ( k2 === -d || ( k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
+                                       x2 = v2[ k2Offset + 1 ];
+                               } else {
+                                       x2 = v2[ k2Offset - 1 ] + 1;
+                               }
+                               y2 = x2 - k2;
+                               while ( x2 < text1Length && y2 < text2Length &&
+                                       text1.charAt( text1Length - x2 - 1 ) ===
+                                       text2.charAt( text2Length - y2 - 1 ) ) {
+                                       x2++;
+                                       y2++;
+                               }
+                               v2[ k2Offset ] = x2;
+                               if ( x2 > text1Length ) {
+                                       // Ran off the left of the graph.
+                                       k2end += 2;
+                               } else if ( y2 > text2Length ) {
+                                       // Ran off the top of the graph.
+                                       k2start += 2;
+                               } else if ( !front ) {
+                                       k1Offset = vOffset + delta - k2;
+                                       if ( k1Offset >= 0 && k1Offset < vLength && v1[ k1Offset ] !== -1 ) {
+                                               x1 = v1[ k1Offset ];
+                                               y1 = vOffset + x1 - k1Offset;
+                                               // Mirror x2 onto top-left coordinate system.
+                                               x2 = text1Length - x2;
+                                               if ( x1 >= x2 ) {
+                                                       // Overlap detected.
+                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
+                                               }
                                        }
+                               }
+                       }
+               }
+               // Diff took too long and hit the deadline or
+               // number of diffs equals number of characters, no commonality at all.
+               return [
+                       [ DIFF_DELETE, text1 ],
+                       [ DIFF_INSERT, text2 ]
+               ];
+       };
 
-                                       return ret + open + "/" + tag + close;
-                               },
-
-                               // function calls it internally, it's the arguments part of the function
-                               functionArgs: function( fn ) {
-                                       var args,
-                                               l = fn.length;
+       /**
+        * Given the location of the 'middle snake', split the diff in two parts
+        * and recurse.
+        * @param {string} text1 Old string to be diffed.
+        * @param {string} text2 New string to be diffed.
+        * @param {number} x Index of split point in text1.
+        * @param {number} y Index of split point in text2.
+        * @param {number} deadline Time at which to bail if not yet complete.
+        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
+               var text1a, text1b, text2a, text2b, diffs, diffsb;
+               text1a = text1.substring( 0, x );
+               text2a = text2.substring( 0, y );
+               text1b = text1.substring( x );
+               text2b = text2.substring( y );
+
+               // Compute both diffs serially.
+               diffs = this.DiffMain( text1a, text2a, false, deadline );
+               diffsb = this.DiffMain( text1b, text2b, false, deadline );
+
+               return diffs.concat( diffsb );
+       };
 
-                                       if ( !l ) {
-                                               return "";
-                                       }
+       /**
+        * Reduce the number of edits by eliminating semantically trivial equalities.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.diffCleanupSemantic = function( diffs ) {
+               var changes, equalities, equalitiesLength, lastequality,
+                       pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
+                       lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
+               changes = false;
+               equalities = []; // Stack of indices where equalities are found.
+               equalitiesLength = 0; // Keeping our own length var is faster in JS.
+               /** @type {?string} */
+               lastequality = null;
+               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+               pointer = 0; // Index of current position.
+               // Number of characters that changed prior to the equality.
+               lengthInsertions1 = 0;
+               lengthDeletions1 = 0;
+               // Number of characters that changed after the equality.
+               lengthInsertions2 = 0;
+               lengthDeletions2 = 0;
+               while ( pointer < diffs.length ) {
+                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
+                               equalities[ equalitiesLength++ ] = pointer;
+                               lengthInsertions1 = lengthInsertions2;
+                               lengthDeletions1 = lengthDeletions2;
+                               lengthInsertions2 = 0;
+                               lengthDeletions2 = 0;
+                               lastequality = diffs[ pointer ][ 1 ];
+                       } else { // An insertion or deletion.
+                               if ( diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
+                                       lengthInsertions2 += diffs[ pointer ][ 1 ].length;
+                               } else {
+                                       lengthDeletions2 += diffs[ pointer ][ 1 ].length;
+                               }
+                               // Eliminate an equality that is smaller or equal to the edits on both
+                               // sides of it.
+                               if ( lastequality && ( lastequality.length <=
+                                               Math.max( lengthInsertions1, lengthDeletions1 ) ) &&
+                                               ( lastequality.length <= Math.max( lengthInsertions2,
+                                                       lengthDeletions2 ) ) ) {
+
+                                       // Duplicate record.
+                                       diffs.splice(
+                                               equalities[ equalitiesLength - 1 ],
+                                               0,
+                                               [ DIFF_DELETE, lastequality ]
+                                       );
+
+                                       // Change second copy to insert.
+                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
+
+                                       // Throw away the equality we just deleted.
+                                       equalitiesLength--;
+
+                                       // Throw away the previous equality (it needs to be reevaluated).
+                                       equalitiesLength--;
+                                       pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
+
+                                       // Reset the counters.
+                                       lengthInsertions1 = 0;
+                                       lengthDeletions1 = 0;
+                                       lengthInsertions2 = 0;
+                                       lengthDeletions2 = 0;
+                                       lastequality = null;
+                                       changes = true;
+                               }
+                       }
+                       pointer++;
+               }
 
-                                       args = new Array( l );
-                                       while ( l-- ) {
+               // Normalize the diff.
+               if ( changes ) {
+                       this.diffCleanupMerge( diffs );
+               }
 
-                                               // 97 is 'a'
-                                               args[ l ] = String.fromCharCode( 97 + l );
+               // Find any overlaps between deletions and insertions.
+               // e.g: <del>abcxxx</del><ins>xxxdef</ins>
+               //   -> <del>abc</del>xxx<ins>def</ins>
+               // e.g: <del>xxxabc</del><ins>defxxx</ins>
+               //   -> <ins>def</ins>xxx<del>abc</del>
+               // Only extract an overlap if it is as big as the edit ahead or behind it.
+               pointer = 1;
+               while ( pointer < diffs.length ) {
+                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_DELETE &&
+                                       diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
+                               deletion = diffs[ pointer - 1 ][ 1 ];
+                               insertion = diffs[ pointer ][ 1 ];
+                               overlapLength1 = this.diffCommonOverlap( deletion, insertion );
+                               overlapLength2 = this.diffCommonOverlap( insertion, deletion );
+                               if ( overlapLength1 >= overlapLength2 ) {
+                                       if ( overlapLength1 >= deletion.length / 2 ||
+                                                       overlapLength1 >= insertion.length / 2 ) {
+                                               // Overlap found.  Insert an equality and trim the surrounding edits.
+                                               diffs.splice(
+                                                       pointer,
+                                                       0,
+                                                       [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ]
+                                               );
+                                               diffs[ pointer - 1 ][ 1 ] =
+                                                       deletion.substring( 0, deletion.length - overlapLength1 );
+                                               diffs[ pointer + 1 ][ 1 ] = insertion.substring( overlapLength1 );
+                                               pointer++;
                                        }
-                                       return " " + args.join( ", " ) + " ";
-                               },
-                               // object calls it internally, the key part of an item in a map
-                               key: quote,
-                               // function calls it internally, it's the content of the function
-                               functionCode: "[code]",
-                               // node calls it internally, it's an html attribute value
-                               attribute: quote,
-                               string: quote,
-                               date: quote,
-                               regexp: literal,
-                               number: literal,
-                               "boolean": literal
-                       },
-                       // if true, entities are escaped ( <, >, \t, space and \n )
-                       HTML: false,
-                       // indentation unit
-                       indentChar: "  ",
-                       // if true, items in a collection, are separated by a \n, else just a space.
-                       multiline: true
-               };
-
-       return dump;
-}());
+                               } else {
+                                       if ( overlapLength2 >= deletion.length / 2 ||
+                                                       overlapLength2 >= insertion.length / 2 ) {
+
+                                               // Reverse overlap found.
+                                               // Insert an equality and swap and trim the surrounding edits.
+                                               diffs.splice(
+                                                       pointer,
+                                                       0,
+                                                       [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ]
+                                               );
+
+                                               diffs[ pointer - 1 ][ 0 ] = DIFF_INSERT;
+                                               diffs[ pointer - 1 ][ 1 ] =
+                                                       insertion.substring( 0, insertion.length - overlapLength2 );
+                                               diffs[ pointer + 1 ][ 0 ] = DIFF_DELETE;
+                                               diffs[ pointer + 1 ][ 1 ] =
+                                                       deletion.substring( overlapLength2 );
+                                               pointer++;
+                                       }
+                               }
+                               pointer++;
+                       }
+                       pointer++;
+               }
+       };
 
-// back compat
-QUnit.jsDump = QUnit.dump;
+       /**
+        * Determine if the suffix of one string is the prefix of another.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {number} The number of characters common to the end of the first
+        *     string and the start of the second string.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffCommonOverlap = function( text1, text2 ) {
+               var text1Length, text2Length, textLength,
+                       best, length, pattern, found;
+               // Cache the text lengths to prevent multiple calls.
+               text1Length = text1.length;
+               text2Length = text2.length;
+               // Eliminate the null case.
+               if ( text1Length === 0 || text2Length === 0 ) {
+                       return 0;
+               }
+               // Truncate the longer string.
+               if ( text1Length > text2Length ) {
+                       text1 = text1.substring( text1Length - text2Length );
+               } else if ( text1Length < text2Length ) {
+                       text2 = text2.substring( 0, text1Length );
+               }
+               textLength = Math.min( text1Length, text2Length );
+               // Quick check for the worst case.
+               if ( text1 === text2 ) {
+                       return textLength;
+               }
 
-// For browser, export only select globals
-if ( typeof window !== "undefined" ) {
+               // Start by looking for a single character match
+               // and increase length until no match is found.
+               // Performance analysis: https://neil.fraser.name/news/2010/11/04/
+               best = 0;
+               length = 1;
+               while ( true ) {
+                       pattern = text1.substring( textLength - length );
+                       found = text2.indexOf( pattern );
+                       if ( found === -1 ) {
+                               return best;
+                       }
+                       length += found;
+                       if ( found === 0 || text1.substring( textLength - length ) ===
+                                       text2.substring( 0, length ) ) {
+                               best = length;
+                               length++;
+                       }
+               }
+       };
 
-       // Deprecated
-       // Extend assert methods to QUnit and Global scope through Backwards compatibility
-       (function() {
-               var i,
-                       assertions = Assert.prototype;
+       /**
+        * Split two texts into an array of strings.  Reduce the texts to a string of
+        * hashes where each Unicode character represents one line.
+        * @param {string} text1 First string.
+        * @param {string} text2 Second string.
+        * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
+        *     An object containing the encoded text1, the encoded text2 and
+        *     the array of unique strings.
+        *     The zeroth element of the array of unique strings is intentionally blank.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffLinesToChars = function( text1, text2 ) {
+               var lineArray, lineHash, chars1, chars2;
+               lineArray = []; // e.g. lineArray[4] === 'Hello\n'
+               lineHash = {}; // e.g. lineHash['Hello\n'] === 4
+
+               // '\x00' is a valid character, but various debuggers don't like it.
+               // So we'll insert a junk entry to avoid generating a null character.
+               lineArray[ 0 ] = "";
+
+               /**
+                * Split a text into an array of strings.  Reduce the texts to a string of
+                * hashes where each Unicode character represents one line.
+                * Modifies linearray and linehash through being a closure.
+                * @param {string} text String to encode.
+                * @return {string} Encoded string.
+                * @private
+                */
+               function diffLinesToCharsMunge( text ) {
+                       var chars, lineStart, lineEnd, lineArrayLength, line;
+                       chars = "";
+                       // Walk the text, pulling out a substring for each line.
+                       // text.split('\n') would would temporarily double our memory footprint.
+                       // Modifying text would create many large strings to garbage collect.
+                       lineStart = 0;
+                       lineEnd = -1;
+                       // Keeping our own length variable is faster than looking it up.
+                       lineArrayLength = lineArray.length;
+                       while ( lineEnd < text.length - 1 ) {
+                               lineEnd = text.indexOf( "\n", lineStart );
+                               if ( lineEnd === -1 ) {
+                                       lineEnd = text.length - 1;
+                               }
+                               line = text.substring( lineStart, lineEnd + 1 );
+                               lineStart = lineEnd + 1;
 
-               function applyCurrent( current ) {
-                       return function() {
-                               var assert = new Assert( QUnit.config.current );
-                               current.apply( assert, arguments );
-                       };
+                               if ( lineHash.hasOwnProperty ? lineHash.hasOwnProperty( line ) :
+                                                       ( lineHash[ line ] !== undefined ) ) {
+                                       chars += String.fromCharCode( lineHash[ line ] );
+                               } else {
+                                       chars += String.fromCharCode( lineArrayLength );
+                                       lineHash[ line ] = lineArrayLength;
+                                       lineArray[ lineArrayLength++ ] = line;
+                               }
+                       }
+                       return chars;
                }
 
-               for ( i in assertions ) {
-                       QUnit[ i ] = applyCurrent( assertions[ i ] );
+               chars1 = diffLinesToCharsMunge( text1 );
+               chars2 = diffLinesToCharsMunge( text2 );
+               return {
+                       chars1: chars1,
+                       chars2: chars2,
+                       lineArray: lineArray
+               };
+       };
+
+       /**
+        * Rehydrate the text in a diff from a string of line hashes to real lines of
+        * text.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        * @param {!Array.<string>} lineArray Array of unique strings.
+        * @private
+        */
+       DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
+               var x, chars, text, y;
+               for ( x = 0; x < diffs.length; x++ ) {
+                       chars = diffs[ x ][ 1 ];
+                       text = [];
+                       for ( y = 0; y < chars.length; y++ ) {
+                               text[ y ] = lineArray[ chars.charCodeAt( y ) ];
+                       }
+                       diffs[ x ][ 1 ] = text.join( "" );
                }
-       })();
+       };
 
-       (function() {
-               var i, l,
-                       keys = [
-                               "test",
-                               "module",
-                               "expect",
-                               "asyncTest",
-                               "start",
-                               "stop",
-                               "ok",
-                               "notOk",
-                               "equal",
-                               "notEqual",
-                               "propEqual",
-                               "notPropEqual",
-                               "deepEqual",
-                               "notDeepEqual",
-                               "strictEqual",
-                               "notStrictEqual",
-                               "throws"
-                       ];
+       /**
+        * Reorder and merge like edit sections.  Merge equalities.
+        * Any edit section can move as long as it doesn't cross an equality.
+        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+        */
+       DiffMatchPatch.prototype.diffCleanupMerge = function( diffs ) {
+               var pointer, countDelete, countInsert, textInsert, textDelete,
+                       commonlength, changes, diffPointer, position;
+               diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
+               pointer = 0;
+               countDelete = 0;
+               countInsert = 0;
+               textDelete = "";
+               textInsert = "";
+               commonlength;
+               while ( pointer < diffs.length ) {
+                       switch ( diffs[ pointer ][ 0 ] ) {
+                       case DIFF_INSERT:
+                               countInsert++;
+                               textInsert += diffs[ pointer ][ 1 ];
+                               pointer++;
+                               break;
+                       case DIFF_DELETE:
+                               countDelete++;
+                               textDelete += diffs[ pointer ][ 1 ];
+                               pointer++;
+                               break;
+                       case DIFF_EQUAL:
+                               // Upon reaching an equality, check for prior redundancies.
+                               if ( countDelete + countInsert > 1 ) {
+                                       if ( countDelete !== 0 && countInsert !== 0 ) {
+                                               // Factor out any common prefixes.
+                                               commonlength = this.diffCommonPrefix( textInsert, textDelete );
+                                               if ( commonlength !== 0 ) {
+                                                       if ( ( pointer - countDelete - countInsert ) > 0 &&
+                                                                       diffs[ pointer - countDelete - countInsert - 1 ][ 0 ] ===
+                                                                       DIFF_EQUAL ) {
+                                                               diffs[ pointer - countDelete - countInsert - 1 ][ 1 ] +=
+                                                                       textInsert.substring( 0, commonlength );
+                                                       } else {
+                                                               diffs.splice( 0, 0, [ DIFF_EQUAL,
+                                                                       textInsert.substring( 0, commonlength )
+                                                               ] );
+                                                               pointer++;
+                                                       }
+                                                       textInsert = textInsert.substring( commonlength );
+                                                       textDelete = textDelete.substring( commonlength );
+                                               }
+                                               // Factor out any common suffixies.
+                                               commonlength = this.diffCommonSuffix( textInsert, textDelete );
+                                               if ( commonlength !== 0 ) {
+                                                       diffs[ pointer ][ 1 ] = textInsert.substring( textInsert.length -
+                                                                       commonlength ) + diffs[ pointer ][ 1 ];
+                                                       textInsert = textInsert.substring( 0, textInsert.length -
+                                                               commonlength );
+                                                       textDelete = textDelete.substring( 0, textDelete.length -
+                                                               commonlength );
+                                               }
+                                       }
+                                       // Delete the offending records and add the merged ones.
+                                       if ( countDelete === 0 ) {
+                                               diffs.splice( pointer - countInsert,
+                                                       countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
+                                       } else if ( countInsert === 0 ) {
+                                               diffs.splice( pointer - countDelete,
+                                                       countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
+                                       } else {
+                                               diffs.splice(
+                                                       pointer - countDelete - countInsert,
+                                                       countDelete + countInsert,
+                                                       [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ]
+                                               );
+                                       }
+                                       pointer = pointer - countDelete - countInsert +
+                                               ( countDelete ? 1 : 0 ) + ( countInsert ? 1 : 0 ) + 1;
+                               } else if ( pointer !== 0 && diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL ) {
 
-               for ( i = 0, l = keys.length; i < l; i++ ) {
-                       window[ keys[ i ] ] = QUnit[ keys[ i ] ];
+                                       // Merge this equality with the previous one.
+                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer ][ 1 ];
+                                       diffs.splice( pointer, 1 );
+                               } else {
+                                       pointer++;
+                               }
+                               countInsert = 0;
+                               countDelete = 0;
+                               textDelete = "";
+                               textInsert = "";
+                               break;
+                       }
+               }
+               if ( diffs[ diffs.length - 1 ][ 1 ] === "" ) {
+                       diffs.pop(); // Remove the dummy entry at the end.
                }
-       })();
 
-       window.QUnit = QUnit;
-}
+               // Second pass: look for single edits surrounded on both sides by equalities
+               // which can be shifted sideways to eliminate an equality.
+               // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
+               changes = false;
+               pointer = 1;
 
-// For nodejs
-if ( typeof module !== "undefined" && module && module.exports ) {
-       module.exports = QUnit;
+               // Intentionally ignore the first and last element (don't need checking).
+               while ( pointer < diffs.length - 1 ) {
+                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL &&
+                                       diffs[ pointer + 1 ][ 0 ] === DIFF_EQUAL ) {
 
-       // For consistency with CommonJS environments' exports
-       module.exports.QUnit = QUnit;
-}
+                               diffPointer = diffs[ pointer ][ 1 ];
+                               position = diffPointer.substring(
+                                       diffPointer.length - diffs[ pointer - 1 ][ 1 ].length
+                               );
 
-// For CommonJS with exports, but without module.exports, like Rhino
-if ( typeof exports !== "undefined" && exports ) {
-       exports.QUnit = QUnit;
-}
+                               // This is a single edit surrounded by equalities.
+                               if ( position === diffs[ pointer - 1 ][ 1 ] ) {
+
+                                       // Shift the edit over the previous equality.
+                                       diffs[ pointer ][ 1 ] = diffs[ pointer - 1 ][ 1 ] +
+                                               diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer ][ 1 ].length -
+                                                       diffs[ pointer - 1 ][ 1 ].length );
+                                       diffs[ pointer + 1 ][ 1 ] =
+                                               diffs[ pointer - 1 ][ 1 ] + diffs[ pointer + 1 ][ 1 ];
+                                       diffs.splice( pointer - 1, 1 );
+                                       changes = true;
+                               } else if ( diffPointer.substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
+                                               diffs[ pointer + 1 ][ 1 ] ) {
+
+                                       // Shift the edit over the next equality.
+                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer + 1 ][ 1 ];
+                                       diffs[ pointer ][ 1 ] =
+                                               diffs[ pointer ][ 1 ].substring( diffs[ pointer + 1 ][ 1 ].length ) +
+                                               diffs[ pointer + 1 ][ 1 ];
+                                       diffs.splice( pointer + 1, 1 );
+                                       changes = true;
+                               }
+                       }
+                       pointer++;
+               }
+               // If shifts were made, the diff needs reordering and another shift sweep.
+               if ( changes ) {
+                       this.diffCleanupMerge( diffs );
+               }
+       };
 
-if ( typeof define === "function" && define.amd ) {
-       define( function() {
-               return QUnit;
-       } );
-       QUnit.config.autostart = false;
-}
+       return function( o, n ) {
+               var diff, output, text;
+               diff = new DiffMatchPatch();
+               output = diff.DiffMain( o, n );
+               diff.diffCleanupEfficiency( output );
+               text = diff.diffPrettyHtml( output );
+
+               return text;
+       };
+}() );
 
 // Get a reference to the global object, like window in browsers
 }( (function() {
        return this;
 })() ));
 
-/*istanbul ignore next */
-// jscs:disable maximumLineLength
-/*
- * This file is a modified version of google-diff-match-patch's JavaScript implementation
- * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
- * modifications are licensed as more fully set forth in LICENSE.txt.
- *
- * The original source of google-diff-match-patch is attributable and licensed as follows:
- *
- * Copyright 2006 Google Inc.
- * http://code.google.com/p/google-diff-match-patch/
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * More Info:
- *  https://code.google.com/p/google-diff-match-patch/
- *
- * Usage: QUnit.diff(expected, actual)
- *
- * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) === "the  quick <del>brown </del> fox jump<ins>s</ins><del>ed</del over"
- */
-QUnit.diff = (function() {
-
-    function DiffMatchPatch() {
-
-        // Defaults.
-        // Redefine these in your program to override the defaults.
-
-        // Number of seconds to map a diff before giving up (0 for infinity).
-        this.DiffTimeout = 1.0;
-        // Cost of an empty edit operation in terms of edit characters.
-        this.DiffEditCost = 4;
-    }
-
-    //  DIFF FUNCTIONS
-
-    /**
-     * The data structure representing a diff is an array of tuples:
-     * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
-     * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
-     */
-    var DIFF_DELETE = -1,
-               DIFF_INSERT = 1,
-               DIFF_EQUAL = 0;
-
-    /**
-     * Find the differences between two texts.  Simplifies the problem by stripping
-     * any common prefix or suffix off the texts before diffing.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {boolean=} optChecklines Optional speedup flag. If present and false,
-     *     then don't run a line-level diff first to identify the changed areas.
-     *     Defaults to true, which does a faster, slightly less optimal diff.
-     * @param {number} optDeadline Optional time when the diff should be complete
-     *     by.  Used internally for recursive calls.  Users should set DiffTimeout
-     *     instead.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines, optDeadline ) {
-        var deadline, checklines, commonlength,
-                       commonprefix, commonsuffix, diffs;
-        // Set a deadline by which time the diff must be complete.
-        if ( typeof optDeadline === "undefined" ) {
-            if ( this.DiffTimeout <= 0 ) {
-                optDeadline = Number.MAX_VALUE;
-            } else {
-                optDeadline = ( new Date() ).getTime() + this.DiffTimeout * 1000;
-            }
-        }
-        deadline = optDeadline;
-
-        // Check for null inputs.
-        if ( text1 === null || text2 === null ) {
-            throw new Error( "Null input. (DiffMain)" );
-        }
-
-        // Check for equality (speedup).
-        if ( text1 === text2 ) {
-            if ( text1 ) {
-                return [
-                    [ DIFF_EQUAL, text1 ]
-                ];
-            }
-            return [];
-        }
-
-        if ( typeof optChecklines === "undefined" ) {
-            optChecklines = true;
-        }
-
-        checklines = optChecklines;
-
-        // Trim off common prefix (speedup).
-        commonlength = this.diffCommonPrefix( text1, text2 );
-        commonprefix = text1.substring( 0, commonlength );
-        text1 = text1.substring( commonlength );
-        text2 = text2.substring( commonlength );
-
-        // Trim off common suffix (speedup).
-        /////////
-        commonlength = this.diffCommonSuffix( text1, text2 );
-        commonsuffix = text1.substring( text1.length - commonlength );
-        text1 = text1.substring( 0, text1.length - commonlength );
-        text2 = text2.substring( 0, text2.length - commonlength );
-
-        // Compute the diff on the middle block.
-        diffs = this.diffCompute( text1, text2, checklines, deadline );
-
-        // Restore the prefix and suffix.
-        if ( commonprefix ) {
-            diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
-        }
-        if ( commonsuffix ) {
-            diffs.push( [ DIFF_EQUAL, commonsuffix ] );
-        }
-        this.diffCleanupMerge( diffs );
-        return diffs;
-    };
-
-    /**
-     * Reduce the number of edits by eliminating operationally trivial equalities.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
-        var changes, equalities, equalitiesLength, lastequality,
-                       pointer, preIns, preDel, postIns, postDel;
-        changes = false;
-        equalities = []; // Stack of indices where equalities are found.
-        equalitiesLength = 0; // Keeping our own length var is faster in JS.
-        /** @type {?string} */
-        lastequality = null;
-        // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-        pointer = 0; // Index of current position.
-        // Is there an insertion operation before the last equality.
-        preIns = false;
-        // Is there a deletion operation before the last equality.
-        preDel = false;
-        // Is there an insertion operation after the last equality.
-        postIns = false;
-        // Is there a deletion operation after the last equality.
-        postDel = false;
-        while ( pointer < diffs.length ) {
-            if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
-                if ( diffs[ pointer ][ 1 ].length < this.DiffEditCost && ( postIns || postDel ) ) {
-                    // Candidate found.
-                    equalities[ equalitiesLength++ ] = pointer;
-                    preIns = postIns;
-                    preDel = postDel;
-                    lastequality = diffs[ pointer ][ 1 ];
-                } else {
-                    // Not a candidate, and can never become one.
-                    equalitiesLength = 0;
-                    lastequality = null;
-                }
-                postIns = postDel = false;
-            } else { // An insertion or deletion.
-                if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
-                    postDel = true;
-                } else {
-                    postIns = true;
-                }
-                /*
-                 * Five types to be split:
-                 * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
-                 * <ins>A</ins>X<ins>C</ins><del>D</del>
-                 * <ins>A</ins><del>B</del>X<ins>C</ins>
-                 * <ins>A</del>X<ins>C</ins><del>D</del>
-                 * <ins>A</ins><del>B</del>X<del>C</del>
-                 */
-                if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
-                        ( ( lastequality.length < this.DiffEditCost / 2 ) &&
-                            ( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
-                    // Duplicate record.
-                    diffs.splice( equalities[equalitiesLength - 1], 0, [ DIFF_DELETE, lastequality ] );
-                    // Change second copy to insert.
-                    diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
-                    equalitiesLength--; // Throw away the equality we just deleted;
-                    lastequality = null;
-                    if (preIns && preDel) {
-                        // No changes made which could affect previous entry, keep going.
-                        postIns = postDel = true;
-                        equalitiesLength = 0;
-                    } else {
-                        equalitiesLength--; // Throw away the previous equality.
-                        pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
-                        postIns = postDel = false;
-                    }
-                    changes = true;
-                }
-            }
-            pointer++;
-        }
-
-        if ( changes ) {
-            this.diffCleanupMerge( diffs );
-        }
-    };
-
-    /**
-     * Convert a diff array into a pretty HTML report.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     * @param {integer} string to be beautified.
-     * @return {string} HTML representation.
-     */
-    DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
-        var op, data, x, html = [];
-        for ( x = 0; x < diffs.length; x++ ) {
-            op = diffs[x][0]; // Operation (insert, delete, equal)
-            data = diffs[x][1]; // Text of change.
-            switch ( op ) {
-                case DIFF_INSERT:
-                    html[x] = "<ins>" + data + "</ins>";
-                    break;
-                case DIFF_DELETE:
-                    html[x] = "<del>" + data + "</del>";
-                    break;
-                case DIFF_EQUAL:
-                    html[x] = "<span>" + data + "</span>";
-                    break;
-            }
-        }
-        return html.join("");
-    };
-
-    /**
-     * Determine the common prefix of two strings.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {number} The number of characters common to the start of each
-     *     string.
-     */
-    DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
-        var pointermid, pointermax, pointermin, pointerstart;
-        // Quick check for common null cases.
-        if ( !text1 || !text2 || text1.charAt(0) !== text2.charAt(0) ) {
-            return 0;
-        }
-        // Binary search.
-        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
-        pointermin = 0;
-        pointermax = Math.min( text1.length, text2.length );
-        pointermid = pointermax;
-        pointerstart = 0;
-        while ( pointermin < pointermid ) {
-            if ( text1.substring( pointerstart, pointermid ) === text2.substring( pointerstart, pointermid ) ) {
-                pointermin = pointermid;
-                pointerstart = pointermin;
-            } else {
-                pointermax = pointermid;
-            }
-            pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
-        }
-        return pointermid;
-    };
-
-    /**
-     * Determine the common suffix of two strings.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {number} The number of characters common to the end of each string.
-     */
-    DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
-        var pointermid, pointermax, pointermin, pointerend;
-        // Quick check for common null cases.
-        if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) {
-            return 0;
-        }
-        // Binary search.
-        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
-        pointermin = 0;
-        pointermax = Math.min(text1.length, text2.length);
-        pointermid = pointermax;
-        pointerend = 0;
-        while ( pointermin < pointermid ) {
-            if (text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
-                text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
-                pointermin = pointermid;
-                pointerend = pointermin;
-            } else {
-                pointermax = pointermid;
-            }
-            pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
-        }
-        return pointermid;
-    };
-
-    /**
-     * Find the differences between two texts.  Assumes that the texts do not
-     * have any common prefix or suffix.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {boolean} checklines Speedup flag.  If false, then don't run a
-     *     line-level diff first to identify the changed areas.
-     *     If true, then run a faster, slightly less optimal diff.
-     * @param {number} deadline Time when the diff should be complete by.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
-        var diffs, longtext, shorttext, i, hm,
-                       text1A, text2A, text1B, text2B,
-                       midCommon, diffsA, diffsB;
-
-        if ( !text1 ) {
-            // Just add some text (speedup).
-            return [
-                [ DIFF_INSERT, text2 ]
-            ];
-        }
-
-        if (!text2) {
-            // Just delete some text (speedup).
-            return [
-                [ DIFF_DELETE, text1 ]
-            ];
-        }
-
-        longtext = text1.length > text2.length ? text1 : text2;
-        shorttext = text1.length > text2.length ? text2 : text1;
-        i = longtext.indexOf( shorttext );
-        if ( i !== -1 ) {
-            // Shorter text is inside the longer text (speedup).
-            diffs = [
-                [ DIFF_INSERT, longtext.substring( 0, i ) ],
-                [ DIFF_EQUAL, shorttext ],
-                [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
-            ];
-            // Swap insertions for deletions if diff is reversed.
-            if ( text1.length > text2.length ) {
-                diffs[0][0] = diffs[2][0] = DIFF_DELETE;
-            }
-            return diffs;
-        }
-
-        if ( shorttext.length === 1 ) {
-            // Single character string.
-            // After the previous speedup, the character can't be an equality.
-            return [
-                [ DIFF_DELETE, text1 ],
-                [ DIFF_INSERT, text2 ]
-            ];
-        }
-
-        // Check to see if the problem can be split in two.
-        hm = this.diffHalfMatch(text1, text2);
-        if (hm) {
-            // A half-match was found, sort out the return data.
-            text1A = hm[0];
-            text1B = hm[1];
-            text2A = hm[2];
-            text2B = hm[3];
-            midCommon = hm[4];
-            // Send both pairs off for separate processing.
-            diffsA = this.DiffMain(text1A, text2A, checklines, deadline);
-            diffsB = this.DiffMain(text1B, text2B, checklines, deadline);
-            // Merge the results.
-            return diffsA.concat([
-                [ DIFF_EQUAL, midCommon ]
-            ], diffsB);
-        }
-
-        if (checklines && text1.length > 100 && text2.length > 100) {
-            return this.diffLineMode(text1, text2, deadline);
-        }
-
-        return this.diffBisect(text1, text2, deadline);
-    };
-
-    /**
-     * Do the two texts share a substring which is at least half the length of the
-     * longer text?
-     * This speedup can produce non-minimal diffs.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {Array.<string>} Five element Array, containing the prefix of
-     *     text1, the suffix of text1, the prefix of text2, the suffix of
-     *     text2 and the common middle.  Or null if there was no match.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffHalfMatch = function(text1, text2) {
-        var longtext, shorttext, dmp,
-                       text1A, text2B, text2A, text1B, midCommon,
-                       hm1, hm2, hm;
-        if (this.DiffTimeout <= 0) {
-            // Don't risk returning a non-optimal diff if we have unlimited time.
-            return null;
-        }
-        longtext = text1.length > text2.length ? text1 : text2;
-        shorttext = text1.length > text2.length ? text2 : text1;
-        if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
-            return null; // Pointless.
-        }
-        dmp = this; // 'this' becomes 'window' in a closure.
-
-        /**
-         * Does a substring of shorttext exist within longtext such that the substring
-         * is at least half the length of longtext?
-         * Closure, but does not reference any external variables.
-         * @param {string} longtext Longer string.
-         * @param {string} shorttext Shorter string.
-         * @param {number} i Start index of quarter length substring within longtext.
-         * @return {Array.<string>} Five element Array, containing the prefix of
-         *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
-         *     of shorttext and the common middle.  Or null if there was no match.
-         * @private
-         */
-        function diffHalfMatchI(longtext, shorttext, i) {
-            var seed, j, bestCommon, prefixLength, suffixLength,
-                               bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
-            // Start with a 1/4 length substring at position i as a seed.
-            seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
-            j = -1;
-            bestCommon = "";
-            while ((j = shorttext.indexOf(seed, j + 1)) !== -1) {
-                prefixLength = dmp.diffCommonPrefix(longtext.substring(i),
-                    shorttext.substring(j));
-                suffixLength = dmp.diffCommonSuffix(longtext.substring(0, i),
-                    shorttext.substring(0, j));
-                if (bestCommon.length < suffixLength + prefixLength) {
-                    bestCommon = shorttext.substring(j - suffixLength, j) +
-                        shorttext.substring(j, j + prefixLength);
-                    bestLongtextA = longtext.substring(0, i - suffixLength);
-                    bestLongtextB = longtext.substring(i + prefixLength);
-                    bestShorttextA = shorttext.substring(0, j - suffixLength);
-                    bestShorttextB = shorttext.substring(j + prefixLength);
-                }
-            }
-            if (bestCommon.length * 2 >= longtext.length) {
-                return [ bestLongtextA, bestLongtextB,
-                    bestShorttextA, bestShorttextB, bestCommon
-                ];
-            } else {
-                return null;
-            }
-        }
-
-        // First check if the second quarter is the seed for a half-match.
-        hm1 = diffHalfMatchI(longtext, shorttext,
-            Math.ceil(longtext.length / 4));
-        // Check again based on the third quarter.
-        hm2 = diffHalfMatchI(longtext, shorttext,
-            Math.ceil(longtext.length / 2));
-        if (!hm1 && !hm2) {
-            return null;
-        } else if (!hm2) {
-            hm = hm1;
-        } else if (!hm1) {
-            hm = hm2;
-        } else {
-            // Both matched.  Select the longest.
-            hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
-        }
-
-        // A half-match was found, sort out the return data.
-        text1A, text1B, text2A, text2B;
-        if (text1.length > text2.length) {
-            text1A = hm[0];
-            text1B = hm[1];
-            text2A = hm[2];
-            text2B = hm[3];
-        } else {
-            text2A = hm[0];
-            text2B = hm[1];
-            text1A = hm[2];
-            text1B = hm[3];
-        }
-        midCommon = hm[4];
-        return [ text1A, text1B, text2A, text2B, midCommon ];
-    };
-
-    /**
-     * Do a quick line-level diff on both strings, then rediff the parts for
-     * greater accuracy.
-     * This speedup can produce non-minimal diffs.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {number} deadline Time when the diff should be complete by.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffLineMode = function(text1, text2, deadline) {
-        var a, diffs, linearray, pointer, countInsert,
-                       countDelete, textInsert, textDelete, j;
-        // Scan the text on a line-by-line basis first.
-        a = this.diffLinesToChars(text1, text2);
-        text1 = a.chars1;
-        text2 = a.chars2;
-        linearray = a.lineArray;
-
-        diffs = this.DiffMain(text1, text2, false, deadline);
-
-        // Convert the diff back to original text.
-        this.diffCharsToLines(diffs, linearray);
-        // Eliminate freak matches (e.g. blank lines)
-        this.diffCleanupSemantic(diffs);
-
-        // Rediff any replacement blocks, this time character-by-character.
-        // Add a dummy entry at the end.
-        diffs.push( [ DIFF_EQUAL, "" ] );
-        pointer = 0;
-        countDelete = 0;
-        countInsert = 0;
-        textDelete = "";
-        textInsert = "";
-        while (pointer < diffs.length) {
-            switch ( diffs[pointer][0] ) {
-                case DIFF_INSERT:
-                    countInsert++;
-                    textInsert += diffs[pointer][1];
-                    break;
-                case DIFF_DELETE:
-                    countDelete++;
-                    textDelete += diffs[pointer][1];
-                    break;
-                case DIFF_EQUAL:
-                    // Upon reaching an equality, check for prior redundancies.
-                    if (countDelete >= 1 && countInsert >= 1) {
-                        // Delete the offending records and add the merged ones.
-                        diffs.splice(pointer - countDelete - countInsert,
-                            countDelete + countInsert);
-                        pointer = pointer - countDelete - countInsert;
-                        a = this.DiffMain(textDelete, textInsert, false, deadline);
-                        for (j = a.length - 1; j >= 0; j--) {
-                            diffs.splice( pointer, 0, a[j] );
-                        }
-                        pointer = pointer + a.length;
-                    }
-                    countInsert = 0;
-                    countDelete = 0;
-                    textDelete = "";
-                    textInsert = "";
-                    break;
-            }
-            pointer++;
-        }
-        diffs.pop(); // Remove the dummy entry at the end.
-
-        return diffs;
-    };
-
-    /**
-     * Find the 'middle snake' of a diff, split the problem in two
-     * and return the recursively constructed diff.
-     * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {number} deadline Time at which to bail if not yet complete.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffBisect = function(text1, text2, deadline) {
-        var text1Length, text2Length, maxD, vOffset, vLength,
-                       v1, v2, x, delta, front, k1start, k1end, k2start,
-                       k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
-        // Cache the text lengths to prevent multiple calls.
-        text1Length = text1.length;
-        text2Length = text2.length;
-        maxD = Math.ceil((text1Length + text2Length) / 2);
-        vOffset = maxD;
-        vLength = 2 * maxD;
-        v1 = new Array(vLength);
-        v2 = new Array(vLength);
-        // Setting all elements to -1 is faster in Chrome & Firefox than mixing
-        // integers and undefined.
-        for (x = 0; x < vLength; x++) {
-            v1[x] = -1;
-            v2[x] = -1;
-        }
-        v1[vOffset + 1] = 0;
-        v2[vOffset + 1] = 0;
-        delta = text1Length - text2Length;
-        // If the total number of characters is odd, then the front path will collide
-        // with the reverse path.
-        front = (delta % 2 !== 0);
-        // Offsets for start and end of k loop.
-        // Prevents mapping of space beyond the grid.
-        k1start = 0;
-        k1end = 0;
-        k2start = 0;
-        k2end = 0;
-        for (d = 0; d < maxD; d++) {
-            // Bail out if deadline is reached.
-            if ((new Date()).getTime() > deadline) {
-                break;
-            }
-
-            // Walk the front path one step.
-            for (k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
-                k1Offset = vOffset + k1;
-                if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
-                    x1 = v1[k1Offset + 1];
-                } else {
-                    x1 = v1[k1Offset - 1] + 1;
-                }
-                y1 = x1 - k1;
-                while (x1 < text1Length && y1 < text2Length &&
-                    text1.charAt(x1) === text2.charAt(y1)) {
-                    x1++;
-                    y1++;
-                }
-                v1[k1Offset] = x1;
-                if (x1 > text1Length) {
-                    // Ran off the right of the graph.
-                    k1end += 2;
-                } else if (y1 > text2Length) {
-                    // Ran off the bottom of the graph.
-                    k1start += 2;
-                } else if (front) {
-                    k2Offset = vOffset + delta - k1;
-                    if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
-                        // Mirror x2 onto top-left coordinate system.
-                        x2 = text1Length - v2[k2Offset];
-                        if (x1 >= x2) {
-                            // Overlap detected.
-                            return this.diffBisectSplit(text1, text2, x1, y1, deadline);
-                        }
-                    }
-                }
-            }
-
-            // Walk the reverse path one step.
-            for (k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
-                k2Offset = vOffset + k2;
-                if ( k2 === -d || (k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
-                    x2 = v2[k2Offset + 1];
-                } else {
-                    x2 = v2[k2Offset - 1] + 1;
-                }
-                y2 = x2 - k2;
-                while (x2 < text1Length && y2 < text2Length &&
-                    text1.charAt(text1Length - x2 - 1) ===
-                    text2.charAt(text2Length - y2 - 1)) {
-                    x2++;
-                    y2++;
-                }
-                v2[k2Offset] = x2;
-                if (x2 > text1Length) {
-                    // Ran off the left of the graph.
-                    k2end += 2;
-                } else if (y2 > text2Length) {
-                    // Ran off the top of the graph.
-                    k2start += 2;
-                } else if (!front) {
-                    k1Offset = vOffset + delta - k2;
-                    if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
-                        x1 = v1[k1Offset];
-                        y1 = vOffset + x1 - k1Offset;
-                        // Mirror x2 onto top-left coordinate system.
-                        x2 = text1Length - x2;
-                        if (x1 >= x2) {
-                            // Overlap detected.
-                            return this.diffBisectSplit(text1, text2, x1, y1, deadline);
-                        }
-                    }
-                }
-            }
-        }
-        // Diff took too long and hit the deadline or
-        // number of diffs equals number of characters, no commonality at all.
-        return [
-            [ DIFF_DELETE, text1 ],
-            [ DIFF_INSERT, text2 ]
-        ];
-    };
-
-    /**
-     * Given the location of the 'middle snake', split the diff in two parts
-     * and recurse.
-     * @param {string} text1 Old string to be diffed.
-     * @param {string} text2 New string to be diffed.
-     * @param {number} x Index of split point in text1.
-     * @param {number} y Index of split point in text2.
-     * @param {number} deadline Time at which to bail if not yet complete.
-     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
-        var text1a, text1b, text2a, text2b, diffs, diffsb;
-        text1a = text1.substring(0, x);
-        text2a = text2.substring(0, y);
-        text1b = text1.substring(x);
-        text2b = text2.substring(y);
-
-        // Compute both diffs serially.
-        diffs = this.DiffMain(text1a, text2a, false, deadline);
-        diffsb = this.DiffMain(text1b, text2b, false, deadline);
-
-        return diffs.concat(diffsb);
-    };
-
-    /**
-     * Reduce the number of edits by eliminating semantically trivial equalities.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.diffCleanupSemantic = function(diffs) {
-        var changes, equalities, equalitiesLength, lastequality,
-                       pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
-                       lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
-        changes = false;
-        equalities = []; // Stack of indices where equalities are found.
-        equalitiesLength = 0; // Keeping our own length var is faster in JS.
-        /** @type {?string} */
-        lastequality = null;
-        // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-        pointer = 0; // Index of current position.
-        // Number of characters that changed prior to the equality.
-        lengthInsertions1 = 0;
-        lengthDeletions1 = 0;
-        // Number of characters that changed after the equality.
-        lengthInsertions2 = 0;
-        lengthDeletions2 = 0;
-        while (pointer < diffs.length) {
-            if (diffs[pointer][0] === DIFF_EQUAL) { // Equality found.
-                equalities[equalitiesLength++] = pointer;
-                lengthInsertions1 = lengthInsertions2;
-                lengthDeletions1 = lengthDeletions2;
-                lengthInsertions2 = 0;
-                lengthDeletions2 = 0;
-                lastequality = diffs[pointer][1];
-            } else { // An insertion or deletion.
-                if (diffs[pointer][0] === DIFF_INSERT) {
-                    lengthInsertions2 += diffs[pointer][1].length;
-                } else {
-                    lengthDeletions2 += diffs[pointer][1].length;
-                }
-                // Eliminate an equality that is smaller or equal to the edits on both
-                // sides of it.
-                if (lastequality && (lastequality.length <=
-                        Math.max(lengthInsertions1, lengthDeletions1)) &&
-                    (lastequality.length <= Math.max(lengthInsertions2,
-                        lengthDeletions2))) {
-                    // Duplicate record.
-                    diffs.splice( equalities[ equalitiesLength - 1 ], 0, [ DIFF_DELETE, lastequality ] );
-                    // Change second copy to insert.
-                    diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
-                    // Throw away the equality we just deleted.
-                    equalitiesLength--;
-                    // Throw away the previous equality (it needs to be reevaluated).
-                    equalitiesLength--;
-                    pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
-                    lengthInsertions1 = 0; // Reset the counters.
-                    lengthDeletions1 = 0;
-                    lengthInsertions2 = 0;
-                    lengthDeletions2 = 0;
-                    lastequality = null;
-                    changes = true;
-                }
-            }
-            pointer++;
-        }
-
-        // Normalize the diff.
-        if (changes) {
-            this.diffCleanupMerge(diffs);
-        }
-
-        // Find any overlaps between deletions and insertions.
-        // e.g: <del>abcxxx</del><ins>xxxdef</ins>
-        //   -> <del>abc</del>xxx<ins>def</ins>
-        // e.g: <del>xxxabc</del><ins>defxxx</ins>
-        //   -> <ins>def</ins>xxx<del>abc</del>
-        // Only extract an overlap if it is as big as the edit ahead or behind it.
-        pointer = 1;
-        while (pointer < diffs.length) {
-            if (diffs[pointer - 1][0] === DIFF_DELETE &&
-                diffs[pointer][0] === DIFF_INSERT) {
-                deletion = diffs[pointer - 1][1];
-                insertion = diffs[pointer][1];
-                overlapLength1 = this.diffCommonOverlap(deletion, insertion);
-                overlapLength2 = this.diffCommonOverlap(insertion, deletion);
-                if (overlapLength1 >= overlapLength2) {
-                    if (overlapLength1 >= deletion.length / 2 ||
-                        overlapLength1 >= insertion.length / 2) {
-                        // Overlap found.  Insert an equality and trim the surrounding edits.
-                        diffs.splice( pointer, 0, [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ] );
-                        diffs[pointer - 1][1] =
-                            deletion.substring(0, deletion.length - overlapLength1);
-                        diffs[pointer + 1][1] = insertion.substring(overlapLength1);
-                        pointer++;
-                    }
-                } else {
-                    if (overlapLength2 >= deletion.length / 2 ||
-                        overlapLength2 >= insertion.length / 2) {
-                        // Reverse overlap found.
-                        // Insert an equality and swap and trim the surrounding edits.
-                        diffs.splice( pointer, 0, [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ] );
-                        diffs[pointer - 1][0] = DIFF_INSERT;
-                        diffs[pointer - 1][1] =
-                            insertion.substring(0, insertion.length - overlapLength2);
-                        diffs[pointer + 1][0] = DIFF_DELETE;
-                        diffs[pointer + 1][1] =
-                            deletion.substring(overlapLength2);
-                        pointer++;
-                    }
-                }
-                pointer++;
-            }
-            pointer++;
-        }
-    };
-
-    /**
-     * Determine if the suffix of one string is the prefix of another.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {number} The number of characters common to the end of the first
-     *     string and the start of the second string.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffCommonOverlap = function(text1, text2) {
-        var text1Length, text2Length, textLength,
-                       best, length, pattern, found;
-        // Cache the text lengths to prevent multiple calls.
-        text1Length = text1.length;
-        text2Length = text2.length;
-        // Eliminate the null case.
-        if (text1Length === 0 || text2Length === 0) {
-            return 0;
-        }
-        // Truncate the longer string.
-        if (text1Length > text2Length) {
-            text1 = text1.substring(text1Length - text2Length);
-        } else if (text1Length < text2Length) {
-            text2 = text2.substring(0, text1Length);
-        }
-        textLength = Math.min(text1Length, text2Length);
-        // Quick check for the worst case.
-        if (text1 === text2) {
-            return textLength;
-        }
-
-        // Start by looking for a single character match
-        // and increase length until no match is found.
-        // Performance analysis: http://neil.fraser.name/news/2010/11/04/
-        best = 0;
-        length = 1;
-        while (true) {
-            pattern = text1.substring(textLength - length);
-            found = text2.indexOf(pattern);
-            if (found === -1) {
-                return best;
-            }
-            length += found;
-            if (found === 0 || text1.substring(textLength - length) ===
-                text2.substring(0, length)) {
-                best = length;
-                length++;
-            }
-        }
-    };
-
-    /**
-     * Split two texts into an array of strings.  Reduce the texts to a string of
-     * hashes where each Unicode character represents one line.
-     * @param {string} text1 First string.
-     * @param {string} text2 Second string.
-     * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
-     *     An object containing the encoded text1, the encoded text2 and
-     *     the array of unique strings.
-     *     The zeroth element of the array of unique strings is intentionally blank.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffLinesToChars = function(text1, text2) {
-        var lineArray, lineHash, chars1, chars2;
-        lineArray = []; // e.g. lineArray[4] === 'Hello\n'
-        lineHash = {}; // e.g. lineHash['Hello\n'] === 4
-
-        // '\x00' is a valid character, but various debuggers don't like it.
-        // So we'll insert a junk entry to avoid generating a null character.
-        lineArray[0] = "";
-
-        /**
-         * Split a text into an array of strings.  Reduce the texts to a string of
-         * hashes where each Unicode character represents one line.
-         * Modifies linearray and linehash through being a closure.
-         * @param {string} text String to encode.
-         * @return {string} Encoded string.
-         * @private
-         */
-        function diffLinesToCharsMunge(text) {
-            var chars, lineStart, lineEnd, lineArrayLength, line;
-            chars = "";
-            // Walk the text, pulling out a substring for each line.
-            // text.split('\n') would would temporarily double our memory footprint.
-            // Modifying text would create many large strings to garbage collect.
-            lineStart = 0;
-            lineEnd = -1;
-            // Keeping our own length variable is faster than looking it up.
-            lineArrayLength = lineArray.length;
-            while (lineEnd < text.length - 1) {
-                lineEnd = text.indexOf("\n", lineStart);
-                if (lineEnd === -1) {
-                    lineEnd = text.length - 1;
-                }
-                line = text.substring(lineStart, lineEnd + 1);
-                lineStart = lineEnd + 1;
-
-                if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :
-                    (lineHash[line] !== undefined)) {
-                    chars += String.fromCharCode( lineHash[ line ] );
-                } else {
-                    chars += String.fromCharCode(lineArrayLength);
-                    lineHash[line] = lineArrayLength;
-                    lineArray[lineArrayLength++] = line;
-                }
-            }
-            return chars;
-        }
-
-        chars1 = diffLinesToCharsMunge(text1);
-        chars2 = diffLinesToCharsMunge(text2);
-        return {
-            chars1: chars1,
-            chars2: chars2,
-            lineArray: lineArray
-        };
-    };
-
-    /**
-     * Rehydrate the text in a diff from a string of line hashes to real lines of
-     * text.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     * @param {!Array.<string>} lineArray Array of unique strings.
-     * @private
-     */
-    DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
-        var x, chars, text, y;
-        for ( x = 0; x < diffs.length; x++ ) {
-            chars = diffs[x][1];
-            text = [];
-            for ( y = 0; y < chars.length; y++ ) {
-                text[y] = lineArray[chars.charCodeAt(y)];
-            }
-            diffs[x][1] = text.join("");
-        }
-    };
-
-    /**
-     * Reorder and merge like edit sections.  Merge equalities.
-     * Any edit section can move as long as it doesn't cross an equality.
-     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-     */
-    DiffMatchPatch.prototype.diffCleanupMerge = function(diffs) {
-        var pointer, countDelete, countInsert, textInsert, textDelete,
-                       commonlength, changes;
-        diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
-        pointer = 0;
-        countDelete = 0;
-        countInsert = 0;
-        textDelete = "";
-        textInsert = "";
-        commonlength;
-        while (pointer < diffs.length) {
-            switch ( diffs[ pointer ][ 0 ] ) {
-                case DIFF_INSERT:
-                    countInsert++;
-                    textInsert += diffs[pointer][1];
-                    pointer++;
-                    break;
-                case DIFF_DELETE:
-                    countDelete++;
-                    textDelete += diffs[pointer][1];
-                    pointer++;
-                    break;
-                case DIFF_EQUAL:
-                    // Upon reaching an equality, check for prior redundancies.
-                    if (countDelete + countInsert > 1) {
-                        if (countDelete !== 0 && countInsert !== 0) {
-                            // Factor out any common prefixies.
-                            commonlength = this.diffCommonPrefix(textInsert, textDelete);
-                            if (commonlength !== 0) {
-                                if ((pointer - countDelete - countInsert) > 0 &&
-                                    diffs[pointer - countDelete - countInsert - 1][0] ===
-                                    DIFF_EQUAL) {
-                                    diffs[pointer - countDelete - countInsert - 1][1] +=
-                                        textInsert.substring(0, commonlength);
-                                } else {
-                                    diffs.splice( 0, 0, [ DIFF_EQUAL,
-                                        textInsert.substring( 0, commonlength )
-                                     ] );
-                                    pointer++;
-                                }
-                                textInsert = textInsert.substring(commonlength);
-                                textDelete = textDelete.substring(commonlength);
-                            }
-                            // Factor out any common suffixies.
-                            commonlength = this.diffCommonSuffix(textInsert, textDelete);
-                            if (commonlength !== 0) {
-                                diffs[pointer][1] = textInsert.substring(textInsert.length -
-                                    commonlength) + diffs[pointer][1];
-                                textInsert = textInsert.substring(0, textInsert.length -
-                                    commonlength);
-                                textDelete = textDelete.substring(0, textDelete.length -
-                                    commonlength);
-                            }
-                        }
-                        // Delete the offending records and add the merged ones.
-                        if (countDelete === 0) {
-                            diffs.splice( pointer - countInsert,
-                                countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
-                        } else if (countInsert === 0) {
-                            diffs.splice( pointer - countDelete,
-                                countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
-                        } else {
-                            diffs.splice( pointer - countDelete - countInsert,
-                                countDelete + countInsert, [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ] );
-                        }
-                        pointer = pointer - countDelete - countInsert +
-                            (countDelete ? 1 : 0) + (countInsert ? 1 : 0) + 1;
-                    } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
-                        // Merge this equality with the previous one.
-                        diffs[pointer - 1][1] += diffs[pointer][1];
-                        diffs.splice(pointer, 1);
-                    } else {
-                        pointer++;
-                    }
-                    countInsert = 0;
-                    countDelete = 0;
-                    textDelete = "";
-                    textInsert = "";
-                    break;
-            }
-        }
-        if (diffs[diffs.length - 1][1] === "") {
-            diffs.pop(); // Remove the dummy entry at the end.
-        }
-
-        // Second pass: look for single edits surrounded on both sides by equalities
-        // which can be shifted sideways to eliminate an equality.
-        // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
-        changes = false;
-        pointer = 1;
-        // Intentionally ignore the first and last element (don't need checking).
-        while (pointer < diffs.length - 1) {
-            if (diffs[pointer - 1][0] === DIFF_EQUAL &&
-                diffs[pointer + 1][0] === DIFF_EQUAL) {
-                // This is a single edit surrounded by equalities.
-                if ( diffs[ pointer ][ 1 ].substring( diffs[ pointer ][ 1 ].length -
-                        diffs[ pointer - 1 ][ 1 ].length ) === diffs[ pointer - 1 ][ 1 ] ) {
-                    // Shift the edit over the previous equality.
-                    diffs[pointer][1] = diffs[pointer - 1][1] +
-                        diffs[pointer][1].substring(0, diffs[pointer][1].length -
-                            diffs[pointer - 1][1].length);
-                    diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
-                    diffs.splice(pointer - 1, 1);
-                    changes = true;
-                } else if ( diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
-                    diffs[ pointer + 1 ][ 1 ] ) {
-                    // Shift the edit over the next equality.
-                    diffs[pointer - 1][1] += diffs[pointer + 1][1];
-                    diffs[pointer][1] =
-                        diffs[pointer][1].substring(diffs[pointer + 1][1].length) +
-                        diffs[pointer + 1][1];
-                    diffs.splice(pointer + 1, 1);
-                    changes = true;
-                }
-            }
-            pointer++;
-        }
-        // If shifts were made, the diff needs reordering and another shift sweep.
-        if (changes) {
-            this.diffCleanupMerge(diffs);
-        }
-    };
-
-    return function(o, n) {
-               var diff, output, text;
-        diff = new DiffMatchPatch();
-        output = diff.DiffMain(o, n);
-        //console.log(output);
-        diff.diffCleanupEfficiency(output);
-        text = diff.diffPrettyHtml(output);
-
-        return text;
-    };
-}());
-// jscs:enable
-
 (function() {
 
+// Don't load the HTML Reporter on non-Browser environments
+if ( typeof window === "undefined" || !window.document ) {
+       return;
+}
+
 // Deprecated QUnit.init - Ref #530
 // Re-initialize the configuration options
 QUnit.init = function() {
@@ -3115,12 +3427,8 @@ QUnit.init = function() {
        }
 };
 
-// Don't load the HTML Reporter on non-Browser environments
-if ( typeof window === "undefined" ) {
-       return;
-}
-
 var config = QUnit.config,
+       collapseNext = false,
        hasOwn = Object.prototype.hasOwnProperty,
        defined = {
                document: window.document !== undefined,
@@ -3479,7 +3787,7 @@ function appendHeader() {
 
        if ( header ) {
                header.innerHTML = "<a href='" +
-                       setUrl({ filter: undefined, module: undefined, testId: undefined }) +
+                       escapeText( setUrl( { filter: undefined, module: undefined, testId: undefined } ) ) +
                        "'>" + header.innerHTML + "</a> ";
        }
 }
@@ -3517,6 +3825,18 @@ function storeFixture() {
        }
 }
 
+function appendFilteredTest() {
+       var testId = QUnit.config.testId;
+       if ( !testId || testId.length <= 0 ) {
+               return "";
+       }
+       return "<div id='qunit-filteredTest'>Rerunning selected tests: " +
+               escapeText( testId.join(", ") ) +
+               " <a id='qunit-clearFilter' href='" +
+               escapeText( setUrl( { filter: undefined, module: undefined, testId: undefined } ) ) +
+               "'>" + "Run all tests" + "</a></div>";
+}
+
 function appendUserAgent() {
        var userAgent = id( "qunit-userAgent" );
 
@@ -3524,7 +3844,7 @@ function appendUserAgent() {
                userAgent.innerHTML = "";
                userAgent.appendChild(
                        document.createTextNode(
-                               "QUnit " + QUnit.version  + "; " + navigator.userAgent
+                               "QUnit " + QUnit.version + "; " + navigator.userAgent
                        )
                );
        }
@@ -3588,6 +3908,7 @@ QUnit.begin(function( details ) {
                        "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
                        "<h2 id='qunit-banner'></h2>" +
                        "<div id='qunit-testrunner-toolbar'></div>" +
+                       appendFilteredTest() +
                        "<h2 id='qunit-userAgent'></h2>" +
                        "<ol id='qunit-tests'></ol>";
        }
@@ -3693,9 +4014,15 @@ QUnit.testStart(function( details ) {
 
 });
 
+function stripHtml( string ) {
+       // strip tags, html entity and whitespaces
+       return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/\&quot;/g, "").replace(/\s+/g, "");
+}
+
 QUnit.log(function( details ) {
        var assertList, assertLi,
-               message, expected, actual,
+               message, expected, actual, diff,
+               showDiff = false,
                testItem = id( "qunit-test-output-" + details.testId );
 
        if ( !testItem ) {
@@ -3710,26 +4037,44 @@ QUnit.log(function( details ) {
        // when it calls, it's implicit to also not show expected and diff stuff
        // Also, we need to check details.expected existence, as it can exist and be undefined
        if ( !details.result && hasOwn.call( details, "expected" ) ) {
-               expected = escapeText( QUnit.dump.parse( details.expected ) );
+               if ( details.negative ) {
+                       expected = escapeText( "NOT " + QUnit.dump.parse( details.expected ) );
+               } else {
+                       expected = escapeText( QUnit.dump.parse( details.expected ) );
+               }
+
                actual = escapeText( QUnit.dump.parse( details.actual ) );
                message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
                        expected +
                        "</pre></td></tr>";
 
                if ( actual !== expected ) {
+
                        message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
-                               actual + "</pre></td></tr>" +
-                               "<tr class='test-diff'><th>Diff: </th><td><pre>" +
-                               QUnit.diff( expected, actual ) + "</pre></td></tr>";
-               } else {
-                       if ( expected.indexOf( "[object Array]" ) !== -1 ||
-                                       expected.indexOf( "[object Object]" ) !== -1 ) {
-                               message += "<tr class='test-message'><th>Message: </th><td>" +
-                                       "Diff suppressed as the depth of object is more than current max depth (" +
-                                       QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
-                                       " run with a higher max depth or <a href='" + setUrl({ maxDepth: -1 }) + "'>" +
-                                       "Rerun</a> without max depth.</p></td></tr>";
+                               actual + "</pre></td></tr>";
+
+                       // Don't show diff if actual or expected are booleans
+                       if ( !( /^(true|false)$/.test( actual ) ) &&
+                                       !( /^(true|false)$/.test( expected ) ) ) {
+                               diff = QUnit.diff( expected, actual );
+                               showDiff = stripHtml( diff ).length !==
+                                       stripHtml( expected ).length +
+                                       stripHtml( actual ).length;
+                       }
+
+                       // Don't show diff if expected and actual are totally different
+                       if ( showDiff ) {
+                               message += "<tr class='test-diff'><th>Diff: </th><td><pre>" +
+                                       diff + "</pre></td></tr>";
                        }
+               } else if ( expected.indexOf( "[object Array]" ) !== -1 ||
+                               expected.indexOf( "[object Object]" ) !== -1 ) {
+                       message += "<tr class='test-message'><th>Message: </th><td>" +
+                               "Diff suppressed as the depth of object is more than current max depth (" +
+                               QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
+                               " run with a higher max depth or <a href='" +
+                               escapeText( setUrl( { maxDepth: -1 } ) ) + "'>" +
+                               "Rerun</a> without max depth.</p></td></tr>";
                }
 
                if ( details.source ) {
@@ -3739,7 +4084,7 @@ QUnit.log(function( details ) {
 
                message += "</table>";
 
-       // this occours when pushFailure is set and we have an extracted stack trace
+       // this occurs when pushFailure is set and we have an extracted stack trace
        } else if ( !details.result && details.source ) {
                message += "<table>" +
                        "<tr class='test-source'><th>Source: </th><td><pre>" +
@@ -3757,7 +4102,7 @@ QUnit.log(function( details ) {
 
 QUnit.testDone(function( details ) {
        var testTitle, time, testItem, assertList,
-               good, bad, testCounts, skipped,
+               good, bad, testCounts, skipped, sourceName,
                tests = id( "qunit-tests" );
 
        if ( !tests ) {
@@ -3781,6 +4126,16 @@ QUnit.testDone(function( details ) {
        }
 
        if ( bad === 0 ) {
+
+               // Collapse the passing tests
+               addClass( assertList, "qunit-collapsed" );
+       } else if ( bad && config.collapse && !collapseNext ) {
+
+               // Skip collapsing the first failing test
+               collapseNext = true;
+       } else {
+
+               // Collapse remaining tests
                addClass( assertList, "qunit-collapsed" );
        }
 
@@ -3812,10 +4167,31 @@ QUnit.testDone(function( details ) {
                time.innerHTML = details.runtime + " ms";
                testItem.insertBefore( time, assertList );
        }
+
+       // Show the source of the test when showing assertions
+       if ( details.source ) {
+               sourceName = document.createElement( "p" );
+               sourceName.innerHTML = "<strong>Source: </strong>" + details.source;
+               addClass( sourceName, "qunit-source" );
+               if ( bad === 0 ) {
+                       addClass( sourceName, "qunit-collapsed" );
+               }
+               addEvent( testTitle, "click", function() {
+                       toggleClass( sourceName, "qunit-collapsed" );
+               });
+               testItem.appendChild( sourceName );
+       }
 });
 
 if ( defined.document ) {
-       if ( document.readyState === "complete" ) {
+
+       // Avoid readyState issue with phantomjs
+       // Ref: #818
+       var notPhantom = ( function( p ) {
+               return !( p && p.version && p.version.major > 0 );
+       } )( window.phantom );
+
+       if ( notPhantom && document.readyState === "complete" ) {
                QUnit.load();
        } else {
                addEvent( window, "load", QUnit.load );
diff --git a/resources/lib/sinonjs/sinon-1.15.4.js b/resources/lib/sinonjs/sinon-1.15.4.js
deleted file mode 100644 (file)
index 20bc9e2..0000000
+++ /dev/null
@@ -1,5949 +0,0 @@
-/**
- * Sinon.JS 1.15.4, 2015/06/27
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-(function (root, factory) {
-  'use strict';
-  if (typeof define === 'function' && define.amd) {
-    define('sinon', [], function () {
-      return (root.sinon = factory());
-    });
-  } else if (typeof exports === 'object') {
-    module.exports = factory();
-  } else {
-    root.sinon = factory();
-  }
-}(this, function () {
-  'use strict';
-  var samsam, formatio, lolex;
-  (function () {
-                function define(mod, deps, fn) {
-                  if (mod == "samsam") {
-                    samsam = deps();
-                  } else if (typeof deps === "function" && mod.length === 0) {
-                    lolex = deps();
-                  } else if (typeof fn === "function") {
-                    formatio = fn(samsam);
-                  }
-                }
-    define.amd = {};
-((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
- (typeof module === "object" &&
-      function (m) { module.exports = m(); }) || // Node
- function (m) { this.samsam = m(); } // Browser globals
-)(function () {
-    var o = Object.prototype;
-    var div = typeof document !== "undefined" && document.createElement("div");
-
-    function isNaN(value) {
-        // Unlike global isNaN, this avoids type coercion
-        // typeof check avoids IE host object issues, hat tip to
-        // lodash
-        var val = value; // JsLint thinks value !== value is "weird"
-        return typeof value === "number" && value !== val;
-    }
-
-    function getClass(value) {
-        // Returns the internal [[Class]] by calling Object.prototype.toString
-        // with the provided value as this. Return value is a string, naming the
-        // internal class, e.g. "Array"
-        return o.toString.call(value).split(/[ \]]/)[1];
-    }
-
-    /**
-     * @name samsam.isArguments
-     * @param Object object
-     *
-     * Returns ``true`` if ``object`` is an ``arguments`` object,
-     * ``false`` otherwise.
-     */
-    function isArguments(object) {
-        if (getClass(object) === 'Arguments') { return true; }
-        if (typeof object !== "object" || typeof object.length !== "number" ||
-                getClass(object) === "Array") {
-            return false;
-        }
-        if (typeof object.callee == "function") { return true; }
-        try {
-            object[object.length] = 6;
-            delete object[object.length];
-        } catch (e) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @name samsam.isElement
-     * @param Object object
-     *
-     * Returns ``true`` if ``object`` is a DOM element node. Unlike
-     * Underscore.js/lodash, this function will return ``false`` if ``object``
-     * is an *element-like* object, i.e. a regular object with a ``nodeType``
-     * property that holds the value ``1``.
-     */
-    function isElement(object) {
-        if (!object || object.nodeType !== 1 || !div) { return false; }
-        try {
-            object.appendChild(div);
-            object.removeChild(div);
-        } catch (e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * @name samsam.keys
-     * @param Object object
-     *
-     * Return an array of own property names.
-     */
-    function keys(object) {
-        var ks = [], prop;
-        for (prop in object) {
-            if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
-        }
-        return ks;
-    }
-
-    /**
-     * @name samsam.isDate
-     * @param Object value
-     *
-     * Returns true if the object is a ``Date``, or *date-like*. Duck typing
-     * of date objects work by checking that the object has a ``getTime``
-     * function whose return value equals the return value from the object's
-     * ``valueOf``.
-     */
-    function isDate(value) {
-        return typeof value.getTime == "function" &&
-            value.getTime() == value.valueOf();
-    }
-
-    /**
-     * @name samsam.isNegZero
-     * @param Object value
-     *
-     * Returns ``true`` if ``value`` is ``-0``.
-     */
-    function isNegZero(value) {
-        return value === 0 && 1 / value === -Infinity;
-    }
-
-    /**
-     * @name samsam.equal
-     * @param Object obj1
-     * @param Object obj2
-     *
-     * Returns ``true`` if two objects are strictly equal. Compared to
-     * ``===`` there are two exceptions:
-     *
-     *   - NaN is considered equal to NaN
-     *   - -0 and +0 are not considered equal
-     */
-    function identical(obj1, obj2) {
-        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
-            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
-        }
-    }
-
-
-    /**
-     * @name samsam.deepEqual
-     * @param Object obj1
-     * @param Object obj2
-     *
-     * Deep equal comparison. Two values are "deep equal" if:
-     *
-     *   - They are equal, according to samsam.identical
-     *   - They are both date objects representing the same time
-     *   - They are both arrays containing elements that are all deepEqual
-     *   - They are objects with the same set of properties, and each property
-     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
-     *
-     * Supports cyclic objects.
-     */
-    function deepEqualCyclic(obj1, obj2) {
-
-        // used for cyclic comparison
-        // contain already visited objects
-        var objects1 = [],
-            objects2 = [],
-        // contain pathes (position in the object structure)
-        // of the already visited objects
-        // indexes same as in objects arrays
-            paths1 = [],
-            paths2 = [],
-        // contains combinations of already compared objects
-        // in the manner: { "$1['ref']$2['ref']": true }
-            compared = {};
-
-        /**
-         * used to check, if the value of a property is an object
-         * (cyclic logic is only needed for objects)
-         * only needed for cyclic logic
-         */
-        function isObject(value) {
-
-            if (typeof value === 'object' && value !== null &&
-                    !(value instanceof Boolean) &&
-                    !(value instanceof Date)    &&
-                    !(value instanceof Number)  &&
-                    !(value instanceof RegExp)  &&
-                    !(value instanceof String)) {
-
-                return true;
-            }
-
-            return false;
-        }
-
-        /**
-         * returns the index of the given object in the
-         * given objects array, -1 if not contained
-         * only needed for cyclic logic
-         */
-        function getIndex(objects, obj) {
-
-            var i;
-            for (i = 0; i < objects.length; i++) {
-                if (objects[i] === obj) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        // does the recursion for the deep equal check
-        return (function deepEqual(obj1, obj2, path1, path2) {
-            var type1 = typeof obj1;
-            var type2 = typeof obj2;
-
-            // == null also matches undefined
-            if (obj1 === obj2 ||
-                    isNaN(obj1) || isNaN(obj2) ||
-                    obj1 == null || obj2 == null ||
-                    type1 !== "object" || type2 !== "object") {
-
-                return identical(obj1, obj2);
-            }
-
-            // Elements are only equal if identical(expected, actual)
-            if (isElement(obj1) || isElement(obj2)) { return false; }
-
-            var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
-            if (isDate1 || isDate2) {
-                if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
-                    return false;
-                }
-            }
-
-            if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
-                if (obj1.toString() !== obj2.toString()) { return false; }
-            }
-
-            var class1 = getClass(obj1);
-            var class2 = getClass(obj2);
-            var keys1 = keys(obj1);
-            var keys2 = keys(obj2);
-
-            if (isArguments(obj1) || isArguments(obj2)) {
-                if (obj1.length !== obj2.length) { return false; }
-            } else {
-                if (type1 !== type2 || class1 !== class2 ||
-                        keys1.length !== keys2.length) {
-                    return false;
-                }
-            }
-
-            var key, i, l,
-                // following vars are used for the cyclic logic
-                value1, value2,
-                isObject1, isObject2,
-                index1, index2,
-                newPath1, newPath2;
-
-            for (i = 0, l = keys1.length; i < l; i++) {
-                key = keys1[i];
-                if (!o.hasOwnProperty.call(obj2, key)) {
-                    return false;
-                }
-
-                // Start of the cyclic logic
-
-                value1 = obj1[key];
-                value2 = obj2[key];
-
-                isObject1 = isObject(value1);
-                isObject2 = isObject(value2);
-
-                // determine, if the objects were already visited
-                // (it's faster to check for isObject first, than to
-                // get -1 from getIndex for non objects)
-                index1 = isObject1 ? getIndex(objects1, value1) : -1;
-                index2 = isObject2 ? getIndex(objects2, value2) : -1;
-
-                // determine the new pathes of the objects
-                // - for non cyclic objects the current path will be extended
-                //   by current property name
-                // - for cyclic objects the stored path is taken
-                newPath1 = index1 !== -1
-                    ? paths1[index1]
-                    : path1 + '[' + JSON.stringify(key) + ']';
-                newPath2 = index2 !== -1
-                    ? paths2[index2]
-                    : path2 + '[' + JSON.stringify(key) + ']';
-
-                // stop recursion if current objects are already compared
-                if (compared[newPath1 + newPath2]) {
-                    return true;
-                }
-
-                // remember the current objects and their pathes
-                if (index1 === -1 && isObject1) {
-                    objects1.push(value1);
-                    paths1.push(newPath1);
-                }
-                if (index2 === -1 && isObject2) {
-                    objects2.push(value2);
-                    paths2.push(newPath2);
-                }
-
-                // remember that the current objects are already compared
-                if (isObject1 && isObject2) {
-                    compared[newPath1 + newPath2] = true;
-                }
-
-                // End of cyclic logic
-
-                // neither value1 nor value2 is a cycle
-                // continue with next level
-                if (!deepEqual(value1, value2, newPath1, newPath2)) {
-                    return false;
-                }
-            }
-
-            return true;
-
-        }(obj1, obj2, '$1', '$2'));
-    }
-
-    var match;
-
-    function arrayContains(array, subset) {
-        if (subset.length === 0) { return true; }
-        var i, l, j, k;
-        for (i = 0, l = array.length; i < l; ++i) {
-            if (match(array[i], subset[0])) {
-                for (j = 0, k = subset.length; j < k; ++j) {
-                    if (!match(array[i + j], subset[j])) { return false; }
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @name samsam.match
-     * @param Object object
-     * @param Object matcher
-     *
-     * Compare arbitrary value ``object`` with matcher.
-     */
-    match = function match(object, matcher) {
-        if (matcher && typeof matcher.test === "function") {
-            return matcher.test(object);
-        }
-
-        if (typeof matcher === "function") {
-            return matcher(object) === true;
-        }
-
-        if (typeof matcher === "string") {
-            matcher = matcher.toLowerCase();
-            var notNull = typeof object === "string" || !!object;
-            return notNull &&
-                (String(object)).toLowerCase().indexOf(matcher) >= 0;
-        }
-
-        if (typeof matcher === "number") {
-            return matcher === object;
-        }
-
-        if (typeof matcher === "boolean") {
-            return matcher === object;
-        }
-
-        if (typeof(matcher) === "undefined") {
-            return typeof(object) === "undefined";
-        }
-
-        if (matcher === null) {
-            return object === null;
-        }
-
-        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
-            return arrayContains(object, matcher);
-        }
-
-        if (matcher && typeof matcher === "object") {
-            if (matcher === object) {
-                return true;
-            }
-            var prop;
-            for (prop in matcher) {
-                var value = object[prop];
-                if (typeof value === "undefined" &&
-                        typeof object.getAttribute === "function") {
-                    value = object.getAttribute(prop);
-                }
-                if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
-                    if (value !== matcher[prop]) {
-                        return false;
-                    }
-                } else if (typeof  value === "undefined" || !match(value, matcher[prop])) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        throw new Error("Matcher was not a string, a number, a " +
-                        "function, a boolean or an object");
-    };
-
-    return {
-        isArguments: isArguments,
-        isElement: isElement,
-        isDate: isDate,
-        isNegZero: isNegZero,
-        identical: identical,
-        deepEqual: deepEqualCyclic,
-        match: match,
-        keys: keys
-    };
-});
-((typeof define === "function" && define.amd && function (m) {
-    define("formatio", ["samsam"], m);
-}) || (typeof module === "object" && function (m) {
-    module.exports = m(require("samsam"));
-}) || function (m) { this.formatio = m(this.samsam); }
-)(function (samsam) {
-    
-    var formatio = {
-        excludeConstructors: ["Object", /^.$/],
-        quoteStrings: true,
-        limitChildrenCount: 0
-    };
-
-    var hasOwn = Object.prototype.hasOwnProperty;
-
-    var specialObjects = [];
-    if (typeof global !== "undefined") {
-        specialObjects.push({ object: global, value: "[object global]" });
-    }
-    if (typeof document !== "undefined") {
-        specialObjects.push({
-            object: document,
-            value: "[object HTMLDocument]"
-        });
-    }
-    if (typeof window !== "undefined") {
-        specialObjects.push({ object: window, value: "[object Window]" });
-    }
-
-    function functionName(func) {
-        if (!func) { return ""; }
-        if (func.displayName) { return func.displayName; }
-        if (func.name) { return func.name; }
-        var matches = func.toString().match(/function\s+([^\(]+)/m);
-        return (matches && matches[1]) || "";
-    }
-
-    function constructorName(f, object) {
-        var name = functionName(object && object.constructor);
-        var excludes = f.excludeConstructors ||
-                formatio.excludeConstructors || [];
-
-        var i, l;
-        for (i = 0, l = excludes.length; i < l; ++i) {
-            if (typeof excludes[i] === "string" && excludes[i] === name) {
-                return "";
-            } else if (excludes[i].test && excludes[i].test(name)) {
-                return "";
-            }
-        }
-
-        return name;
-    }
-
-    function isCircular(object, objects) {
-        if (typeof object !== "object") { return false; }
-        var i, l;
-        for (i = 0, l = objects.length; i < l; ++i) {
-            if (objects[i] === object) { return true; }
-        }
-        return false;
-    }
-
-    function ascii(f, object, processed, indent) {
-        if (typeof object === "string") {
-            var qs = f.quoteStrings;
-            var quote = typeof qs !== "boolean" || qs;
-            return processed || quote ? '"' + object + '"' : object;
-        }
-
-        if (typeof object === "function" && !(object instanceof RegExp)) {
-            return ascii.func(object);
-        }
-
-        processed = processed || [];
-
-        if (isCircular(object, processed)) { return "[Circular]"; }
-
-        if (Object.prototype.toString.call(object) === "[object Array]") {
-            return ascii.array.call(f, object, processed);
-        }
-
-        if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
-        if (samsam.isElement(object)) { return ascii.element(object); }
-
-        if (typeof object.toString === "function" &&
-                object.toString !== Object.prototype.toString) {
-            return object.toString();
-        }
-
-        var i, l;
-        for (i = 0, l = specialObjects.length; i < l; i++) {
-            if (object === specialObjects[i].object) {
-                return specialObjects[i].value;
-            }
-        }
-
-        return ascii.object.call(f, object, processed, indent);
-    }
-
-    ascii.func = function (func) {
-        return "function " + functionName(func) + "() {}";
-    };
-
-    ascii.array = function (array, processed) {
-        processed = processed || [];
-        processed.push(array);
-        var pieces = [];
-        var i, l;
-        l = (this.limitChildrenCount > 0) ? 
-            Math.min(this.limitChildrenCount, array.length) : array.length;
-
-        for (i = 0; i < l; ++i) {
-            pieces.push(ascii(this, array[i], processed));
-        }
-
-        if(l < array.length)
-            pieces.push("[... " + (array.length - l) + " more elements]");
-
-        return "[" + pieces.join(", ") + "]";
-    };
-
-    ascii.object = function (object, processed, indent) {
-        processed = processed || [];
-        processed.push(object);
-        indent = indent || 0;
-        var pieces = [], properties = samsam.keys(object).sort();
-        var length = 3;
-        var prop, str, obj, i, k, l;
-        l = (this.limitChildrenCount > 0) ? 
-            Math.min(this.limitChildrenCount, properties.length) : properties.length;
-
-        for (i = 0; i < l; ++i) {
-            prop = properties[i];
-            obj = object[prop];
-
-            if (isCircular(obj, processed)) {
-                str = "[Circular]";
-            } else {
-                str = ascii(this, obj, processed, indent + 2);
-            }
-
-            str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
-            length += str.length;
-            pieces.push(str);
-        }
-
-        var cons = constructorName(this, object);
-        var prefix = cons ? "[" + cons + "] " : "";
-        var is = "";
-        for (i = 0, k = indent; i < k; ++i) { is += " "; }
-
-        if(l < properties.length)
-            pieces.push("[... " + (properties.length - l) + " more elements]");
-
-        if (length + indent > 80) {
-            return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
-                is + "}";
-        }
-        return prefix + "{ " + pieces.join(", ") + " }";
-    };
-
-    ascii.element = function (element) {
-        var tagName = element.tagName.toLowerCase();
-        var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
-
-        for (i = 0, l = attrs.length; i < l; ++i) {
-            attr = attrs.item(i);
-            attrName = attr.nodeName.toLowerCase().replace("html:", "");
-            val = attr.nodeValue;
-            if (attrName !== "contenteditable" || val !== "inherit") {
-                if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
-            }
-        }
-
-        var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
-        var content = element.innerHTML;
-
-        if (content.length > 20) {
-            content = content.substr(0, 20) + "[...]";
-        }
-
-        var res = formatted + pairs.join(" ") + ">" + content +
-                "</" + tagName + ">";
-
-        return res.replace(/ contentEditable="inherit"/, "");
-    };
-
-    function Formatio(options) {
-        for (var opt in options) {
-            this[opt] = options[opt];
-        }
-    }
-
-    Formatio.prototype = {
-        functionName: functionName,
-
-        configure: function (options) {
-            return new Formatio(options);
-        },
-
-        constructorName: function (object) {
-            return constructorName(this, object);
-        },
-
-        ascii: function (object, processed, indent) {
-            return ascii(this, object, processed, indent);
-        }
-    };
-
-    return Formatio.prototype;
-});
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.lolex=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
-(function (global){
-/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
-/*global global*/
-/**
- * @author Christian Johansen (christian@cjohansen.no) and contributors
- * @license BSD
- *
- * Copyright (c) 2010-2014 Christian Johansen
- */
-
-// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
-// browsers, a number.
-// see https://github.com/cjohansen/Sinon.JS/pull/436
-var timeoutResult = setTimeout(function() {}, 0);
-var addTimerReturnsObject = typeof timeoutResult === "object";
-clearTimeout(timeoutResult);
-
-var NativeDate = Date;
-var id = 1;
-
-/**
- * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
- * number of milliseconds. This is used to support human-readable strings passed
- * to clock.tick()
- */
-function parseTime(str) {
-    if (!str) {
-        return 0;
-    }
-
-    var strings = str.split(":");
-    var l = strings.length, i = l;
-    var ms = 0, parsed;
-
-    if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
-        throw new Error("tick only understands numbers and 'h:m:s'");
-    }
-
-    while (i--) {
-        parsed = parseInt(strings[i], 10);
-
-        if (parsed >= 60) {
-            throw new Error("Invalid time " + str);
-        }
-
-        ms += parsed * Math.pow(60, (l - i - 1));
-    }
-
-    return ms * 1000;
-}
-
-/**
- * Used to grok the `now` parameter to createClock.
- */
-function getEpoch(epoch) {
-    if (!epoch) { return 0; }
-    if (typeof epoch.getTime === "function") { return epoch.getTime(); }
-    if (typeof epoch === "number") { return epoch; }
-    throw new TypeError("now should be milliseconds since UNIX epoch");
-}
-
-function inRange(from, to, timer) {
-    return timer && timer.callAt >= from && timer.callAt <= to;
-}
-
-function mirrorDateProperties(target, source) {
-    if (source.now) {
-        target.now = function now() {
-            return target.clock.now;
-        };
-    } else {
-        delete target.now;
-    }
-
-    if (source.toSource) {
-        target.toSource = function toSource() {
-            return source.toSource();
-        };
-    } else {
-        delete target.toSource;
-    }
-
-    target.toString = function toString() {
-        return source.toString();
-    };
-
-    target.prototype = source.prototype;
-    target.parse = source.parse;
-    target.UTC = source.UTC;
-    target.prototype.toUTCString = source.prototype.toUTCString;
-
-    for (var prop in source) {
-        if (source.hasOwnProperty(prop)) {
-            target[prop] = source[prop];
-        }
-    }
-
-    return target;
-}
-
-function createDate() {
-    function ClockDate(year, month, date, hour, minute, second, ms) {
-        // Defensive and verbose to avoid potential harm in passing
-        // explicit undefined when user does not pass argument
-        switch (arguments.length) {
-        case 0:
-            return new NativeDate(ClockDate.clock.now);
-        case 1:
-            return new NativeDate(year);
-        case 2:
-            return new NativeDate(year, month);
-        case 3:
-            return new NativeDate(year, month, date);
-        case 4:
-            return new NativeDate(year, month, date, hour);
-        case 5:
-            return new NativeDate(year, month, date, hour, minute);
-        case 6:
-            return new NativeDate(year, month, date, hour, minute, second);
-        default:
-            return new NativeDate(year, month, date, hour, minute, second, ms);
-        }
-    }
-
-    return mirrorDateProperties(ClockDate, NativeDate);
-}
-
-function addTimer(clock, timer) {
-    if (typeof timer.func === "undefined") {
-        throw new Error("Callback must be provided to timer calls");
-    }
-
-    if (!clock.timers) {
-        clock.timers = {};
-    }
-
-    timer.id = id++;
-    timer.createdAt = clock.now;
-    timer.callAt = clock.now + (timer.delay || 0);
-
-    clock.timers[timer.id] = timer;
-
-    if (addTimerReturnsObject) {
-        return {
-            id: timer.id,
-            ref: function() {},
-            unref: function() {}
-        };
-    }
-    else {
-        return timer.id;
-    }
-}
-
-function firstTimerInRange(clock, from, to) {
-    var timers = clock.timers, timer = null;
-
-    for (var id in timers) {
-        if (!inRange(from, to, timers[id])) {
-            continue;
-        }
-
-        if (!timer || ~compareTimers(timer, timers[id])) {
-            timer = timers[id];
-        }
-    }
-
-    return timer;
-}
-
-function compareTimers(a, b) {
-    // Sort first by absolute timing
-    if (a.callAt < b.callAt) {
-        return -1;
-    }
-    if (a.callAt > b.callAt) {
-        return 1;
-    }
-
-    // Sort next by immediate, immediate timers take precedence
-    if (a.immediate && !b.immediate) {
-        return -1;
-    }
-    if (!a.immediate && b.immediate) {
-        return 1;
-    }
-
-    // Sort next by creation time, earlier-created timers take precedence
-    if (a.createdAt < b.createdAt) {
-        return -1;
-    }
-    if (a.createdAt > b.createdAt) {
-        return 1;
-    }
-
-    // Sort next by id, lower-id timers take precedence
-    if (a.id < b.id) {
-        return -1;
-    }
-    if (a.id > b.id) {
-        return 1;
-    }
-
-    // As timer ids are unique, no fallback `0` is necessary
-}
-
-function callTimer(clock, timer) {
-    if (typeof timer.interval == "number") {
-        clock.timers[timer.id].callAt += timer.interval;
-    } else {
-        delete clock.timers[timer.id];
-    }
-
-    try {
-        if (typeof timer.func == "function") {
-            timer.func.apply(null, timer.args);
-        } else {
-            eval(timer.func);
-        }
-    } catch (e) {
-        var exception = e;
-    }
-
-    if (!clock.timers[timer.id]) {
-        if (exception) {
-            throw exception;
-        }
-        return;
-    }
-
-    if (exception) {
-        throw exception;
-    }
-}
-
-function uninstall(clock, target) {
-    var method;
-
-    for (var i = 0, l = clock.methods.length; i < l; i++) {
-        method = clock.methods[i];
-
-        if (target[method].hadOwnProperty) {
-            target[method] = clock["_" + method];
-        } else {
-            try {
-                delete target[method];
-            } catch (e) {}
-        }
-    }
-
-    // Prevent multiple executions which will completely remove these props
-    clock.methods = [];
-}
-
-function hijackMethod(target, method, clock) {
-    clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
-    clock["_" + method] = target[method];
-
-    if (method == "Date") {
-        var date = mirrorDateProperties(clock[method], target[method]);
-        target[method] = date;
-    } else {
-        target[method] = function () {
-            return clock[method].apply(clock, arguments);
-        };
-
-        for (var prop in clock[method]) {
-            if (clock[method].hasOwnProperty(prop)) {
-                target[method][prop] = clock[method][prop];
-            }
-        }
-    }
-
-    target[method].clock = clock;
-}
-
-var timers = {
-    setTimeout: setTimeout,
-    clearTimeout: clearTimeout,
-    setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
-    clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
-    setInterval: setInterval,
-    clearInterval: clearInterval,
-    Date: Date
-};
-
-var keys = Object.keys || function (obj) {
-    var ks = [];
-    for (var key in obj) {
-        ks.push(key);
-    }
-    return ks;
-};
-
-exports.timers = timers;
-
-var createClock = exports.createClock = function (now) {
-    var clock = {
-        now: getEpoch(now),
-        timeouts: {},
-        Date: createDate()
-    };
-
-    clock.Date.clock = clock;
-
-    clock.setTimeout = function setTimeout(func, timeout) {
-        return addTimer(clock, {
-            func: func,
-            args: Array.prototype.slice.call(arguments, 2),
-            delay: timeout
-        });
-    };
-
-    clock.clearTimeout = function clearTimeout(timerId) {
-        if (!timerId) {
-            // null appears to be allowed in most browsers, and appears to be
-            // relied upon by some libraries, like Bootstrap carousel
-            return;
-        }
-        if (!clock.timers) {
-            clock.timers = [];
-        }
-        // in Node, timerId is an object with .ref()/.unref(), and
-        // its .id field is the actual timer id.
-        if (typeof timerId === "object") {
-            timerId = timerId.id
-        }
-        if (timerId in clock.timers) {
-            delete clock.timers[timerId];
-        }
-    };
-
-    clock.setInterval = function setInterval(func, timeout) {
-        return addTimer(clock, {
-            func: func,
-            args: Array.prototype.slice.call(arguments, 2),
-            delay: timeout,
-            interval: timeout
-        });
-    };
-
-    clock.clearInterval = function clearInterval(timerId) {
-        clock.clearTimeout(timerId);
-    };
-
-    clock.setImmediate = function setImmediate(func) {
-        return addTimer(clock, {
-            func: func,
-            args: Array.prototype.slice.call(arguments, 1),
-            immediate: true
-        });
-    };
-
-    clock.clearImmediate = function clearImmediate(timerId) {
-        clock.clearTimeout(timerId);
-    };
-
-    clock.tick = function tick(ms) {
-        ms = typeof ms == "number" ? ms : parseTime(ms);
-        var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
-        var timer = firstTimerInRange(clock, tickFrom, tickTo);
-
-        var firstException;
-        while (timer && tickFrom <= tickTo) {
-            if (clock.timers[timer.id]) {
-                tickFrom = clock.now = timer.callAt;
-                try {
-                    callTimer(clock, timer);
-                } catch (e) {
-                    firstException = firstException || e;
-                }
-            }
-
-            timer = firstTimerInRange(clock, previous, tickTo);
-            previous = tickFrom;
-        }
-
-        clock.now = tickTo;
-
-        if (firstException) {
-            throw firstException;
-        }
-
-        return clock.now;
-    };
-
-    clock.reset = function reset() {
-        clock.timers = {};
-    };
-
-    return clock;
-};
-
-exports.install = function install(target, now, toFake) {
-    if (typeof target === "number") {
-        toFake = now;
-        now = target;
-        target = null;
-    }
-
-    if (!target) {
-        target = global;
-    }
-
-    var clock = createClock(now);
-
-    clock.uninstall = function () {
-        uninstall(clock, target);
-    };
-
-    clock.methods = toFake || [];
-
-    if (clock.methods.length === 0) {
-        clock.methods = keys(timers);
-    }
-
-    for (var i = 0, l = clock.methods.length; i < l; i++) {
-        hijackMethod(target, clock.methods[i], clock);
-    }
-
-    return clock;
-};
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}]},{},[1])(1)
-});
-  })();
-  var define;
-/**
- * Sinon core utilities. For internal use only.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-var sinon = (function () {
-"use strict";
-
-    var sinon;
-    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        sinon = module.exports = require("./sinon/util/core");
-        require("./sinon/extend");
-        require("./sinon/typeOf");
-        require("./sinon/times_in_words");
-        require("./sinon/spy");
-        require("./sinon/call");
-        require("./sinon/behavior");
-        require("./sinon/stub");
-        require("./sinon/mock");
-        require("./sinon/collection");
-        require("./sinon/assert");
-        require("./sinon/sandbox");
-        require("./sinon/test");
-        require("./sinon/test_case");
-        require("./sinon/match");
-        require("./sinon/format");
-        require("./sinon/log_error");
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-        sinon = module.exports;
-    } else {
-        sinon = {};
-    }
-
-    return sinon;
-}());
-
-/**
- * @depend ../../sinon.js
- */
-/**
- * Sinon core utilities. For internal use only.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var div = typeof document != "undefined" && document.createElement("div");
-    var hasOwn = Object.prototype.hasOwnProperty;
-
-    function isDOMNode(obj) {
-        var success = false;
-
-        try {
-            obj.appendChild(div);
-            success = div.parentNode == obj;
-        } catch (e) {
-            return false;
-        } finally {
-            try {
-                obj.removeChild(div);
-            } catch (e) {
-                // Remove failed, not much we can do about that
-            }
-        }
-
-        return success;
-    }
-
-    function isElement(obj) {
-        return div && obj && obj.nodeType === 1 && isDOMNode(obj);
-    }
-
-    function isFunction(obj) {
-        return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
-    }
-
-    function isReallyNaN(val) {
-        return typeof val === "number" && isNaN(val);
-    }
-
-    function mirrorProperties(target, source) {
-        for (var prop in source) {
-            if (!hasOwn.call(target, prop)) {
-                target[prop] = source[prop];
-            }
-        }
-    }
-
-    function isRestorable(obj) {
-        return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
-    }
-
-    // Cheap way to detect if we have ES5 support.
-    var hasES5Support = "keys" in Object;
-
-    function makeApi(sinon) {
-        sinon.wrapMethod = function wrapMethod(object, property, method) {
-            if (!object) {
-                throw new TypeError("Should wrap property of object");
-            }
-
-            if (typeof method != "function" && typeof method != "object") {
-                throw new TypeError("Method wrapper should be a function or a property descriptor");
-            }
-
-            function checkWrappedMethod(wrappedMethod) {
-                if (!isFunction(wrappedMethod)) {
-                    error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
-                                        property + " as function");
-                } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
-                    error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
-                } else if (wrappedMethod.calledBefore) {
-                    var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
-                    error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
-                }
-
-                if (error) {
-                    if (wrappedMethod && wrappedMethod.stackTrace) {
-                        error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
-                    }
-                    throw error;
-                }
-            }
-
-            var error, wrappedMethod;
-
-            // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
-            // when using hasOwn.call on objects from other frames.
-            var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
-
-            if (hasES5Support) {
-                var methodDesc = (typeof method == "function") ? {value: method} : method,
-                    wrappedMethodDesc = sinon.getPropertyDescriptor(object, property),
-                    i;
-
-                if (!wrappedMethodDesc) {
-                    error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
-                                        property + " as function");
-                } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
-                    error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
-                }
-                if (error) {
-                    if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
-                        error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
-                    }
-                    throw error;
-                }
-
-                var types = sinon.objectKeys(methodDesc);
-                for (i = 0; i < types.length; i++) {
-                    wrappedMethod = wrappedMethodDesc[types[i]];
-                    checkWrappedMethod(wrappedMethod);
-                }
-
-                mirrorProperties(methodDesc, wrappedMethodDesc);
-                for (i = 0; i < types.length; i++) {
-                    mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
-                }
-                Object.defineProperty(object, property, methodDesc);
-            } else {
-                wrappedMethod = object[property];
-                checkWrappedMethod(wrappedMethod);
-                object[property] = method;
-                method.displayName = property;
-            }
-
-            method.displayName = property;
-
-            // Set up a stack trace which can be used later to find what line of
-            // code the original method was created on.
-            method.stackTrace = (new Error("Stack Trace for original")).stack;
-
-            method.restore = function () {
-                // For prototype properties try to reset by delete first.
-                // If this fails (ex: localStorage on mobile safari) then force a reset
-                // via direct assignment.
-                if (!owned) {
-                    // In some cases `delete` may throw an error
-                    try {
-                        delete object[property];
-                    } catch (e) {}
-                    // For native code functions `delete` fails without throwing an error
-                    // on Chrome < 43, PhantomJS, etc.
-                } else if (hasES5Support) {
-                    Object.defineProperty(object, property, wrappedMethodDesc);
-                }
-
-                // Use strict equality comparison to check failures then force a reset
-                // via direct assignment.
-                if (object[property] === method) {
-                    object[property] = wrappedMethod;
-                }
-            };
-
-            method.restore.sinon = true;
-
-            if (!hasES5Support) {
-                mirrorProperties(method, wrappedMethod);
-            }
-
-            return method;
-        };
-
-        sinon.create = function create(proto) {
-            var F = function () {};
-            F.prototype = proto;
-            return new F();
-        };
-
-        sinon.deepEqual = function deepEqual(a, b) {
-            if (sinon.match && sinon.match.isMatcher(a)) {
-                return a.test(b);
-            }
-
-            if (typeof a != "object" || typeof b != "object") {
-                if (isReallyNaN(a) && isReallyNaN(b)) {
-                    return true;
-                } else {
-                    return a === b;
-                }
-            }
-
-            if (isElement(a) || isElement(b)) {
-                return a === b;
-            }
-
-            if (a === b) {
-                return true;
-            }
-
-            if ((a === null && b !== null) || (a !== null && b === null)) {
-                return false;
-            }
-
-            if (a instanceof RegExp && b instanceof RegExp) {
-                return (a.source === b.source) && (a.global === b.global) &&
-                    (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
-            }
-
-            var aString = Object.prototype.toString.call(a);
-            if (aString != Object.prototype.toString.call(b)) {
-                return false;
-            }
-
-            if (aString == "[object Date]") {
-                return a.valueOf() === b.valueOf();
-            }
-
-            var prop, aLength = 0, bLength = 0;
-
-            if (aString == "[object Array]" && a.length !== b.length) {
-                return false;
-            }
-
-            for (prop in a) {
-                aLength += 1;
-
-                if (!(prop in b)) {
-                    return false;
-                }
-
-                if (!deepEqual(a[prop], b[prop])) {
-                    return false;
-                }
-            }
-
-            for (prop in b) {
-                bLength += 1;
-            }
-
-            return aLength == bLength;
-        };
-
-        sinon.functionName = function functionName(func) {
-            var name = func.displayName || func.name;
-
-            // Use function decomposition as a last resort to get function
-            // name. Does not rely on function decomposition to work - if it
-            // doesn't debugging will be slightly less informative
-            // (i.e. toString will say 'spy' rather than 'myFunc').
-            if (!name) {
-                var matches = func.toString().match(/function ([^\s\(]+)/);
-                name = matches && matches[1];
-            }
-
-            return name;
-        };
-
-        sinon.functionToString = function toString() {
-            if (this.getCall && this.callCount) {
-                var thisValue, prop, i = this.callCount;
-
-                while (i--) {
-                    thisValue = this.getCall(i).thisValue;
-
-                    for (prop in thisValue) {
-                        if (thisValue[prop] === this) {
-                            return prop;
-                        }
-                    }
-                }
-            }
-
-            return this.displayName || "sinon fake";
-        };
-
-        sinon.objectKeys = function objectKeys(obj) {
-            if (obj !== Object(obj)) {
-                throw new TypeError("sinon.objectKeys called on a non-object");
-            }
-
-            var keys = [];
-            var key;
-            for (key in obj) {
-                if (hasOwn.call(obj, key)) {
-                    keys.push(key);
-                }
-            }
-
-            return keys;
-        };
-
-        sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
-            var proto = object, descriptor;
-            while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
-                proto = Object.getPrototypeOf(proto);
-            }
-            return descriptor;
-        }
-
-        sinon.getConfig = function (custom) {
-            var config = {};
-            custom = custom || {};
-            var defaults = sinon.defaultConfig;
-
-            for (var prop in defaults) {
-                if (defaults.hasOwnProperty(prop)) {
-                    config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
-                }
-            }
-
-            return config;
-        };
-
-        sinon.defaultConfig = {
-            injectIntoThis: true,
-            injectInto: null,
-            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-            useFakeTimers: true,
-            useFakeServer: true
-        };
-
-        sinon.timesInWords = function timesInWords(count) {
-            return count == 1 && "once" ||
-                count == 2 && "twice" ||
-                count == 3 && "thrice" ||
-                (count || 0) + " times";
-        };
-
-        sinon.calledInOrder = function (spies) {
-            for (var i = 1, l = spies.length; i < l; i++) {
-                if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
-                    return false;
-                }
-            }
-
-            return true;
-        };
-
-        sinon.orderByFirstCall = function (spies) {
-            return spies.sort(function (a, b) {
-                // uuid, won't ever be equal
-                var aCall = a.getCall(0);
-                var bCall = b.getCall(0);
-                var aId = aCall && aCall.callId || -1;
-                var bId = bCall && bCall.callId || -1;
-
-                return aId < bId ? -1 : 1;
-            });
-        };
-
-        sinon.createStubInstance = function (constructor) {
-            if (typeof constructor !== "function") {
-                throw new TypeError("The constructor should be a function.");
-            }
-            return sinon.stub(sinon.create(constructor.prototype));
-        };
-
-        sinon.restore = function (object) {
-            if (object !== null && typeof object === "object") {
-                for (var prop in object) {
-                    if (isRestorable(object[prop])) {
-                        object[prop].restore();
-                    }
-                }
-            } else if (isRestorable(object)) {
-                object.restore();
-            }
-        };
-
-        return sinon;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports) {
-        makeApi(exports);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- */
-
-(function (sinon) {
-    function makeApi(sinon) {
-
-        // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
-        var hasDontEnumBug = (function () {
-            var obj = {
-                constructor: function () {
-                    return "0";
-                },
-                toString: function () {
-                    return "1";
-                },
-                valueOf: function () {
-                    return "2";
-                },
-                toLocaleString: function () {
-                    return "3";
-                },
-                prototype: function () {
-                    return "4";
-                },
-                isPrototypeOf: function () {
-                    return "5";
-                },
-                propertyIsEnumerable: function () {
-                    return "6";
-                },
-                hasOwnProperty: function () {
-                    return "7";
-                },
-                length: function () {
-                    return "8";
-                },
-                unique: function () {
-                    return "9"
-                }
-            };
-
-            var result = [];
-            for (var prop in obj) {
-                result.push(obj[prop]());
-            }
-            return result.join("") !== "0123456789";
-        })();
-
-        /* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
-         *         override properties in previous sources.
-         *
-         * target - The Object to extend
-         * sources - Objects to copy properties from.
-         *
-         * Returns the extended target
-         */
-        function extend(target /*, sources */) {
-            var sources = Array.prototype.slice.call(arguments, 1),
-                source, i, prop;
-
-            for (i = 0; i < sources.length; i++) {
-                source = sources[i];
-
-                for (prop in source) {
-                    if (source.hasOwnProperty(prop)) {
-                        target[prop] = source[prop];
-                    }
-                }
-
-                // Make sure we copy (own) toString method even when in JScript with DontEnum bug
-                // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
-                if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
-                    target.toString = source.toString;
-                }
-            }
-
-            return target;
-        };
-
-        sinon.extend = extend;
-        return sinon.extend;
-    }
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        module.exports = makeApi(sinon);
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- */
-
-(function (sinon) {
-    function makeApi(sinon) {
-
-        function timesInWords(count) {
-            switch (count) {
-                case 1:
-                    return "once";
-                case 2:
-                    return "twice";
-                case 3:
-                    return "thrice";
-                default:
-                    return (count || 0) + " times";
-            }
-        }
-
-        sinon.timesInWords = timesInWords;
-        return sinon.timesInWords;
-    }
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        module.exports = makeApi(sinon);
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- */
-/**
- * Format functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2014 Christian Johansen
- */
-
-(function (sinon, formatio) {
-    function makeApi(sinon) {
-        function typeOf(value) {
-            if (value === null) {
-                return "null";
-            } else if (value === undefined) {
-                return "undefined";
-            }
-            var string = Object.prototype.toString.call(value);
-            return string.substring(8, string.length - 1).toLowerCase();
-        };
-
-        sinon.typeOf = typeOf;
-        return sinon.typeOf;
-    }
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        module.exports = makeApi(sinon);
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(
-    (typeof sinon == "object" && sinon || null),
-    (typeof formatio == "object" && formatio)
-));
-
-/**
- * @depend util/core.js
- * @depend typeOf.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Match functions
- *
- * @author Maximilian Antoni (mail@maxantoni.de)
- * @license BSD
- *
- * Copyright (c) 2012 Maximilian Antoni
- */
-
-(function (sinon) {
-    function makeApi(sinon) {
-        function assertType(value, type, name) {
-            var actual = sinon.typeOf(value);
-            if (actual !== type) {
-                throw new TypeError("Expected type of " + name + " to be " +
-                    type + ", but was " + actual);
-            }
-        }
-
-        var matcher = {
-            toString: function () {
-                return this.message;
-            }
-        };
-
-        function isMatcher(object) {
-            return matcher.isPrototypeOf(object);
-        }
-
-        function matchObject(expectation, actual) {
-            if (actual === null || actual === undefined) {
-                return false;
-            }
-            for (var key in expectation) {
-                if (expectation.hasOwnProperty(key)) {
-                    var exp = expectation[key];
-                    var act = actual[key];
-                    if (match.isMatcher(exp)) {
-                        if (!exp.test(act)) {
-                            return false;
-                        }
-                    } else if (sinon.typeOf(exp) === "object") {
-                        if (!matchObject(exp, act)) {
-                            return false;
-                        }
-                    } else if (!sinon.deepEqual(exp, act)) {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        }
-
-        matcher.or = function (m2) {
-            if (!arguments.length) {
-                throw new TypeError("Matcher expected");
-            } else if (!isMatcher(m2)) {
-                m2 = match(m2);
-            }
-            var m1 = this;
-            var or = sinon.create(matcher);
-            or.test = function (actual) {
-                return m1.test(actual) || m2.test(actual);
-            };
-            or.message = m1.message + ".or(" + m2.message + ")";
-            return or;
-        };
-
-        matcher.and = function (m2) {
-            if (!arguments.length) {
-                throw new TypeError("Matcher expected");
-            } else if (!isMatcher(m2)) {
-                m2 = match(m2);
-            }
-            var m1 = this;
-            var and = sinon.create(matcher);
-            and.test = function (actual) {
-                return m1.test(actual) && m2.test(actual);
-            };
-            and.message = m1.message + ".and(" + m2.message + ")";
-            return and;
-        };
-
-        var match = function (expectation, message) {
-            var m = sinon.create(matcher);
-            var type = sinon.typeOf(expectation);
-            switch (type) {
-            case "object":
-                if (typeof expectation.test === "function") {
-                    m.test = function (actual) {
-                        return expectation.test(actual) === true;
-                    };
-                    m.message = "match(" + sinon.functionName(expectation.test) + ")";
-                    return m;
-                }
-                var str = [];
-                for (var key in expectation) {
-                    if (expectation.hasOwnProperty(key)) {
-                        str.push(key + ": " + expectation[key]);
-                    }
-                }
-                m.test = function (actual) {
-                    return matchObject(expectation, actual);
-                };
-                m.message = "match(" + str.join(", ") + ")";
-                break;
-            case "number":
-                m.test = function (actual) {
-                    return expectation == actual;
-                };
-                break;
-            case "string":
-                m.test = function (actual) {
-                    if (typeof actual !== "string") {
-                        return false;
-                    }
-                    return actual.indexOf(expectation) !== -1;
-                };
-                m.message = "match(\"" + expectation + "\")";
-                break;
-            case "regexp":
-                m.test = function (actual) {
-                    if (typeof actual !== "string") {
-                        return false;
-                    }
-                    return expectation.test(actual);
-                };
-                break;
-            case "function":
-                m.test = expectation;
-                if (message) {
-                    m.message = message;
-                } else {
-                    m.message = "match(" + sinon.functionName(expectation) + ")";
-                }
-                break;
-            default:
-                m.test = function (actual) {
-                    return sinon.deepEqual(expectation, actual);
-                };
-            }
-            if (!m.message) {
-                m.message = "match(" + expectation + ")";
-            }
-            return m;
-        };
-
-        match.isMatcher = isMatcher;
-
-        match.any = match(function () {
-            return true;
-        }, "any");
-
-        match.defined = match(function (actual) {
-            return actual !== null && actual !== undefined;
-        }, "defined");
-
-        match.truthy = match(function (actual) {
-            return !!actual;
-        }, "truthy");
-
-        match.falsy = match(function (actual) {
-            return !actual;
-        }, "falsy");
-
-        match.same = function (expectation) {
-            return match(function (actual) {
-                return expectation === actual;
-            }, "same(" + expectation + ")");
-        };
-
-        match.typeOf = function (type) {
-            assertType(type, "string", "type");
-            return match(function (actual) {
-                return sinon.typeOf(actual) === type;
-            }, "typeOf(\"" + type + "\")");
-        };
-
-        match.instanceOf = function (type) {
-            assertType(type, "function", "type");
-            return match(function (actual) {
-                return actual instanceof type;
-            }, "instanceOf(" + sinon.functionName(type) + ")");
-        };
-
-        function createPropertyMatcher(propertyTest, messagePrefix) {
-            return function (property, value) {
-                assertType(property, "string", "property");
-                var onlyProperty = arguments.length === 1;
-                var message = messagePrefix + "(\"" + property + "\"";
-                if (!onlyProperty) {
-                    message += ", " + value;
-                }
-                message += ")";
-                return match(function (actual) {
-                    if (actual === undefined || actual === null ||
-                            !propertyTest(actual, property)) {
-                        return false;
-                    }
-                    return onlyProperty || sinon.deepEqual(value, actual[property]);
-                }, message);
-            };
-        }
-
-        match.has = createPropertyMatcher(function (actual, property) {
-            if (typeof actual === "object") {
-                return property in actual;
-            }
-            return actual[property] !== undefined;
-        }, "has");
-
-        match.hasOwn = createPropertyMatcher(function (actual, property) {
-            return actual.hasOwnProperty(property);
-        }, "hasOwn");
-
-        match.bool = match.typeOf("boolean");
-        match.number = match.typeOf("number");
-        match.string = match.typeOf("string");
-        match.object = match.typeOf("object");
-        match.func = match.typeOf("function");
-        match.array = match.typeOf("array");
-        match.regexp = match.typeOf("regexp");
-        match.date = match.typeOf("date");
-
-        sinon.match = match;
-        return match;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./typeOf");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- */
-/**
- * Format functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2014 Christian Johansen
- */
-
-(function (sinon, formatio) {
-    function makeApi(sinon) {
-        function valueFormatter(value) {
-            return "" + value;
-        }
-
-        function getFormatioFormatter() {
-            var formatter = formatio.configure({
-                    quoteStrings: false,
-                    limitChildrenCount: 250
-                });
-
-            function format() {
-                return formatter.ascii.apply(formatter, arguments);
-            };
-
-            return format;
-        }
-
-        function getNodeFormatter(value) {
-            function format(value) {
-                return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
-            };
-
-            try {
-                var util = require("util");
-            } catch (e) {
-                /* Node, but no util module - would be very old, but better safe than sorry */
-            }
-
-            return util ? format : valueFormatter;
-        }
-
-        var isNode = typeof module !== "undefined" && module.exports && typeof require == "function",
-            formatter;
-
-        if (isNode) {
-            try {
-                formatio = require("formatio");
-            } catch (e) {}
-        }
-
-        if (formatio) {
-            formatter = getFormatioFormatter()
-        } else if (isNode) {
-            formatter = getNodeFormatter();
-        } else {
-            formatter = valueFormatter;
-        }
-
-        sinon.format = formatter;
-        return sinon.format;
-    }
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        module.exports = makeApi(sinon);
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(
-    (typeof sinon == "object" && sinon || null),
-    (typeof formatio == "object" && formatio)
-));
-
-/**
-  * @depend util/core.js
-  * @depend match.js
-  * @depend format.js
-  */
-/**
-  * Spy calls
-  *
-  * @author Christian Johansen (christian@cjohansen.no)
-  * @author Maximilian Antoni (mail@maxantoni.de)
-  * @license BSD
-  *
-  * Copyright (c) 2010-2013 Christian Johansen
-  * Copyright (c) 2013 Maximilian Antoni
-  */
-
-(function (sinon) {
-    function makeApi(sinon) {
-        function throwYieldError(proxy, text, args) {
-            var msg = sinon.functionName(proxy) + text;
-            if (args.length) {
-                msg += " Received [" + slice.call(args).join(", ") + "]";
-            }
-            throw new Error(msg);
-        }
-
-        var slice = Array.prototype.slice;
-
-        var callProto = {
-            calledOn: function calledOn(thisValue) {
-                if (sinon.match && sinon.match.isMatcher(thisValue)) {
-                    return thisValue.test(this.thisValue);
-                }
-                return this.thisValue === thisValue;
-            },
-
-            calledWith: function calledWith() {
-                var l = arguments.length;
-                if (l > this.args.length) {
-                    return false;
-                }
-                for (var i = 0; i < l; i += 1) {
-                    if (!sinon.deepEqual(arguments[i], this.args[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            },
-
-            calledWithMatch: function calledWithMatch() {
-                var l = arguments.length;
-                if (l > this.args.length) {
-                    return false;
-                }
-                for (var i = 0; i < l; i += 1) {
-                    var actual = this.args[i];
-                    var expectation = arguments[i];
-                    if (!sinon.match || !sinon.match(expectation).test(actual)) {
-                        return false;
-                    }
-                }
-                return true;
-            },
-
-            calledWithExactly: function calledWithExactly() {
-                return arguments.length == this.args.length &&
-                    this.calledWith.apply(this, arguments);
-            },
-
-            notCalledWith: function notCalledWith() {
-                return !this.calledWith.apply(this, arguments);
-            },
-
-            notCalledWithMatch: function notCalledWithMatch() {
-                return !this.calledWithMatch.apply(this, arguments);
-            },
-
-            returned: function returned(value) {
-                return sinon.deepEqual(value, this.returnValue);
-            },
-
-            threw: function threw(error) {
-                if (typeof error === "undefined" || !this.exception) {
-                    return !!this.exception;
-                }
-
-                return this.exception === error || this.exception.name === error;
-            },
-
-            calledWithNew: function calledWithNew() {
-                return this.proxy.prototype && this.thisValue instanceof this.proxy;
-            },
-
-            calledBefore: function (other) {
-                return this.callId < other.callId;
-            },
-
-            calledAfter: function (other) {
-                return this.callId > other.callId;
-            },
-
-            callArg: function (pos) {
-                this.args[pos]();
-            },
-
-            callArgOn: function (pos, thisValue) {
-                this.args[pos].apply(thisValue);
-            },
-
-            callArgWith: function (pos) {
-                this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
-            },
-
-            callArgOnWith: function (pos, thisValue) {
-                var args = slice.call(arguments, 2);
-                this.args[pos].apply(thisValue, args);
-            },
-
-            yield: function () {
-                this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
-            },
-
-            yieldOn: function (thisValue) {
-                var args = this.args;
-                for (var i = 0, l = args.length; i < l; ++i) {
-                    if (typeof args[i] === "function") {
-                        args[i].apply(thisValue, slice.call(arguments, 1));
-                        return;
-                    }
-                }
-                throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
-            },
-
-            yieldTo: function (prop) {
-                this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
-            },
-
-            yieldToOn: function (prop, thisValue) {
-                var args = this.args;
-                for (var i = 0, l = args.length; i < l; ++i) {
-                    if (args[i] && typeof args[i][prop] === "function") {
-                        args[i][prop].apply(thisValue, slice.call(arguments, 2));
-                        return;
-                    }
-                }
-                throwYieldError(this.proxy, " cannot yield to '" + prop +
-                    "' since no callback was passed.", args);
-            },
-
-            toString: function () {
-                var callStr = this.proxy.toString() + "(";
-                var args = [];
-
-                for (var i = 0, l = this.args.length; i < l; ++i) {
-                    args.push(sinon.format(this.args[i]));
-                }
-
-                callStr = callStr + args.join(", ") + ")";
-
-                if (typeof this.returnValue != "undefined") {
-                    callStr += " => " + sinon.format(this.returnValue);
-                }
-
-                if (this.exception) {
-                    callStr += " !" + this.exception.name;
-
-                    if (this.exception.message) {
-                        callStr += "(" + this.exception.message + ")";
-                    }
-                }
-
-                return callStr;
-            }
-        };
-
-        callProto.invokeCallback = callProto.yield;
-
-        function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
-            if (typeof id !== "number") {
-                throw new TypeError("Call id is not a number");
-            }
-            var proxyCall = sinon.create(callProto);
-            proxyCall.proxy = spy;
-            proxyCall.thisValue = thisValue;
-            proxyCall.args = args;
-            proxyCall.returnValue = returnValue;
-            proxyCall.exception = exception;
-            proxyCall.callId = id;
-
-            return proxyCall;
-        }
-        createSpyCall.toString = callProto.toString; // used by mocks
-
-        sinon.spyCall = createSpyCall;
-        return createSpyCall;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./match");
-        require("./format");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
-  * @depend times_in_words.js
-  * @depend util/core.js
-  * @depend extend.js
-  * @depend call.js
-  * @depend format.js
-  */
-/**
-  * Spy functions
-  *
-  * @author Christian Johansen (christian@cjohansen.no)
-  * @license BSD
-  *
-  * Copyright (c) 2010-2013 Christian Johansen
-  */
-
-(function (sinon) {
-
-    function makeApi(sinon) {
-        var push = Array.prototype.push;
-        var slice = Array.prototype.slice;
-        var callId = 0;
-
-        function spy(object, property, types) {
-            if (!property && typeof object == "function") {
-                return spy.create(object);
-            }
-
-            if (!object && !property) {
-                return spy.create(function () { });
-            }
-
-            if (types) {
-                var methodDesc = sinon.getPropertyDescriptor(object, property);
-                for (var i = 0; i < types.length; i++) {
-                    methodDesc[types[i]] = spy.create(methodDesc[types[i]]);
-                }
-                return sinon.wrapMethod(object, property, methodDesc);
-            } else {
-                var method = object[property];
-                return sinon.wrapMethod(object, property, spy.create(method));
-            }
-        }
-
-        function matchingFake(fakes, args, strict) {
-            if (!fakes) {
-                return;
-            }
-
-            for (var i = 0, l = fakes.length; i < l; i++) {
-                if (fakes[i].matches(args, strict)) {
-                    return fakes[i];
-                }
-            }
-        }
-
-        function incrementCallCount() {
-            this.called = true;
-            this.callCount += 1;
-            this.notCalled = false;
-            this.calledOnce = this.callCount == 1;
-            this.calledTwice = this.callCount == 2;
-            this.calledThrice = this.callCount == 3;
-        }
-
-        function createCallProperties() {
-            this.firstCall = this.getCall(0);
-            this.secondCall = this.getCall(1);
-            this.thirdCall = this.getCall(2);
-            this.lastCall = this.getCall(this.callCount - 1);
-        }
-
-        var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
-        function createProxy(func, proxyLength) {
-            // Retain the function length:
-            var p;
-            if (proxyLength) {
-                eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) +
-                    ") { return p.invoke(func, this, slice.call(arguments)); });");
-            } else {
-                p = function proxy() {
-                    return p.invoke(func, this, slice.call(arguments));
-                };
-            }
-            p.isSinonProxy = true;
-            return p;
-        }
-
-        var uuid = 0;
-
-        // Public API
-        var spyApi = {
-            reset: function () {
-                if (this.invoking) {
-                    var err = new Error("Cannot reset Sinon function while invoking it. " +
-                                        "Move the call to .reset outside of the callback.");
-                    err.name = "InvalidResetException";
-                    throw err;
-                }
-
-                this.called = false;
-                this.notCalled = true;
-                this.calledOnce = false;
-                this.calledTwice = false;
-                this.calledThrice = false;
-                this.callCount = 0;
-                this.firstCall = null;
-                this.secondCall = null;
-                this.thirdCall = null;
-                this.lastCall = null;
-                this.args = [];
-                this.returnValues = [];
-                this.thisValues = [];
-                this.exceptions = [];
-                this.callIds = [];
-                if (this.fakes) {
-                    for (var i = 0; i < this.fakes.length; i++) {
-                        this.fakes[i].reset();
-                    }
-                }
-
-                return this;
-            },
-
-            create: function create(func, spyLength) {
-                var name;
-
-                if (typeof func != "function") {
-                    func = function () { };
-                } else {
-                    name = sinon.functionName(func);
-                }
-
-                if (!spyLength) {
-                    spyLength = func.length;
-                }
-
-                var proxy = createProxy(func, spyLength);
-
-                sinon.extend(proxy, spy);
-                delete proxy.create;
-                sinon.extend(proxy, func);
-
-                proxy.reset();
-                proxy.prototype = func.prototype;
-                proxy.displayName = name || "spy";
-                proxy.toString = sinon.functionToString;
-                proxy.instantiateFake = sinon.spy.create;
-                proxy.id = "spy#" + uuid++;
-
-                return proxy;
-            },
-
-            invoke: function invoke(func, thisValue, args) {
-                var matching = matchingFake(this.fakes, args);
-                var exception, returnValue;
-
-                incrementCallCount.call(this);
-                push.call(this.thisValues, thisValue);
-                push.call(this.args, args);
-                push.call(this.callIds, callId++);
-
-                // Make call properties available from within the spied function:
-                createCallProperties.call(this);
-
-                try {
-                    this.invoking = true;
-
-                    if (matching) {
-                        returnValue = matching.invoke(func, thisValue, args);
-                    } else {
-                        returnValue = (this.func || func).apply(thisValue, args);
-                    }
-
-                    var thisCall = this.getCall(this.callCount - 1);
-                    if (thisCall.calledWithNew() && typeof returnValue !== "object") {
-                        returnValue = thisValue;
-                    }
-                } catch (e) {
-                    exception = e;
-                } finally {
-                    delete this.invoking;
-                }
-
-                push.call(this.exceptions, exception);
-                push.call(this.returnValues, returnValue);
-
-                // Make return value and exception available in the calls:
-                createCallProperties.call(this);
-
-                if (exception !== undefined) {
-                    throw exception;
-                }
-
-                return returnValue;
-            },
-
-            named: function named(name) {
-                this.displayName = name;
-                return this;
-            },
-
-            getCall: function getCall(i) {
-                if (i < 0 || i >= this.callCount) {
-                    return null;
-                }
-
-                return sinon.spyCall(this, this.thisValues[i], this.args[i],
-                                        this.returnValues[i], this.exceptions[i],
-                                        this.callIds[i]);
-            },
-
-            getCalls: function () {
-                var calls = [];
-                var i;
-
-                for (i = 0; i < this.callCount; i++) {
-                    calls.push(this.getCall(i));
-                }
-
-                return calls;
-            },
-
-            calledBefore: function calledBefore(spyFn) {
-                if (!this.called) {
-                    return false;
-                }
-
-                if (!spyFn.called) {
-                    return true;
-                }
-
-                return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
-            },
-
-            calledAfter: function calledAfter(spyFn) {
-                if (!this.called || !spyFn.called) {
-                    return false;
-                }
-
-                return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
-            },
-
-            withArgs: function () {
-                var args = slice.call(arguments);
-
-                if (this.fakes) {
-                    var match = matchingFake(this.fakes, args, true);
-
-                    if (match) {
-                        return match;
-                    }
-                } else {
-                    this.fakes = [];
-                }
-
-                var original = this;
-                var fake = this.instantiateFake();
-                fake.matchingAguments = args;
-                fake.parent = this;
-                push.call(this.fakes, fake);
-
-                fake.withArgs = function () {
-                    return original.withArgs.apply(original, arguments);
-                };
-
-                for (var i = 0; i < this.args.length; i++) {
-                    if (fake.matches(this.args[i])) {
-                        incrementCallCount.call(fake);
-                        push.call(fake.thisValues, this.thisValues[i]);
-                        push.call(fake.args, this.args[i]);
-                        push.call(fake.returnValues, this.returnValues[i]);
-                        push.call(fake.exceptions, this.exceptions[i]);
-                        push.call(fake.callIds, this.callIds[i]);
-                    }
-                }
-                createCallProperties.call(fake);
-
-                return fake;
-            },
-
-            matches: function (args, strict) {
-                var margs = this.matchingAguments;
-
-                if (margs.length <= args.length &&
-                    sinon.deepEqual(margs, args.slice(0, margs.length))) {
-                    return !strict || margs.length == args.length;
-                }
-            },
-
-            printf: function (format) {
-                var spy = this;
-                var args = slice.call(arguments, 1);
-                var formatter;
-
-                return (format || "").replace(/%(.)/g, function (match, specifyer) {
-                    formatter = spyApi.formatters[specifyer];
-
-                    if (typeof formatter == "function") {
-                        return formatter.call(null, spy, args);
-                    } else if (!isNaN(parseInt(specifyer, 10))) {
-                        return sinon.format(args[specifyer - 1]);
-                    }
-
-                    return "%" + specifyer;
-                });
-            }
-        };
-
-        function delegateToCalls(method, matchAny, actual, notCalled) {
-            spyApi[method] = function () {
-                if (!this.called) {
-                    if (notCalled) {
-                        return notCalled.apply(this, arguments);
-                    }
-                    return false;
-                }
-
-                var currentCall;
-                var matches = 0;
-
-                for (var i = 0, l = this.callCount; i < l; i += 1) {
-                    currentCall = this.getCall(i);
-
-                    if (currentCall[actual || method].apply(currentCall, arguments)) {
-                        matches += 1;
-
-                        if (matchAny) {
-                            return true;
-                        }
-                    }
-                }
-
-                return matches === this.callCount;
-            };
-        }
-
-        delegateToCalls("calledOn", true);
-        delegateToCalls("alwaysCalledOn", false, "calledOn");
-        delegateToCalls("calledWith", true);
-        delegateToCalls("calledWithMatch", true);
-        delegateToCalls("alwaysCalledWith", false, "calledWith");
-        delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
-        delegateToCalls("calledWithExactly", true);
-        delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
-        delegateToCalls("neverCalledWith", false, "notCalledWith", function () {
-            return true;
-        });
-        delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () {
-            return true;
-        });
-        delegateToCalls("threw", true);
-        delegateToCalls("alwaysThrew", false, "threw");
-        delegateToCalls("returned", true);
-        delegateToCalls("alwaysReturned", false, "returned");
-        delegateToCalls("calledWithNew", true);
-        delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
-        delegateToCalls("callArg", false, "callArgWith", function () {
-            throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
-        });
-        spyApi.callArgWith = spyApi.callArg;
-        delegateToCalls("callArgOn", false, "callArgOnWith", function () {
-            throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
-        });
-        spyApi.callArgOnWith = spyApi.callArgOn;
-        delegateToCalls("yield", false, "yield", function () {
-            throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
-        });
-        // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
-        spyApi.invokeCallback = spyApi.yield;
-        delegateToCalls("yieldOn", false, "yieldOn", function () {
-            throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
-        });
-        delegateToCalls("yieldTo", false, "yieldTo", function (property) {
-            throw new Error(this.toString() + " cannot yield to '" + property +
-                "' since it was not yet invoked.");
-        });
-        delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
-            throw new Error(this.toString() + " cannot yield to '" + property +
-                "' since it was not yet invoked.");
-        });
-
-        spyApi.formatters = {
-            c: function (spy) {
-                return sinon.timesInWords(spy.callCount);
-            },
-
-            n: function (spy) {
-                return spy.toString();
-            },
-
-            C: function (spy) {
-                var calls = [];
-
-                for (var i = 0, l = spy.callCount; i < l; ++i) {
-                    var stringifiedCall = "    " + spy.getCall(i).toString();
-                    if (/\n/.test(calls[i - 1])) {
-                        stringifiedCall = "\n" + stringifiedCall;
-                    }
-                    push.call(calls, stringifiedCall);
-                }
-
-                return calls.length > 0 ? "\n" + calls.join("\n") : "";
-            },
-
-            t: function (spy) {
-                var objects = [];
-
-                for (var i = 0, l = spy.callCount; i < l; ++i) {
-                    push.call(objects, sinon.format(spy.thisValues[i]));
-                }
-
-                return objects.join(", ");
-            },
-
-            "*": function (spy, args) {
-                var formatted = [];
-
-                for (var i = 0, l = args.length; i < l; ++i) {
-                    push.call(formatted, sinon.format(args[i]));
-                }
-
-                return formatted.join(", ");
-            }
-        };
-
-        sinon.extend(spy, spyApi);
-
-        spy.spyCall = sinon.spyCall;
-        sinon.spy = spy;
-
-        return spy;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./call");
-        require("./extend");
-        require("./times_in_words");
-        require("./format");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- * @depend extend.js
- */
-/**
- * Stub behavior
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Tim Fischbach (mail@timfischbach.de)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var slice = Array.prototype.slice;
-    var join = Array.prototype.join;
-    var useLeftMostCallback = -1;
-    var useRightMostCallback = -2;
-
-    var nextTick = (function () {
-        if (typeof process === "object" && typeof process.nextTick === "function") {
-            return process.nextTick;
-        } else if (typeof setImmediate === "function") {
-            return setImmediate;
-        } else {
-            return function (callback) {
-                setTimeout(callback, 0);
-            };
-        }
-    })();
-
-    function throwsException(error, message) {
-        if (typeof error == "string") {
-            this.exception = new Error(message || "");
-            this.exception.name = error;
-        } else if (!error) {
-            this.exception = new Error("Error");
-        } else {
-            this.exception = error;
-        }
-
-        return this;
-    }
-
-    function getCallback(behavior, args) {
-        var callArgAt = behavior.callArgAt;
-
-        if (callArgAt >= 0) {
-            return args[callArgAt];
-        }
-
-        var argumentList;
-
-        if (callArgAt === useLeftMostCallback) {
-            argumentList = args;
-        }
-
-        if (callArgAt === useRightMostCallback) {
-            argumentList = slice.call(args).reverse();
-        }
-
-        var callArgProp = behavior.callArgProp;
-
-        for (var i = 0, l = argumentList.length; i < l; ++i) {
-            if (!callArgProp && typeof argumentList[i] == "function") {
-                return argumentList[i];
-            }
-
-            if (callArgProp && argumentList[i] &&
-                typeof argumentList[i][callArgProp] == "function") {
-                return argumentList[i][callArgProp];
-            }
-        }
-
-        return null;
-    }
-
-    function makeApi(sinon) {
-        function getCallbackError(behavior, func, args) {
-            if (behavior.callArgAt < 0) {
-                var msg;
-
-                if (behavior.callArgProp) {
-                    msg = sinon.functionName(behavior.stub) +
-                        " expected to yield to '" + behavior.callArgProp +
-                        "', but no object with such a property was passed.";
-                } else {
-                    msg = sinon.functionName(behavior.stub) +
-                        " expected to yield, but no callback was passed.";
-                }
-
-                if (args.length > 0) {
-                    msg += " Received [" + join.call(args, ", ") + "]";
-                }
-
-                return msg;
-            }
-
-            return "argument at index " + behavior.callArgAt + " is not a function: " + func;
-        }
-
-        function callCallback(behavior, args) {
-            if (typeof behavior.callArgAt == "number") {
-                var func = getCallback(behavior, args);
-
-                if (typeof func != "function") {
-                    throw new TypeError(getCallbackError(behavior, func, args));
-                }
-
-                if (behavior.callbackAsync) {
-                    nextTick(function () {
-                        func.apply(behavior.callbackContext, behavior.callbackArguments);
-                    });
-                } else {
-                    func.apply(behavior.callbackContext, behavior.callbackArguments);
-                }
-            }
-        }
-
-        var proto = {
-            create: function create(stub) {
-                var behavior = sinon.extend({}, sinon.behavior);
-                delete behavior.create;
-                behavior.stub = stub;
-
-                return behavior;
-            },
-
-            isPresent: function isPresent() {
-                return (typeof this.callArgAt == "number" ||
-                        this.exception ||
-                        typeof this.returnArgAt == "number" ||
-                        this.returnThis ||
-                        this.returnValueDefined);
-            },
-
-            invoke: function invoke(context, args) {
-                callCallback(this, args);
-
-                if (this.exception) {
-                    throw this.exception;
-                } else if (typeof this.returnArgAt == "number") {
-                    return args[this.returnArgAt];
-                } else if (this.returnThis) {
-                    return context;
-                }
-
-                return this.returnValue;
-            },
-
-            onCall: function onCall(index) {
-                return this.stub.onCall(index);
-            },
-
-            onFirstCall: function onFirstCall() {
-                return this.stub.onFirstCall();
-            },
-
-            onSecondCall: function onSecondCall() {
-                return this.stub.onSecondCall();
-            },
-
-            onThirdCall: function onThirdCall() {
-                return this.stub.onThirdCall();
-            },
-
-            withArgs: function withArgs(/* arguments */) {
-                throw new Error("Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" is not supported. " +
-                                "Use \"stub.withArgs(...).onCall(...)\" to define sequential behavior for calls with certain arguments.");
-            },
-
-            callsArg: function callsArg(pos) {
-                if (typeof pos != "number") {
-                    throw new TypeError("argument index is not number");
-                }
-
-                this.callArgAt = pos;
-                this.callbackArguments = [];
-                this.callbackContext = undefined;
-                this.callArgProp = undefined;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            callsArgOn: function callsArgOn(pos, context) {
-                if (typeof pos != "number") {
-                    throw new TypeError("argument index is not number");
-                }
-                if (typeof context != "object") {
-                    throw new TypeError("argument context is not an object");
-                }
-
-                this.callArgAt = pos;
-                this.callbackArguments = [];
-                this.callbackContext = context;
-                this.callArgProp = undefined;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            callsArgWith: function callsArgWith(pos) {
-                if (typeof pos != "number") {
-                    throw new TypeError("argument index is not number");
-                }
-
-                this.callArgAt = pos;
-                this.callbackArguments = slice.call(arguments, 1);
-                this.callbackContext = undefined;
-                this.callArgProp = undefined;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            callsArgOnWith: function callsArgWith(pos, context) {
-                if (typeof pos != "number") {
-                    throw new TypeError("argument index is not number");
-                }
-                if (typeof context != "object") {
-                    throw new TypeError("argument context is not an object");
-                }
-
-                this.callArgAt = pos;
-                this.callbackArguments = slice.call(arguments, 2);
-                this.callbackContext = context;
-                this.callArgProp = undefined;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            yields: function () {
-                this.callArgAt = useLeftMostCallback;
-                this.callbackArguments = slice.call(arguments, 0);
-                this.callbackContext = undefined;
-                this.callArgProp = undefined;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            yieldsRight: function () {
-                this.callArgAt = useRightMostCallback;
-                this.callbackArguments = slice.call(arguments, 0);
-                this.callbackContext = undefined;
-                this.callArgProp = undefined;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            yieldsOn: function (context) {
-                if (typeof context != "object") {
-                    throw new TypeError("argument context is not an object");
-                }
-
-                this.callArgAt = useLeftMostCallback;
-                this.callbackArguments = slice.call(arguments, 1);
-                this.callbackContext = context;
-                this.callArgProp = undefined;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            yieldsTo: function (prop) {
-                this.callArgAt = useLeftMostCallback;
-                this.callbackArguments = slice.call(arguments, 1);
-                this.callbackContext = undefined;
-                this.callArgProp = prop;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            yieldsToOn: function (prop, context) {
-                if (typeof context != "object") {
-                    throw new TypeError("argument context is not an object");
-                }
-
-                this.callArgAt = useLeftMostCallback;
-                this.callbackArguments = slice.call(arguments, 2);
-                this.callbackContext = context;
-                this.callArgProp = prop;
-                this.callbackAsync = false;
-
-                return this;
-            },
-
-            throws: throwsException,
-            throwsException: throwsException,
-
-            returns: function returns(value) {
-                this.returnValue = value;
-                this.returnValueDefined = true;
-
-                return this;
-            },
-
-            returnsArg: function returnsArg(pos) {
-                if (typeof pos != "number") {
-                    throw new TypeError("argument index is not number");
-                }
-
-                this.returnArgAt = pos;
-
-                return this;
-            },
-
-            returnsThis: function returnsThis() {
-                this.returnThis = true;
-
-                return this;
-            }
-        };
-
-        // create asynchronous versions of callsArg* and yields* methods
-        for (var method in proto) {
-            // need to avoid creating anotherasync versions of the newly added async methods
-            if (proto.hasOwnProperty(method) &&
-                method.match(/^(callsArg|yields)/) &&
-                !method.match(/Async/)) {
-                proto[method + "Async"] = (function (syncFnName) {
-                    return function () {
-                        var result = this[syncFnName].apply(this, arguments);
-                        this.callbackAsync = true;
-                        return result;
-                    };
-                })(method);
-            }
-        }
-
-        sinon.behavior = proto;
-        return proto;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./extend");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- * @depend extend.js
- * @depend spy.js
- * @depend behavior.js
- */
-/**
- * Stub functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    function makeApi(sinon) {
-        function stub(object, property, func) {
-            if (!!func && typeof func != "function" && typeof func != "object") {
-                throw new TypeError("Custom stub should be a function or a property descriptor");
-            }
-
-            var wrapper;
-
-            if (func) {
-                if (typeof func == "function") {
-                    wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
-                } else {
-                    wrapper = func;
-                    if (sinon.spy && sinon.spy.create) {
-                        var types = sinon.objectKeys(wrapper);
-                        for (var i = 0; i < types.length; i++) {
-                            wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
-                        }
-                    }
-                }
-            } else {
-                var stubLength = 0;
-                if (typeof object == "object" && typeof object[property] == "function") {
-                    stubLength = object[property].length;
-                }
-                wrapper = stub.create(stubLength);
-            }
-
-            if (!object && typeof property === "undefined") {
-                return sinon.stub.create();
-            }
-
-            if (typeof property === "undefined" && typeof object == "object") {
-                for (var prop in object) {
-                    if (typeof sinon.getPropertyDescriptor(object, prop).value === "function") {
-                        stub(object, prop);
-                    }
-                }
-
-                return object;
-            }
-
-            return sinon.wrapMethod(object, property, wrapper);
-        }
-
-        function getDefaultBehavior(stub) {
-            return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
-        }
-
-        function getParentBehaviour(stub) {
-            return (stub.parent && getCurrentBehavior(stub.parent));
-        }
-
-        function getCurrentBehavior(stub) {
-            var behavior = stub.behaviors[stub.callCount - 1];
-            return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
-        }
-
-        var uuid = 0;
-
-        var proto = {
-            create: function create(stubLength) {
-                var functionStub = function () {
-                    return getCurrentBehavior(functionStub).invoke(this, arguments);
-                };
-
-                functionStub.id = "stub#" + uuid++;
-                var orig = functionStub;
-                functionStub = sinon.spy.create(functionStub, stubLength);
-                functionStub.func = orig;
-
-                sinon.extend(functionStub, stub);
-                functionStub.instantiateFake = sinon.stub.create;
-                functionStub.displayName = "stub";
-                functionStub.toString = sinon.functionToString;
-
-                functionStub.defaultBehavior = null;
-                functionStub.behaviors = [];
-
-                return functionStub;
-            },
-
-            resetBehavior: function () {
-                var i;
-
-                this.defaultBehavior = null;
-                this.behaviors = [];
-
-                delete this.returnValue;
-                delete this.returnArgAt;
-                this.returnThis = false;
-
-                if (this.fakes) {
-                    for (i = 0; i < this.fakes.length; i++) {
-                        this.fakes[i].resetBehavior();
-                    }
-                }
-            },
-
-            onCall: function onCall(index) {
-                if (!this.behaviors[index]) {
-                    this.behaviors[index] = sinon.behavior.create(this);
-                }
-
-                return this.behaviors[index];
-            },
-
-            onFirstCall: function onFirstCall() {
-                return this.onCall(0);
-            },
-
-            onSecondCall: function onSecondCall() {
-                return this.onCall(1);
-            },
-
-            onThirdCall: function onThirdCall() {
-                return this.onCall(2);
-            }
-        };
-
-        for (var method in sinon.behavior) {
-            if (sinon.behavior.hasOwnProperty(method) &&
-                !proto.hasOwnProperty(method) &&
-                method != "create" &&
-                method != "withArgs" &&
-                method != "invoke") {
-                proto[method] = (function (behaviorMethod) {
-                    return function () {
-                        this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
-                        this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
-                        return this;
-                    };
-                }(method));
-            }
-        }
-
-        sinon.extend(stub, proto);
-        sinon.stub = stub;
-
-        return stub;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./behavior");
-        require("./spy");
-        require("./extend");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend times_in_words.js
- * @depend util/core.js
- * @depend call.js
- * @depend extend.js
- * @depend match.js
- * @depend spy.js
- * @depend stub.js
- * @depend format.js
- */
-/**
- * Mock functions.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    function makeApi(sinon) {
-        var push = [].push;
-        var match = sinon.match;
-
-        function mock(object) {
-            // if (typeof console !== undefined && console.warn) {
-            //     console.warn("mock will be removed from Sinon.JS v2.0");
-            // }
-
-            if (!object) {
-                return sinon.expectation.create("Anonymous mock");
-            }
-
-            return mock.create(object);
-        }
-
-        function each(collection, callback) {
-            if (!collection) {
-                return;
-            }
-
-            for (var i = 0, l = collection.length; i < l; i += 1) {
-                callback(collection[i]);
-            }
-        }
-
-        sinon.extend(mock, {
-            create: function create(object) {
-                if (!object) {
-                    throw new TypeError("object is null");
-                }
-
-                var mockObject = sinon.extend({}, mock);
-                mockObject.object = object;
-                delete mockObject.create;
-
-                return mockObject;
-            },
-
-            expects: function expects(method) {
-                if (!method) {
-                    throw new TypeError("method is falsy");
-                }
-
-                if (!this.expectations) {
-                    this.expectations = {};
-                    this.proxies = [];
-                }
-
-                if (!this.expectations[method]) {
-                    this.expectations[method] = [];
-                    var mockObject = this;
-
-                    sinon.wrapMethod(this.object, method, function () {
-                        return mockObject.invokeMethod(method, this, arguments);
-                    });
-
-                    push.call(this.proxies, method);
-                }
-
-                var expectation = sinon.expectation.create(method);
-                push.call(this.expectations[method], expectation);
-
-                return expectation;
-            },
-
-            restore: function restore() {
-                var object = this.object;
-
-                each(this.proxies, function (proxy) {
-                    if (typeof object[proxy].restore == "function") {
-                        object[proxy].restore();
-                    }
-                });
-            },
-
-            verify: function verify() {
-                var expectations = this.expectations || {};
-                var messages = [], met = [];
-
-                each(this.proxies, function (proxy) {
-                    each(expectations[proxy], function (expectation) {
-                        if (!expectation.met()) {
-                            push.call(messages, expectation.toString());
-                        } else {
-                            push.call(met, expectation.toString());
-                        }
-                    });
-                });
-
-                this.restore();
-
-                if (messages.length > 0) {
-                    sinon.expectation.fail(messages.concat(met).join("\n"));
-                } else if (met.length > 0) {
-                    sinon.expectation.pass(messages.concat(met).join("\n"));
-                }
-
-                return true;
-            },
-
-            invokeMethod: function invokeMethod(method, thisValue, args) {
-                var expectations = this.expectations && this.expectations[method];
-                var length = expectations && expectations.length || 0, i;
-
-                for (i = 0; i < length; i += 1) {
-                    if (!expectations[i].met() &&
-                        expectations[i].allowsCall(thisValue, args)) {
-                        return expectations[i].apply(thisValue, args);
-                    }
-                }
-
-                var messages = [], available, exhausted = 0;
-
-                for (i = 0; i < length; i += 1) {
-                    if (expectations[i].allowsCall(thisValue, args)) {
-                        available = available || expectations[i];
-                    } else {
-                        exhausted += 1;
-                    }
-                    push.call(messages, "    " + expectations[i].toString());
-                }
-
-                if (exhausted === 0) {
-                    return available.apply(thisValue, args);
-                }
-
-                messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
-                    proxy: method,
-                    args: args
-                }));
-
-                sinon.expectation.fail(messages.join("\n"));
-            }
-        });
-
-        var times = sinon.timesInWords;
-        var slice = Array.prototype.slice;
-
-        function callCountInWords(callCount) {
-            if (callCount == 0) {
-                return "never called";
-            } else {
-                return "called " + times(callCount);
-            }
-        }
-
-        function expectedCallCountInWords(expectation) {
-            var min = expectation.minCalls;
-            var max = expectation.maxCalls;
-
-            if (typeof min == "number" && typeof max == "number") {
-                var str = times(min);
-
-                if (min != max) {
-                    str = "at least " + str + " and at most " + times(max);
-                }
-
-                return str;
-            }
-
-            if (typeof min == "number") {
-                return "at least " + times(min);
-            }
-
-            return "at most " + times(max);
-        }
-
-        function receivedMinCalls(expectation) {
-            var hasMinLimit = typeof expectation.minCalls == "number";
-            return !hasMinLimit || expectation.callCount >= expectation.minCalls;
-        }
-
-        function receivedMaxCalls(expectation) {
-            if (typeof expectation.maxCalls != "number") {
-                return false;
-            }
-
-            return expectation.callCount == expectation.maxCalls;
-        }
-
-        function verifyMatcher(possibleMatcher, arg) {
-            if (match && match.isMatcher(possibleMatcher)) {
-                return possibleMatcher.test(arg);
-            } else {
-                return true;
-            }
-        }
-
-        sinon.expectation = {
-            minCalls: 1,
-            maxCalls: 1,
-
-            create: function create(methodName) {
-                var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
-                delete expectation.create;
-                expectation.method = methodName;
-
-                return expectation;
-            },
-
-            invoke: function invoke(func, thisValue, args) {
-                this.verifyCallAllowed(thisValue, args);
-
-                return sinon.spy.invoke.apply(this, arguments);
-            },
-
-            atLeast: function atLeast(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.maxCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.minCalls = num;
-
-                return this;
-            },
-
-            atMost: function atMost(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.minCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.maxCalls = num;
-
-                return this;
-            },
-
-            never: function never() {
-                return this.exactly(0);
-            },
-
-            once: function once() {
-                return this.exactly(1);
-            },
-
-            twice: function twice() {
-                return this.exactly(2);
-            },
-
-            thrice: function thrice() {
-                return this.exactly(3);
-            },
-
-            exactly: function exactly(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not a number");
-                }
-
-                this.atLeast(num);
-                return this.atMost(num);
-            },
-
-            met: function met() {
-                return !this.failed && receivedMinCalls(this);
-            },
-
-            verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
-                if (receivedMaxCalls(this)) {
-                    this.failed = true;
-                    sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
-                        this.expectedThis);
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return;
-                }
-
-                if (!args) {
-                    sinon.expectation.fail(this.method + " received no arguments, expected " +
-                        sinon.format(this.expectedArguments));
-                }
-
-                if (args.length < this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
-                        "), expected " + sinon.format(this.expectedArguments));
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
-                        "), expected " + sinon.format(this.expectedArguments));
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-
-                    if (!verifyMatcher(this.expectedArguments[i], args[i])) {
-                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
-                            ", didn't match " + this.expectedArguments.toString());
-                    }
-
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
-                            ", expected " + sinon.format(this.expectedArguments));
-                    }
-                }
-            },
-
-            allowsCall: function allowsCall(thisValue, args) {
-                if (this.met() && receivedMaxCalls(this)) {
-                    return false;
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    return false;
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return true;
-                }
-
-                args = args || [];
-
-                if (args.length < this.expectedArguments.length) {
-                    return false;
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    return false;
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-                    if (!verifyMatcher(this.expectedArguments[i], args[i])) {
-                        return false;
-                    }
-
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            },
-
-            withArgs: function withArgs() {
-                this.expectedArguments = slice.call(arguments);
-                return this;
-            },
-
-            withExactArgs: function withExactArgs() {
-                this.withArgs.apply(this, arguments);
-                this.expectsExactArgCount = true;
-                return this;
-            },
-
-            on: function on(thisValue) {
-                this.expectedThis = thisValue;
-                return this;
-            },
-
-            toString: function () {
-                var args = (this.expectedArguments || []).slice();
-
-                if (!this.expectsExactArgCount) {
-                    push.call(args, "[...]");
-                }
-
-                var callStr = sinon.spyCall.toString.call({
-                    proxy: this.method || "anonymous mock expectation",
-                    args: args
-                });
-
-                var message = callStr.replace(", [...", "[, ...") + " " +
-                    expectedCallCountInWords(this);
-
-                if (this.met()) {
-                    return "Expectation met: " + message;
-                }
-
-                return "Expected " + message + " (" +
-                    callCountInWords(this.callCount) + ")";
-            },
-
-            verify: function verify() {
-                if (!this.met()) {
-                    sinon.expectation.fail(this.toString());
-                } else {
-                    sinon.expectation.pass(this.toString());
-                }
-
-                return true;
-            },
-
-            pass: function pass(message) {
-                sinon.assert.pass(message);
-            },
-
-            fail: function fail(message) {
-                var exception = new Error(message);
-                exception.name = "ExpectationError";
-
-                throw exception;
-            }
-        };
-
-        sinon.mock = mock;
-        return mock;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./times_in_words");
-        require("./call");
-        require("./extend");
-        require("./match");
-        require("./spy");
-        require("./stub");
-        require("./format");
-
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- * @depend spy.js
- * @depend stub.js
- * @depend mock.js
- */
-/**
- * Collections of stubs, spies and mocks.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var push = [].push;
-    var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-    function getFakes(fakeCollection) {
-        if (!fakeCollection.fakes) {
-            fakeCollection.fakes = [];
-        }
-
-        return fakeCollection.fakes;
-    }
-
-    function each(fakeCollection, method) {
-        var fakes = getFakes(fakeCollection);
-
-        for (var i = 0, l = fakes.length; i < l; i += 1) {
-            if (typeof fakes[i][method] == "function") {
-                fakes[i][method]();
-            }
-        }
-    }
-
-    function compact(fakeCollection) {
-        var fakes = getFakes(fakeCollection);
-        var i = 0;
-        while (i < fakes.length) {
-            fakes.splice(i, 1);
-        }
-    }
-
-    function makeApi(sinon) {
-        var collection = {
-            verify: function resolve() {
-                each(this, "verify");
-            },
-
-            restore: function restore() {
-                each(this, "restore");
-                compact(this);
-            },
-
-            reset: function restore() {
-                each(this, "reset");
-            },
-
-            verifyAndRestore: function verifyAndRestore() {
-                var exception;
-
-                try {
-                    this.verify();
-                } catch (e) {
-                    exception = e;
-                }
-
-                this.restore();
-
-                if (exception) {
-                    throw exception;
-                }
-            },
-
-            add: function add(fake) {
-                push.call(getFakes(this), fake);
-                return fake;
-            },
-
-            spy: function spy() {
-                return this.add(sinon.spy.apply(sinon, arguments));
-            },
-
-            stub: function stub(object, property, value) {
-                if (property) {
-                    var original = object[property];
-
-                    if (typeof original != "function") {
-                        if (!hasOwnProperty.call(object, property)) {
-                            throw new TypeError("Cannot stub non-existent own property " + property);
-                        }
-
-                        object[property] = value;
-
-                        return this.add({
-                            restore: function () {
-                                object[property] = original;
-                            }
-                        });
-                    }
-                }
-                if (!property && !!object && typeof object == "object") {
-                    var stubbedObj = sinon.stub.apply(sinon, arguments);
-
-                    for (var prop in stubbedObj) {
-                        if (typeof stubbedObj[prop] === "function") {
-                            this.add(stubbedObj[prop]);
-                        }
-                    }
-
-                    return stubbedObj;
-                }
-
-                return this.add(sinon.stub.apply(sinon, arguments));
-            },
-
-            mock: function mock() {
-                return this.add(sinon.mock.apply(sinon, arguments));
-            },
-
-            inject: function inject(obj) {
-                var col = this;
-
-                obj.spy = function () {
-                    return col.spy.apply(col, arguments);
-                };
-
-                obj.stub = function () {
-                    return col.stub.apply(col, arguments);
-                };
-
-                obj.mock = function () {
-                    return col.mock.apply(col, arguments);
-                };
-
-                return obj;
-            }
-        };
-
-        sinon.collection = collection;
-        return collection;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./mock");
-        require("./spy");
-        require("./stub");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/*global lolex */
-
-/**
- * Fake timer API
- * setTimeout
- * setInterval
- * clearTimeout
- * clearInterval
- * tick
- * reset
- * Date
- *
- * Inspired by jsUnitMockTimeOut from JsUnit
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-(function (global) {
-    function makeApi(sinon, lol) {
-        var llx = typeof lolex !== "undefined" ? lolex : lol;
-
-        sinon.useFakeTimers = function () {
-            var now, methods = Array.prototype.slice.call(arguments);
-
-            if (typeof methods[0] === "string") {
-                now = 0;
-            } else {
-                now = methods.shift();
-            }
-
-            var clock = llx.install(now || 0, methods);
-            clock.restore = clock.uninstall;
-            return clock;
-        };
-
-        sinon.clock = {
-            create: function (now) {
-                return llx.createClock(now);
-            }
-        };
-
-        sinon.timers = {
-            setTimeout: setTimeout,
-            clearTimeout: clearTimeout,
-            setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
-            clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
-            setInterval: setInterval,
-            clearInterval: clearInterval,
-            Date: Date
-        };
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, epxorts, module, lolex) {
-        var sinon = require("./core");
-        makeApi(sinon, lolex);
-        module.exports = sinon;
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module, require("lolex"));
-    } else {
-        makeApi(sinon);
-    }
-}(typeof global != "undefined" && typeof global !== "function" ? global : this));
-
-/**
- * Minimal Event interface implementation
- *
- * Original implementation by Sven Fuchs: https://gist.github.com/995028
- * Modifications and tests by Christian Johansen.
- *
- * @author Sven Fuchs (svenfuchs@artweb-design.de)
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2011 Sven Fuchs, Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    this.sinon = {};
-}
-
-(function () {
-    var push = [].push;
-
-    function makeApi(sinon) {
-        sinon.Event = function Event(type, bubbles, cancelable, target) {
-            this.initEvent(type, bubbles, cancelable, target);
-        };
-
-        sinon.Event.prototype = {
-            initEvent: function (type, bubbles, cancelable, target) {
-                this.type = type;
-                this.bubbles = bubbles;
-                this.cancelable = cancelable;
-                this.target = target;
-            },
-
-            stopPropagation: function () {},
-
-            preventDefault: function () {
-                this.defaultPrevented = true;
-            }
-        };
-
-        sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
-            this.initEvent(type, false, false, target);
-            this.loaded = progressEventRaw.loaded || null;
-            this.total = progressEventRaw.total || null;
-            this.lengthComputable = !!progressEventRaw.total;
-        };
-
-        sinon.ProgressEvent.prototype = new sinon.Event();
-
-        sinon.ProgressEvent.prototype.constructor =  sinon.ProgressEvent;
-
-        sinon.CustomEvent = function CustomEvent(type, customData, target) {
-            this.initEvent(type, false, false, target);
-            this.detail = customData.detail || null;
-        };
-
-        sinon.CustomEvent.prototype = new sinon.Event();
-
-        sinon.CustomEvent.prototype.constructor =  sinon.CustomEvent;
-
-        sinon.EventTarget = {
-            addEventListener: function addEventListener(event, listener) {
-                this.eventListeners = this.eventListeners || {};
-                this.eventListeners[event] = this.eventListeners[event] || [];
-                push.call(this.eventListeners[event], listener);
-            },
-
-            removeEventListener: function removeEventListener(event, listener) {
-                var listeners = this.eventListeners && this.eventListeners[event] || [];
-
-                for (var i = 0, l = listeners.length; i < l; ++i) {
-                    if (listeners[i] == listener) {
-                        return listeners.splice(i, 1);
-                    }
-                }
-            },
-
-            dispatchEvent: function dispatchEvent(event) {
-                var type = event.type;
-                var listeners = this.eventListeners && this.eventListeners[type] || [];
-
-                for (var i = 0; i < listeners.length; i++) {
-                    if (typeof listeners[i] == "function") {
-                        listeners[i].call(this, event);
-                    } else {
-                        listeners[i].handleEvent(event);
-                    }
-                }
-
-                return !!event.defaultPrevented;
-            }
-        };
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require) {
-        var sinon = require("./core");
-        makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require);
-    } else {
-        makeApi(sinon);
-    }
-}());
-
-/**
- * @depend util/core.js
- */
-/**
- * Logs errors
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2014 Christian Johansen
- */
-
-(function (sinon) {
-    // cache a reference to setTimeout, so that our reference won't be stubbed out
-    // when using fake timers and errors will still get logged
-    // https://github.com/cjohansen/Sinon.JS/issues/381
-    var realSetTimeout = setTimeout;
-
-    function makeApi(sinon) {
-
-        function log() {}
-
-        function logError(label, err) {
-            var msg = label + " threw exception: ";
-
-            sinon.log(msg + "[" + err.name + "] " + err.message);
-
-            if (err.stack) {
-                sinon.log(err.stack);
-            }
-
-            logError.setTimeout(function () {
-                err.message = msg + err.message;
-                throw err;
-            }, 0);
-        };
-
-        // wrap realSetTimeout with something we can stub in tests
-        logError.setTimeout = function (func, timeout) {
-            realSetTimeout(func, timeout);
-        }
-
-        var exports = {};
-        exports.log = sinon.log = log;
-        exports.logError = sinon.logError = logError;
-
-        return exports;
-    }
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        module.exports = makeApi(sinon);
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend core.js
- * @depend ../extend.js
- * @depend event.js
- * @depend ../log_error.js
- */
-/**
- * Fake XDomainRequest object
- */
-
-if (typeof sinon == "undefined") {
-    this.sinon = {};
-}
-
-// wrapper for global
-(function (global) {
-    var xdr = { XDomainRequest: global.XDomainRequest };
-    xdr.GlobalXDomainRequest = global.XDomainRequest;
-    xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
-    xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest :  false;
-
-    function makeApi(sinon) {
-        sinon.xdr = xdr;
-
-        function FakeXDomainRequest() {
-            this.readyState = FakeXDomainRequest.UNSENT;
-            this.requestBody = null;
-            this.requestHeaders = {};
-            this.status = 0;
-            this.timeout = null;
-
-            if (typeof FakeXDomainRequest.onCreate == "function") {
-                FakeXDomainRequest.onCreate(this);
-            }
-        }
-
-        function verifyState(xdr) {
-            if (xdr.readyState !== FakeXDomainRequest.OPENED) {
-                throw new Error("INVALID_STATE_ERR");
-            }
-
-            if (xdr.sendFlag) {
-                throw new Error("INVALID_STATE_ERR");
-            }
-        }
-
-        function verifyRequestSent(xdr) {
-            if (xdr.readyState == FakeXDomainRequest.UNSENT) {
-                throw new Error("Request not sent");
-            }
-            if (xdr.readyState == FakeXDomainRequest.DONE) {
-                throw new Error("Request done");
-            }
-        }
-
-        function verifyResponseBodyType(body) {
-            if (typeof body != "string") {
-                var error = new Error("Attempted to respond to fake XDomainRequest with " +
-                                    body + ", which is not a string.");
-                error.name = "InvalidBodyException";
-                throw error;
-            }
-        }
-
-        sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
-            open: function open(method, url) {
-                this.method = method;
-                this.url = url;
-
-                this.responseText = null;
-                this.sendFlag = false;
-
-                this.readyStateChange(FakeXDomainRequest.OPENED);
-            },
-
-            readyStateChange: function readyStateChange(state) {
-                this.readyState = state;
-                var eventName = "";
-                switch (this.readyState) {
-                case FakeXDomainRequest.UNSENT:
-                    break;
-                case FakeXDomainRequest.OPENED:
-                    break;
-                case FakeXDomainRequest.LOADING:
-                    if (this.sendFlag) {
-                        //raise the progress event
-                        eventName = "onprogress";
-                    }
-                    break;
-                case FakeXDomainRequest.DONE:
-                    if (this.isTimeout) {
-                        eventName = "ontimeout"
-                    } else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
-                        eventName = "onerror";
-                    } else {
-                        eventName = "onload"
-                    }
-                    break;
-                }
-
-                // raising event (if defined)
-                if (eventName) {
-                    if (typeof this[eventName] == "function") {
-                        try {
-                            this[eventName]();
-                        } catch (e) {
-                            sinon.logError("Fake XHR " + eventName + " handler", e);
-                        }
-                    }
-                }
-            },
-
-            send: function send(data) {
-                verifyState(this);
-
-                if (!/^(get|head)$/i.test(this.method)) {
-                    this.requestBody = data;
-                }
-                this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
-
-                this.errorFlag = false;
-                this.sendFlag = true;
-                this.readyStateChange(FakeXDomainRequest.OPENED);
-
-                if (typeof this.onSend == "function") {
-                    this.onSend(this);
-                }
-            },
-
-            abort: function abort() {
-                this.aborted = true;
-                this.responseText = null;
-                this.errorFlag = true;
-
-                if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
-                    this.readyStateChange(sinon.FakeXDomainRequest.DONE);
-                    this.sendFlag = false;
-                }
-            },
-
-            setResponseBody: function setResponseBody(body) {
-                verifyRequestSent(this);
-                verifyResponseBodyType(body);
-
-                var chunkSize = this.chunkSize || 10;
-                var index = 0;
-                this.responseText = "";
-
-                do {
-                    this.readyStateChange(FakeXDomainRequest.LOADING);
-                    this.responseText += body.substring(index, index + chunkSize);
-                    index += chunkSize;
-                } while (index < body.length);
-
-                this.readyStateChange(FakeXDomainRequest.DONE);
-            },
-
-            respond: function respond(status, contentType, body) {
-                // content-type ignored, since XDomainRequest does not carry this
-                // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
-                // test integration across browsers
-                this.status = typeof status == "number" ? status : 200;
-                this.setResponseBody(body || "");
-            },
-
-            simulatetimeout: function simulatetimeout() {
-                this.status = 0;
-                this.isTimeout = true;
-                // Access to this should actually throw an error
-                this.responseText = undefined;
-                this.readyStateChange(FakeXDomainRequest.DONE);
-            }
-        });
-
-        sinon.extend(FakeXDomainRequest, {
-            UNSENT: 0,
-            OPENED: 1,
-            LOADING: 3,
-            DONE: 4
-        });
-
-        sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
-            sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
-                if (xdr.supportsXDR) {
-                    global.XDomainRequest = xdr.GlobalXDomainRequest;
-                }
-
-                delete sinon.FakeXDomainRequest.restore;
-
-                if (keepOnCreate !== true) {
-                    delete sinon.FakeXDomainRequest.onCreate;
-                }
-            };
-            if (xdr.supportsXDR) {
-                global.XDomainRequest = sinon.FakeXDomainRequest;
-            }
-            return sinon.FakeXDomainRequest;
-        };
-
-        sinon.FakeXDomainRequest = FakeXDomainRequest;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./core");
-        require("../extend");
-        require("./event");
-        require("../log_error");
-        makeApi(sinon);
-        module.exports = sinon;
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else {
-        makeApi(sinon);
-    }
-})(typeof global !== "undefined" ? global : self);
-
-/**
- * @depend core.js
- * @depend ../extend.js
- * @depend event.js
- * @depend ../log_error.js
- */
-/**
- * Fake XMLHttpRequest object
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (global) {
-
-    var supportsProgress = typeof ProgressEvent !== "undefined";
-    var supportsCustomEvent = typeof CustomEvent !== "undefined";
-    var supportsFormData = typeof FormData !== "undefined";
-    var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
-    sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
-    sinonXhr.GlobalActiveXObject = global.ActiveXObject;
-    sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject != "undefined";
-    sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest != "undefined";
-    sinonXhr.workingXHR = sinonXhr.supportsXHR ? sinonXhr.GlobalXMLHttpRequest : sinonXhr.supportsActiveX
-                                     ? function () {
-                                        return new sinonXhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0")
-                                    } : false;
-    sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
-
-    /*jsl:ignore*/
-    var unsafeHeaders = {
-        "Accept-Charset": true,
-        "Accept-Encoding": true,
-        Connection: true,
-        "Content-Length": true,
-        Cookie: true,
-        Cookie2: true,
-        "Content-Transfer-Encoding": true,
-        Date: true,
-        Expect: true,
-        Host: true,
-        "Keep-Alive": true,
-        Referer: true,
-        TE: true,
-        Trailer: true,
-        "Transfer-Encoding": true,
-        Upgrade: true,
-        "User-Agent": true,
-        Via: true
-    };
-    /*jsl:end*/
-
-    // Note that for FakeXMLHttpRequest to work pre ES5
-    // we lose some of the alignment with the spec.
-    // To ensure as close a match as possible,
-    // set responseType before calling open, send or respond;
-    function FakeXMLHttpRequest() {
-        this.readyState = FakeXMLHttpRequest.UNSENT;
-        this.requestHeaders = {};
-        this.requestBody = null;
-        this.status = 0;
-        this.statusText = "";
-        this.upload = new UploadProgress();
-        this.responseType = "";
-        this.response = "";
-        if (sinonXhr.supportsCORS) {
-            this.withCredentials = false;
-        }
-
-        var xhr = this;
-        var events = ["loadstart", "load", "abort", "loadend"];
-
-        function addEventListener(eventName) {
-            xhr.addEventListener(eventName, function (event) {
-                var listener = xhr["on" + eventName];
-
-                if (listener && typeof listener == "function") {
-                    listener.call(this, event);
-                }
-            });
-        }
-
-        for (var i = events.length - 1; i >= 0; i--) {
-            addEventListener(events[i]);
-        }
-
-        if (typeof FakeXMLHttpRequest.onCreate == "function") {
-            FakeXMLHttpRequest.onCreate(this);
-        }
-    }
-
-    // An upload object is created for each
-    // FakeXMLHttpRequest and allows upload
-    // events to be simulated using uploadProgress
-    // and uploadError.
-    function UploadProgress() {
-        this.eventListeners = {
-            progress: [],
-            load: [],
-            abort: [],
-            error: []
-        }
-    }
-
-    UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
-        this.eventListeners[event].push(listener);
-    };
-
-    UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
-        var listeners = this.eventListeners[event] || [];
-
-        for (var i = 0, l = listeners.length; i < l; ++i) {
-            if (listeners[i] == listener) {
-                return listeners.splice(i, 1);
-            }
-        }
-    };
-
-    UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
-        var listeners = this.eventListeners[event.type] || [];
-
-        for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
-            listener(event);
-        }
-    };
-
-    function verifyState(xhr) {
-        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-
-        if (xhr.sendFlag) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-    }
-
-    function getHeader(headers, header) {
-        header = header.toLowerCase();
-
-        for (var h in headers) {
-            if (h.toLowerCase() == header) {
-                return h;
-            }
-        }
-
-        return null;
-    }
-
-    // filtering to enable a white-list version of Sinon FakeXhr,
-    // where whitelisted requests are passed through to real XHR
-    function each(collection, callback) {
-        if (!collection) {
-            return;
-        }
-
-        for (var i = 0, l = collection.length; i < l; i += 1) {
-            callback(collection[i]);
-        }
-    }
-    function some(collection, callback) {
-        for (var index = 0; index < collection.length; index++) {
-            if (callback(collection[index]) === true) {
-                return true;
-            }
-        }
-        return false;
-    }
-    // largest arity in XHR is 5 - XHR#open
-    var apply = function (obj, method, args) {
-        switch (args.length) {
-        case 0: return obj[method]();
-        case 1: return obj[method](args[0]);
-        case 2: return obj[method](args[0], args[1]);
-        case 3: return obj[method](args[0], args[1], args[2]);
-        case 4: return obj[method](args[0], args[1], args[2], args[3]);
-        case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
-        }
-    };
-
-    FakeXMLHttpRequest.filters = [];
-    FakeXMLHttpRequest.addFilter = function addFilter(fn) {
-        this.filters.push(fn)
-    };
-    var IE6Re = /MSIE 6/;
-    FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
-        var xhr = new sinonXhr.workingXHR();
-        each([
-            "open",
-            "setRequestHeader",
-            "send",
-            "abort",
-            "getResponseHeader",
-            "getAllResponseHeaders",
-            "addEventListener",
-            "overrideMimeType",
-            "removeEventListener"
-        ], function (method) {
-            fakeXhr[method] = function () {
-                return apply(xhr, method, arguments);
-            };
-        });
-
-        var copyAttrs = function (args) {
-            each(args, function (attr) {
-                try {
-                    fakeXhr[attr] = xhr[attr]
-                } catch (e) {
-                    if (!IE6Re.test(navigator.userAgent)) {
-                        throw e;
-                    }
-                }
-            });
-        };
-
-        var stateChange = function stateChange() {
-            fakeXhr.readyState = xhr.readyState;
-            if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                copyAttrs(["status", "statusText"]);
-            }
-            if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
-                copyAttrs(["responseText", "response"]);
-            }
-            if (xhr.readyState === FakeXMLHttpRequest.DONE) {
-                copyAttrs(["responseXML"]);
-            }
-            if (fakeXhr.onreadystatechange) {
-                fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
-            }
-        };
-
-        if (xhr.addEventListener) {
-            for (var event in fakeXhr.eventListeners) {
-                if (fakeXhr.eventListeners.hasOwnProperty(event)) {
-                    each(fakeXhr.eventListeners[event], function (handler) {
-                        xhr.addEventListener(event, handler);
-                    });
-                }
-            }
-            xhr.addEventListener("readystatechange", stateChange);
-        } else {
-            xhr.onreadystatechange = stateChange;
-        }
-        apply(xhr, "open", xhrArgs);
-    };
-    FakeXMLHttpRequest.useFilters = false;
-
-    function verifyRequestOpened(xhr) {
-        if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
-            throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
-        }
-    }
-
-    function verifyRequestSent(xhr) {
-        if (xhr.readyState == FakeXMLHttpRequest.DONE) {
-            throw new Error("Request done");
-        }
-    }
-
-    function verifyHeadersReceived(xhr) {
-        if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
-            throw new Error("No headers received");
-        }
-    }
-
-    function verifyResponseBodyType(body) {
-        if (typeof body != "string") {
-            var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
-                                 body + ", which is not a string.");
-            error.name = "InvalidBodyException";
-            throw error;
-        }
-    }
-
-    FakeXMLHttpRequest.parseXML = function parseXML(text) {
-        var xmlDoc;
-
-        if (typeof DOMParser != "undefined") {
-            var parser = new DOMParser();
-            xmlDoc = parser.parseFromString(text, "text/xml");
-        } else {
-            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
-            xmlDoc.async = "false";
-            xmlDoc.loadXML(text);
-        }
-
-        return xmlDoc;
-    };
-
-    FakeXMLHttpRequest.statusCodes = {
-        100: "Continue",
-        101: "Switching Protocols",
-        200: "OK",
-        201: "Created",
-        202: "Accepted",
-        203: "Non-Authoritative Information",
-        204: "No Content",
-        205: "Reset Content",
-        206: "Partial Content",
-        207: "Multi-Status",
-        300: "Multiple Choice",
-        301: "Moved Permanently",
-        302: "Found",
-        303: "See Other",
-        304: "Not Modified",
-        305: "Use Proxy",
-        307: "Temporary Redirect",
-        400: "Bad Request",
-        401: "Unauthorized",
-        402: "Payment Required",
-        403: "Forbidden",
-        404: "Not Found",
-        405: "Method Not Allowed",
-        406: "Not Acceptable",
-        407: "Proxy Authentication Required",
-        408: "Request Timeout",
-        409: "Conflict",
-        410: "Gone",
-        411: "Length Required",
-        412: "Precondition Failed",
-        413: "Request Entity Too Large",
-        414: "Request-URI Too Long",
-        415: "Unsupported Media Type",
-        416: "Requested Range Not Satisfiable",
-        417: "Expectation Failed",
-        422: "Unprocessable Entity",
-        500: "Internal Server Error",
-        501: "Not Implemented",
-        502: "Bad Gateway",
-        503: "Service Unavailable",
-        504: "Gateway Timeout",
-        505: "HTTP Version Not Supported"
-    };
-
-    function makeApi(sinon) {
-        sinon.xhr = sinonXhr;
-
-        sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
-            async: true,
-
-            open: function open(method, url, async, username, password) {
-                this.method = method;
-                this.url = url;
-                this.async = typeof async == "boolean" ? async : true;
-                this.username = username;
-                this.password = password;
-                this.responseText = null;
-                this.response = this.responseType === "json" ? null : "";
-                this.responseXML = null;
-                this.requestHeaders = {};
-                this.sendFlag = false;
-
-                if (FakeXMLHttpRequest.useFilters === true) {
-                    var xhrArgs = arguments;
-                    var defake = some(FakeXMLHttpRequest.filters, function (filter) {
-                        return filter.apply(this, xhrArgs)
-                    });
-                    if (defake) {
-                        return FakeXMLHttpRequest.defake(this, arguments);
-                    }
-                }
-                this.readyStateChange(FakeXMLHttpRequest.OPENED);
-            },
-
-            readyStateChange: function readyStateChange(state) {
-                this.readyState = state;
-
-                if (typeof this.onreadystatechange == "function") {
-                    try {
-                        this.onreadystatechange();
-                    } catch (e) {
-                        sinon.logError("Fake XHR onreadystatechange handler", e);
-                    }
-                }
-
-                switch (this.readyState) {
-                    case FakeXMLHttpRequest.DONE:
-                        if (supportsProgress) {
-                            this.upload.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
-                            this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
-                        }
-                        this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
-                        this.dispatchEvent(new sinon.Event("load", false, false, this));
-                        this.dispatchEvent(new sinon.Event("loadend", false, false, this));
-                        break;
-                }
-
-                this.dispatchEvent(new sinon.Event("readystatechange"));
-            },
-
-            setRequestHeader: function setRequestHeader(header, value) {
-                verifyState(this);
-
-                if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
-                    throw new Error("Refused to set unsafe header \"" + header + "\"");
-                }
-
-                if (this.requestHeaders[header]) {
-                    this.requestHeaders[header] += "," + value;
-                } else {
-                    this.requestHeaders[header] = value;
-                }
-            },
-
-            // Helps testing
-            setResponseHeaders: function setResponseHeaders(headers) {
-                verifyRequestOpened(this);
-                this.responseHeaders = {};
-
-                for (var header in headers) {
-                    if (headers.hasOwnProperty(header)) {
-                        this.responseHeaders[header] = headers[header];
-                    }
-                }
-
-                if (this.async) {
-                    this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
-                } else {
-                    this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
-                }
-            },
-
-            // Currently treats ALL data as a DOMString (i.e. no Document)
-            send: function send(data) {
-                verifyState(this);
-
-                if (!/^(get|head)$/i.test(this.method)) {
-                    var contentType = getHeader(this.requestHeaders, "Content-Type");
-                    if (this.requestHeaders[contentType]) {
-                        var value = this.requestHeaders[contentType].split(";");
-                        this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
-                    } else if (supportsFormData && !(data instanceof FormData)) {
-                        this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
-                    }
-
-                    this.requestBody = data;
-                }
-
-                this.errorFlag = false;
-                this.sendFlag = this.async;
-                this.response = this.responseType === "json" ? null : "";
-                this.readyStateChange(FakeXMLHttpRequest.OPENED);
-
-                if (typeof this.onSend == "function") {
-                    this.onSend(this);
-                }
-
-                this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
-            },
-
-            abort: function abort() {
-                this.aborted = true;
-                this.responseText = null;
-                this.response = this.responseType === "json" ? null : "";
-                this.errorFlag = true;
-                this.requestHeaders = {};
-                this.responseHeaders = {};
-
-                if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
-                    this.readyStateChange(FakeXMLHttpRequest.DONE);
-                    this.sendFlag = false;
-                }
-
-                this.readyState = FakeXMLHttpRequest.UNSENT;
-
-                this.dispatchEvent(new sinon.Event("abort", false, false, this));
-
-                this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
-
-                if (typeof this.onerror === "function") {
-                    this.onerror();
-                }
-            },
-
-            getResponseHeader: function getResponseHeader(header) {
-                if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                    return null;
-                }
-
-                if (/^Set-Cookie2?$/i.test(header)) {
-                    return null;
-                }
-
-                header = getHeader(this.responseHeaders, header);
-
-                return this.responseHeaders[header] || null;
-            },
-
-            getAllResponseHeaders: function getAllResponseHeaders() {
-                if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                    return "";
-                }
-
-                var headers = "";
-
-                for (var header in this.responseHeaders) {
-                    if (this.responseHeaders.hasOwnProperty(header) &&
-                        !/^Set-Cookie2?$/i.test(header)) {
-                        headers += header + ": " + this.responseHeaders[header] + "\r\n";
-                    }
-                }
-
-                return headers;
-            },
-
-            setResponseBody: function setResponseBody(body) {
-                verifyRequestSent(this);
-                verifyHeadersReceived(this);
-                verifyResponseBodyType(body);
-
-                var chunkSize = this.chunkSize || 10;
-                var index = 0;
-                this.responseText = "";
-
-                do {
-                    if (this.async) {
-                        this.readyStateChange(FakeXMLHttpRequest.LOADING);
-                    }
-
-                    this.responseText += body.substring(index, index + chunkSize);
-                    index += chunkSize;
-                } while (index < body.length);
-
-                var type = this.getResponseHeader("Content-Type");
-
-                if (this.responseText &&
-                    (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
-                    try {
-                        this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
-                    } catch (e) {
-                        // Unable to parse XML - no biggie
-                    }
-                }
-
-                this.response = this.responseType === "json" ? JSON.parse(this.responseText) : this.responseText;
-                this.readyStateChange(FakeXMLHttpRequest.DONE);
-            },
-
-            respond: function respond(status, headers, body) {
-                this.status = typeof status == "number" ? status : 200;
-                this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
-                this.setResponseHeaders(headers || {});
-                this.setResponseBody(body || "");
-            },
-
-            uploadProgress: function uploadProgress(progressEventRaw) {
-                if (supportsProgress) {
-                    this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
-                }
-            },
-
-            downloadProgress: function downloadProgress(progressEventRaw) {
-                if (supportsProgress) {
-                    this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
-                }
-            },
-
-            uploadError: function uploadError(error) {
-                if (supportsCustomEvent) {
-                    this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
-                }
-            }
-        });
-
-        sinon.extend(FakeXMLHttpRequest, {
-            UNSENT: 0,
-            OPENED: 1,
-            HEADERS_RECEIVED: 2,
-            LOADING: 3,
-            DONE: 4
-        });
-
-        sinon.useFakeXMLHttpRequest = function () {
-            FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
-                if (sinonXhr.supportsXHR) {
-                    global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
-                }
-
-                if (sinonXhr.supportsActiveX) {
-                    global.ActiveXObject = sinonXhr.GlobalActiveXObject;
-                }
-
-                delete FakeXMLHttpRequest.restore;
-
-                if (keepOnCreate !== true) {
-                    delete FakeXMLHttpRequest.onCreate;
-                }
-            };
-            if (sinonXhr.supportsXHR) {
-                global.XMLHttpRequest = FakeXMLHttpRequest;
-            }
-
-            if (sinonXhr.supportsActiveX) {
-                global.ActiveXObject = function ActiveXObject(objId) {
-                    if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
-
-                        return new FakeXMLHttpRequest();
-                    }
-
-                    return new sinonXhr.GlobalActiveXObject(objId);
-                };
-            }
-
-            return FakeXMLHttpRequest;
-        };
-
-        sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./core");
-        require("../extend");
-        require("./event");
-        require("../log_error");
-        makeApi(sinon);
-        module.exports = sinon;
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (typeof sinon === "undefined") {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-
-})(typeof global !== "undefined" ? global : self);
-
-/**
- * @depend fake_xdomain_request.js
- * @depend fake_xml_http_request.js
- * @depend ../format.js
- * @depend ../log_error.js
- */
-/**
- * The Sinon "server" mimics a web server that receives requests from
- * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
- * both synchronously and asynchronously. To respond synchronuously, canned
- * answers have to be provided upfront.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-(function () {
-    var push = [].push;
-    function F() {}
-
-    function create(proto) {
-        F.prototype = proto;
-        return new F();
-    }
-
-    function responseArray(handler) {
-        var response = handler;
-
-        if (Object.prototype.toString.call(handler) != "[object Array]") {
-            response = [200, {}, handler];
-        }
-
-        if (typeof response[2] != "string") {
-            throw new TypeError("Fake server response body should be string, but was " +
-                                typeof response[2]);
-        }
-
-        return response;
-    }
-
-    var wloc = typeof window !== "undefined" ? window.location : {};
-    var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
-
-    function matchOne(response, reqMethod, reqUrl) {
-        var rmeth = response.method;
-        var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
-        var url = response.url;
-        var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
-
-        return matchMethod && matchUrl;
-    }
-
-    function match(response, request) {
-        var requestUrl = request.url;
-
-        if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
-            requestUrl = requestUrl.replace(rCurrLoc, "");
-        }
-
-        if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
-            if (typeof response.response == "function") {
-                var ru = response.url;
-                var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
-                return response.response.apply(response, args);
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    function makeApi(sinon) {
-        sinon.fakeServer = {
-            create: function () {
-                var server = create(this);
-                if (!sinon.xhr.supportsCORS) {
-                    this.xhr = sinon.useFakeXDomainRequest();
-                } else {
-                    this.xhr = sinon.useFakeXMLHttpRequest();
-                }
-                server.requests = [];
-
-                this.xhr.onCreate = function (xhrObj) {
-                    server.addRequest(xhrObj);
-                };
-
-                return server;
-            },
-
-            addRequest: function addRequest(xhrObj) {
-                var server = this;
-                push.call(this.requests, xhrObj);
-
-                xhrObj.onSend = function () {
-                    server.handleRequest(this);
-
-                    if (server.respondImmediately) {
-                        server.respond();
-                    } else if (server.autoRespond && !server.responding) {
-                        setTimeout(function () {
-                            server.responding = false;
-                            server.respond();
-                        }, server.autoRespondAfter || 10);
-
-                        server.responding = true;
-                    }
-                };
-            },
-
-            getHTTPMethod: function getHTTPMethod(request) {
-                if (this.fakeHTTPMethods && /post/i.test(request.method)) {
-                    var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
-                    return !!matches ? matches[1] : request.method;
-                }
-
-                return request.method;
-            },
-
-            handleRequest: function handleRequest(xhr) {
-                if (xhr.async) {
-                    if (!this.queue) {
-                        this.queue = [];
-                    }
-
-                    push.call(this.queue, xhr);
-                } else {
-                    this.processRequest(xhr);
-                }
-            },
-
-            log: function log(response, request) {
-                var str;
-
-                str =  "Request:\n"  + sinon.format(request)  + "\n\n";
-                str += "Response:\n" + sinon.format(response) + "\n\n";
-
-                sinon.log(str);
-            },
-
-            respondWith: function respondWith(method, url, body) {
-                if (arguments.length == 1 && typeof method != "function") {
-                    this.response = responseArray(method);
-                    return;
-                }
-
-                if (!this.responses) {
-                    this.responses = [];
-                }
-
-                if (arguments.length == 1) {
-                    body = method;
-                    url = method = null;
-                }
-
-                if (arguments.length == 2) {
-                    body = url;
-                    url = method;
-                    method = null;
-                }
-
-                push.call(this.responses, {
-                    method: method,
-                    url: url,
-                    response: typeof body == "function" ? body : responseArray(body)
-                });
-            },
-
-            respond: function respond() {
-                if (arguments.length > 0) {
-                    this.respondWith.apply(this, arguments);
-                }
-
-                var queue = this.queue || [];
-                var requests = queue.splice(0, queue.length);
-                var request;
-
-                while (request = requests.shift()) {
-                    this.processRequest(request);
-                }
-            },
-
-            processRequest: function processRequest(request) {
-                try {
-                    if (request.aborted) {
-                        return;
-                    }
-
-                    var response = this.response || [404, {}, ""];
-
-                    if (this.responses) {
-                        for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
-                            if (match.call(this, this.responses[i], request)) {
-                                response = this.responses[i].response;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (request.readyState != 4) {
-                        this.log(response, request);
-
-                        request.respond(response[0], response[1], response[2]);
-                    }
-                } catch (e) {
-                    sinon.logError("Fake server request processing", e);
-                }
-            },
-
-            restore: function restore() {
-                return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
-            }
-        };
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./core");
-        require("./fake_xdomain_request");
-        require("./fake_xml_http_request");
-        require("../format");
-        makeApi(sinon);
-        module.exports = sinon;
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else {
-        makeApi(sinon);
-    }
-}());
-
-/**
- * @depend fake_server.js
- * @depend fake_timers.js
- */
-/**
- * Add-on for sinon.fakeServer that automatically handles a fake timer along with
- * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
- * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
- * it polls the object for completion with setInterval. Dispite the direct
- * motivation, there is nothing jQuery-specific in this file, so it can be used
- * in any environment where the ajax implementation depends on setInterval or
- * setTimeout.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function () {
-    function makeApi(sinon) {
-        function Server() {}
-        Server.prototype = sinon.fakeServer;
-
-        sinon.fakeServerWithClock = new Server();
-
-        sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
-            if (xhr.async) {
-                if (typeof setTimeout.clock == "object") {
-                    this.clock = setTimeout.clock;
-                } else {
-                    this.clock = sinon.useFakeTimers();
-                    this.resetClock = true;
-                }
-
-                if (!this.longestTimeout) {
-                    var clockSetTimeout = this.clock.setTimeout;
-                    var clockSetInterval = this.clock.setInterval;
-                    var server = this;
-
-                    this.clock.setTimeout = function (fn, timeout) {
-                        server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                        return clockSetTimeout.apply(this, arguments);
-                    };
-
-                    this.clock.setInterval = function (fn, timeout) {
-                        server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                        return clockSetInterval.apply(this, arguments);
-                    };
-                }
-            }
-
-            return sinon.fakeServer.addRequest.call(this, xhr);
-        };
-
-        sinon.fakeServerWithClock.respond = function respond() {
-            var returnVal = sinon.fakeServer.respond.apply(this, arguments);
-
-            if (this.clock) {
-                this.clock.tick(this.longestTimeout || 0);
-                this.longestTimeout = 0;
-
-                if (this.resetClock) {
-                    this.clock.restore();
-                    this.resetClock = false;
-                }
-            }
-
-            return returnVal;
-        };
-
-        sinon.fakeServerWithClock.restore = function restore() {
-            if (this.clock) {
-                this.clock.restore();
-            }
-
-            return sinon.fakeServer.restore.apply(this, arguments);
-        };
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require) {
-        var sinon = require("./core");
-        require("./fake_server");
-        require("./fake_timers");
-        makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require);
-    } else {
-        makeApi(sinon);
-    }
-}());
-
-/**
- * @depend util/core.js
- * @depend extend.js
- * @depend collection.js
- * @depend util/fake_timers.js
- * @depend util/fake_server_with_clock.js
- */
-/**
- * Manages fake collections as well as fake utilities such as Sinon's
- * timers and fake XHR implementation in one convenient object.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function () {
-    function makeApi(sinon) {
-        var push = [].push;
-
-        function exposeValue(sandbox, config, key, value) {
-            if (!value) {
-                return;
-            }
-
-            if (config.injectInto && !(key in config.injectInto)) {
-                config.injectInto[key] = value;
-                sandbox.injectedKeys.push(key);
-            } else {
-                push.call(sandbox.args, value);
-            }
-        }
-
-        function prepareSandboxFromConfig(config) {
-            var sandbox = sinon.create(sinon.sandbox);
-
-            if (config.useFakeServer) {
-                if (typeof config.useFakeServer == "object") {
-                    sandbox.serverPrototype = config.useFakeServer;
-                }
-
-                sandbox.useFakeServer();
-            }
-
-            if (config.useFakeTimers) {
-                if (typeof config.useFakeTimers == "object") {
-                    sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
-                } else {
-                    sandbox.useFakeTimers();
-                }
-            }
-
-            return sandbox;
-        }
-
-        sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
-            useFakeTimers: function useFakeTimers() {
-                this.clock = sinon.useFakeTimers.apply(sinon, arguments);
-
-                return this.add(this.clock);
-            },
-
-            serverPrototype: sinon.fakeServer,
-
-            useFakeServer: function useFakeServer() {
-                var proto = this.serverPrototype || sinon.fakeServer;
-
-                if (!proto || !proto.create) {
-                    return null;
-                }
-
-                this.server = proto.create();
-                return this.add(this.server);
-            },
-
-            inject: function (obj) {
-                sinon.collection.inject.call(this, obj);
-
-                if (this.clock) {
-                    obj.clock = this.clock;
-                }
-
-                if (this.server) {
-                    obj.server = this.server;
-                    obj.requests = this.server.requests;
-                }
-
-                obj.match = sinon.match;
-
-                return obj;
-            },
-
-            restore: function () {
-                sinon.collection.restore.apply(this, arguments);
-                this.restoreContext();
-            },
-
-            restoreContext: function () {
-                if (this.injectedKeys) {
-                    for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
-                        delete this.injectInto[this.injectedKeys[i]];
-                    }
-                    this.injectedKeys = [];
-                }
-            },
-
-            create: function (config) {
-                if (!config) {
-                    return sinon.create(sinon.sandbox);
-                }
-
-                var sandbox = prepareSandboxFromConfig(config);
-                sandbox.args = sandbox.args || [];
-                sandbox.injectedKeys = [];
-                sandbox.injectInto = config.injectInto;
-                var prop, value, exposed = sandbox.inject({});
-
-                if (config.properties) {
-                    for (var i = 0, l = config.properties.length; i < l; i++) {
-                        prop = config.properties[i];
-                        value = exposed[prop] || prop == "sandbox" && sandbox;
-                        exposeValue(sandbox, config, prop, value);
-                    }
-                } else {
-                    exposeValue(sandbox, config, "sandbox", value);
-                }
-
-                return sandbox;
-            },
-
-            match: sinon.match
-        });
-
-        sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
-
-        return sinon.sandbox;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./extend");
-        require("./util/fake_server_with_clock");
-        require("./util/fake_timers");
-        require("./collection");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}());
-
-/**
- * @depend util/core.js
- * @depend sandbox.js
- */
-/**
- * Test function, sandboxes fakes
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    function makeApi(sinon) {
-        var slice = Array.prototype.slice;
-
-        function test(callback) {
-            var type = typeof callback;
-
-            if (type != "function") {
-                throw new TypeError("sinon.test needs to wrap a test function, got " + type);
-            }
-
-            function sinonSandboxedTest() {
-                var config = sinon.getConfig(sinon.config);
-                config.injectInto = config.injectIntoThis && this || config.injectInto;
-                var sandbox = sinon.sandbox.create(config);
-                var args = slice.call(arguments);
-                var oldDone = args.length && args[args.length - 1];
-                var exception, result;
-
-                if (typeof oldDone == "function") {
-                    args[args.length - 1] = function sinonDone(result) {
-                        if (result) {
-                            sandbox.restore();
-                            throw exception;
-                        } else {
-                            sandbox.verifyAndRestore();
-                        }
-                        oldDone(result);
-                    };
-                }
-
-                try {
-                    result = callback.apply(this, args.concat(sandbox.args));
-                } catch (e) {
-                    exception = e;
-                }
-
-                if (typeof oldDone != "function") {
-                    if (typeof exception !== "undefined") {
-                        sandbox.restore();
-                        throw exception;
-                    } else {
-                        sandbox.verifyAndRestore();
-                    }
-                }
-
-                return result;
-            }
-
-            if (callback.length) {
-                return function sinonAsyncSandboxedTest(callback) {
-                    return sinonSandboxedTest.apply(this, arguments);
-                };
-            }
-
-            return sinonSandboxedTest;
-        }
-
-        test.config = {
-            injectIntoThis: true,
-            injectInto: null,
-            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-            useFakeTimers: true,
-            useFakeServer: true
-        };
-
-        sinon.test = test;
-        return test;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./sandbox");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (sinon) {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend util/core.js
- * @depend test.js
- */
-/**
- * Test case, sandboxes all test functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    function createTest(property, setUp, tearDown) {
-        return function () {
-            if (setUp) {
-                setUp.apply(this, arguments);
-            }
-
-            var exception, result;
-
-            try {
-                result = property.apply(this, arguments);
-            } catch (e) {
-                exception = e;
-            }
-
-            if (tearDown) {
-                tearDown.apply(this, arguments);
-            }
-
-            if (exception) {
-                throw exception;
-            }
-
-            return result;
-        };
-    }
-
-    function makeApi(sinon) {
-        function testCase(tests, prefix) {
-            if (!tests || typeof tests != "object") {
-                throw new TypeError("sinon.testCase needs an object with test functions");
-            }
-
-            prefix = prefix || "test";
-            var rPrefix = new RegExp("^" + prefix);
-            var methods = {}, testName, property, method;
-            var setUp = tests.setUp;
-            var tearDown = tests.tearDown;
-
-            for (testName in tests) {
-                if (tests.hasOwnProperty(testName) && !/^(setUp|tearDown)$/.test(testName)) {
-                    property = tests[testName];
-
-                    if (typeof property == "function" && rPrefix.test(testName)) {
-                        method = property;
-
-                        if (setUp || tearDown) {
-                            method = createTest(property, setUp, tearDown);
-                        }
-
-                        methods[testName] = sinon.test(method);
-                    } else {
-                        methods[testName] = tests[testName];
-                    }
-                }
-            }
-
-            return methods;
-        }
-
-        sinon.testCase = testCase;
-        return testCase;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./test");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend times_in_words.js
- * @depend util/core.js
- * @depend match.js
- * @depend format.js
- */
-/**
- * Assertions matching the test spy retrieval interface.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon, global) {
-    var slice = Array.prototype.slice;
-
-    function makeApi(sinon) {
-        var assert;
-
-        function verifyIsStub() {
-            var method;
-
-            for (var i = 0, l = arguments.length; i < l; ++i) {
-                method = arguments[i];
-
-                if (!method) {
-                    assert.fail("fake is not a spy");
-                }
-
-                if (method.proxy && method.proxy.isSinonProxy) {
-                    verifyIsStub(method.proxy);
-                } else {
-                    if (typeof method != "function") {
-                        assert.fail(method + " is not a function");
-                    }
-
-                    if (typeof method.getCall != "function") {
-                        assert.fail(method + " is not stubbed");
-                    }
-                }
-
-            }
-        }
-
-        function failAssertion(object, msg) {
-            object = object || global;
-            var failMethod = object.fail || assert.fail;
-            failMethod.call(object, msg);
-        }
-
-        function mirrorPropAsAssertion(name, method, message) {
-            if (arguments.length == 2) {
-                message = method;
-                method = name;
-            }
-
-            assert[name] = function (fake) {
-                verifyIsStub(fake);
-
-                var args = slice.call(arguments, 1);
-                var failed = false;
-
-                if (typeof method == "function") {
-                    failed = !method(fake);
-                } else {
-                    failed = typeof fake[method] == "function" ?
-                        !fake[method].apply(fake, args) : !fake[method];
-                }
-
-                if (failed) {
-                    failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
-                } else {
-                    assert.pass(name);
-                }
-            };
-        }
-
-        function exposedName(prefix, prop) {
-            return !prefix || /^fail/.test(prop) ? prop :
-                prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
-        }
-
-        assert = {
-            failException: "AssertError",
-
-            fail: function fail(message) {
-                var error = new Error(message);
-                error.name = this.failException || assert.failException;
-
-                throw error;
-            },
-
-            pass: function pass(assertion) {},
-
-            callOrder: function assertCallOrder() {
-                verifyIsStub.apply(null, arguments);
-                var expected = "", actual = "";
-
-                if (!sinon.calledInOrder(arguments)) {
-                    try {
-                        expected = [].join.call(arguments, ", ");
-                        var calls = slice.call(arguments);
-                        var i = calls.length;
-                        while (i) {
-                            if (!calls[--i].called) {
-                                calls.splice(i, 1);
-                            }
-                        }
-                        actual = sinon.orderByFirstCall(calls).join(", ");
-                    } catch (e) {
-                        // If this fails, we'll just fall back to the blank string
-                    }
-
-                    failAssertion(this, "expected " + expected + " to be " +
-                                "called in order but were called as " + actual);
-                } else {
-                    assert.pass("callOrder");
-                }
-            },
-
-            callCount: function assertCallCount(method, count) {
-                verifyIsStub(method);
-
-                if (method.callCount != count) {
-                    var msg = "expected %n to be called " + sinon.timesInWords(count) +
-                        " but was called %c%C";
-                    failAssertion(this, method.printf(msg));
-                } else {
-                    assert.pass("callCount");
-                }
-            },
-
-            expose: function expose(target, options) {
-                if (!target) {
-                    throw new TypeError("target is null or undefined");
-                }
-
-                var o = options || {};
-                var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
-                var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
-
-                for (var method in this) {
-                    if (method != "expose" && (includeFail || !/^(fail)/.test(method))) {
-                        target[exposedName(prefix, method)] = this[method];
-                    }
-                }
-
-                return target;
-            },
-
-            match: function match(actual, expectation) {
-                var matcher = sinon.match(expectation);
-                if (matcher.test(actual)) {
-                    assert.pass("match");
-                } else {
-                    var formatted = [
-                        "expected value to match",
-                        "    expected = " + sinon.format(expectation),
-                        "    actual = " + sinon.format(actual)
-                    ]
-                    failAssertion(this, formatted.join("\n"));
-                }
-            }
-        };
-
-        mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
-        mirrorPropAsAssertion("notCalled", function (spy) {
-            return !spy.called;
-        }, "expected %n to not have been called but was called %c%C");
-        mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
-        mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
-        mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
-        mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
-        mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
-        mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
-        mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
-        mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
-        mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
-        mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
-        mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
-        mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
-        mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
-        mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
-        mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
-        mirrorPropAsAssertion("threw", "%n did not throw exception%C");
-        mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
-
-        sinon.assert = assert;
-        return assert;
-    }
-
-    var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
-    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
-
-    function loadDependencies(require, exports, module) {
-        var sinon = require("./util/core");
-        require("./match");
-        require("./format");
-        module.exports = makeApi(sinon);
-    }
-
-    if (isAMD) {
-        define(loadDependencies);
-    } else if (isNode) {
-        loadDependencies(require, module.exports, module);
-    } else if (!sinon) {
-        return;
-    } else {
-        makeApi(sinon);
-    }
-
-}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
-
-  return sinon;
-}));
diff --git a/resources/lib/sinonjs/sinon-1.17.3.js b/resources/lib/sinonjs/sinon-1.17.3.js
new file mode 100644 (file)
index 0000000..d77b317
--- /dev/null
@@ -0,0 +1,6437 @@
+/**
+ * Sinon.JS 1.17.3, 2016/01/27
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
+ *
+ * (The BSD License)
+ * 
+ * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ *     * Neither the name of Christian Johansen nor the names of his contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function (root, factory) {
+  'use strict';
+  if (typeof define === 'function' && define.amd) {
+    define('sinon', [], function () {
+      return (root.sinon = factory());
+    });
+  } else if (typeof exports === 'object') {
+    module.exports = factory();
+  } else {
+    root.sinon = factory();
+  }
+}(this, function () {
+  'use strict';
+  var samsam, formatio, lolex;
+  (function () {
+                function define(mod, deps, fn) {
+                  if (mod == "samsam") {
+                    samsam = deps();
+                  } else if (typeof deps === "function" && mod.length === 0) {
+                    lolex = deps();
+                  } else if (typeof fn === "function") {
+                    formatio = fn(samsam);
+                  }
+                }
+    define.amd = {};
+((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
+ (typeof module === "object" &&
+      function (m) { module.exports = m(); }) || // Node
+ function (m) { this.samsam = m(); } // Browser globals
+)(function () {
+    var o = Object.prototype;
+    var div = typeof document !== "undefined" && document.createElement("div");
+
+    function isNaN(value) {
+        // Unlike global isNaN, this avoids type coercion
+        // typeof check avoids IE host object issues, hat tip to
+        // lodash
+        var val = value; // JsLint thinks value !== value is "weird"
+        return typeof value === "number" && value !== val;
+    }
+
+    function getClass(value) {
+        // Returns the internal [[Class]] by calling Object.prototype.toString
+        // with the provided value as this. Return value is a string, naming the
+        // internal class, e.g. "Array"
+        return o.toString.call(value).split(/[ \]]/)[1];
+    }
+
+    /**
+     * @name samsam.isArguments
+     * @param Object object
+     *
+     * Returns ``true`` if ``object`` is an ``arguments`` object,
+     * ``false`` otherwise.
+     */
+    function isArguments(object) {
+        if (getClass(object) === 'Arguments') { return true; }
+        if (typeof object !== "object" || typeof object.length !== "number" ||
+                getClass(object) === "Array") {
+            return false;
+        }
+        if (typeof object.callee == "function") { return true; }
+        try {
+            object[object.length] = 6;
+            delete object[object.length];
+        } catch (e) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @name samsam.isElement
+     * @param Object object
+     *
+     * Returns ``true`` if ``object`` is a DOM element node. Unlike
+     * Underscore.js/lodash, this function will return ``false`` if ``object``
+     * is an *element-like* object, i.e. a regular object with a ``nodeType``
+     * property that holds the value ``1``.
+     */
+    function isElement(object) {
+        if (!object || object.nodeType !== 1 || !div) { return false; }
+        try {
+            object.appendChild(div);
+            object.removeChild(div);
+        } catch (e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @name samsam.keys
+     * @param Object object
+     *
+     * Return an array of own property names.
+     */
+    function keys(object) {
+        var ks = [], prop;
+        for (prop in object) {
+            if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
+        }
+        return ks;
+    }
+
+    /**
+     * @name samsam.isDate
+     * @param Object value
+     *
+     * Returns true if the object is a ``Date``, or *date-like*. Duck typing
+     * of date objects work by checking that the object has a ``getTime``
+     * function whose return value equals the return value from the object's
+     * ``valueOf``.
+     */
+    function isDate(value) {
+        return typeof value.getTime == "function" &&
+            value.getTime() == value.valueOf();
+    }
+
+    /**
+     * @name samsam.isNegZero
+     * @param Object value
+     *
+     * Returns ``true`` if ``value`` is ``-0``.
+     */
+    function isNegZero(value) {
+        return value === 0 && 1 / value === -Infinity;
+    }
+
+    /**
+     * @name samsam.equal
+     * @param Object obj1
+     * @param Object obj2
+     *
+     * Returns ``true`` if two objects are strictly equal. Compared to
+     * ``===`` there are two exceptions:
+     *
+     *   - NaN is considered equal to NaN
+     *   - -0 and +0 are not considered equal
+     */
+    function identical(obj1, obj2) {
+        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
+            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
+        }
+    }
+
+
+    /**
+     * @name samsam.deepEqual
+     * @param Object obj1
+     * @param Object obj2
+     *
+     * Deep equal comparison. Two values are "deep equal" if:
+     *
+     *   - They are equal, according to samsam.identical
+     *   - They are both date objects representing the same time
+     *   - They are both arrays containing elements that are all deepEqual
+     *   - They are objects with the same set of properties, and each property
+     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
+     *
+     * Supports cyclic objects.
+     */
+    function deepEqualCyclic(obj1, obj2) {
+
+        // used for cyclic comparison
+        // contain already visited objects
+        var objects1 = [],
+            objects2 = [],
+        // contain pathes (position in the object structure)
+        // of the already visited objects
+        // indexes same as in objects arrays
+            paths1 = [],
+            paths2 = [],
+        // contains combinations of already compared objects
+        // in the manner: { "$1['ref']$2['ref']": true }
+            compared = {};
+
+        /**
+         * used to check, if the value of a property is an object
+         * (cyclic logic is only needed for objects)
+         * only needed for cyclic logic
+         */
+        function isObject(value) {
+
+            if (typeof value === 'object' && value !== null &&
+                    !(value instanceof Boolean) &&
+                    !(value instanceof Date)    &&
+                    !(value instanceof Number)  &&
+                    !(value instanceof RegExp)  &&
+                    !(value instanceof String)) {
+
+                return true;
+            }
+
+            return false;
+        }
+
+        /**
+         * returns the index of the given object in the
+         * given objects array, -1 if not contained
+         * only needed for cyclic logic
+         */
+        function getIndex(objects, obj) {
+
+            var i;
+            for (i = 0; i < objects.length; i++) {
+                if (objects[i] === obj) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        // does the recursion for the deep equal check
+        return (function deepEqual(obj1, obj2, path1, path2) {
+            var type1 = typeof obj1;
+            var type2 = typeof obj2;
+
+            // == null also matches undefined
+            if (obj1 === obj2 ||
+                    isNaN(obj1) || isNaN(obj2) ||
+                    obj1 == null || obj2 == null ||
+                    type1 !== "object" || type2 !== "object") {
+
+                return identical(obj1, obj2);
+            }
+
+            // Elements are only equal if identical(expected, actual)
+            if (isElement(obj1) || isElement(obj2)) { return false; }
+
+            var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
+            if (isDate1 || isDate2) {
+                if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
+                    return false;
+                }
+            }
+
+            if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
+                if (obj1.toString() !== obj2.toString()) { return false; }
+            }
+
+            var class1 = getClass(obj1);
+            var class2 = getClass(obj2);
+            var keys1 = keys(obj1);
+            var keys2 = keys(obj2);
+
+            if (isArguments(obj1) || isArguments(obj2)) {
+                if (obj1.length !== obj2.length) { return false; }
+            } else {
+                if (type1 !== type2 || class1 !== class2 ||
+                        keys1.length !== keys2.length) {
+                    return false;
+                }
+            }
+
+            var key, i, l,
+                // following vars are used for the cyclic logic
+                value1, value2,
+                isObject1, isObject2,
+                index1, index2,
+                newPath1, newPath2;
+
+            for (i = 0, l = keys1.length; i < l; i++) {
+                key = keys1[i];
+                if (!o.hasOwnProperty.call(obj2, key)) {
+                    return false;
+                }
+
+                // Start of the cyclic logic
+
+                value1 = obj1[key];
+                value2 = obj2[key];
+
+                isObject1 = isObject(value1);
+                isObject2 = isObject(value2);
+
+                // determine, if the objects were already visited
+                // (it's faster to check for isObject first, than to
+                // get -1 from getIndex for non objects)
+                index1 = isObject1 ? getIndex(objects1, value1) : -1;
+                index2 = isObject2 ? getIndex(objects2, value2) : -1;
+
+                // determine the new pathes of the objects
+                // - for non cyclic objects the current path will be extended
+                //   by current property name
+                // - for cyclic objects the stored path is taken
+                newPath1 = index1 !== -1
+                    ? paths1[index1]
+                    : path1 + '[' + JSON.stringify(key) + ']';
+                newPath2 = index2 !== -1
+                    ? paths2[index2]
+                    : path2 + '[' + JSON.stringify(key) + ']';
+
+                // stop recursion if current objects are already compared
+                if (compared[newPath1 + newPath2]) {
+                    return true;
+                }
+
+                // remember the current objects and their pathes
+                if (index1 === -1 && isObject1) {
+                    objects1.push(value1);
+                    paths1.push(newPath1);
+                }
+                if (index2 === -1 && isObject2) {
+                    objects2.push(value2);
+                    paths2.push(newPath2);
+                }
+
+                // remember that the current objects are already compared
+                if (isObject1 && isObject2) {
+                    compared[newPath1 + newPath2] = true;
+                }
+
+                // End of cyclic logic
+
+                // neither value1 nor value2 is a cycle
+                // continue with next level
+                if (!deepEqual(value1, value2, newPath1, newPath2)) {
+                    return false;
+                }
+            }
+
+            return true;
+
+        }(obj1, obj2, '$1', '$2'));
+    }
+
+    var match;
+
+    function arrayContains(array, subset) {
+        if (subset.length === 0) { return true; }
+        var i, l, j, k;
+        for (i = 0, l = array.length; i < l; ++i) {
+            if (match(array[i], subset[0])) {
+                for (j = 0, k = subset.length; j < k; ++j) {
+                    if (!match(array[i + j], subset[j])) { return false; }
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @name samsam.match
+     * @param Object object
+     * @param Object matcher
+     *
+     * Compare arbitrary value ``object`` with matcher.
+     */
+    match = function match(object, matcher) {
+        if (matcher && typeof matcher.test === "function") {
+            return matcher.test(object);
+        }
+
+        if (typeof matcher === "function") {
+            return matcher(object) === true;
+        }
+
+        if (typeof matcher === "string") {
+            matcher = matcher.toLowerCase();
+            var notNull = typeof object === "string" || !!object;
+            return notNull &&
+                (String(object)).toLowerCase().indexOf(matcher) >= 0;
+        }
+
+        if (typeof matcher === "number") {
+            return matcher === object;
+        }
+
+        if (typeof matcher === "boolean") {
+            return matcher === object;
+        }
+
+        if (typeof(matcher) === "undefined") {
+            return typeof(object) === "undefined";
+        }
+
+        if (matcher === null) {
+            return object === null;
+        }
+
+        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
+            return arrayContains(object, matcher);
+        }
+
+        if (matcher && typeof matcher === "object") {
+            if (matcher === object) {
+                return true;
+            }
+            var prop;
+            for (prop in matcher) {
+                var value = object[prop];
+                if (typeof value === "undefined" &&
+                        typeof object.getAttribute === "function") {
+                    value = object.getAttribute(prop);
+                }
+                if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
+                    if (value !== matcher[prop]) {
+                        return false;
+                    }
+                } else if (typeof  value === "undefined" || !match(value, matcher[prop])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        throw new Error("Matcher was not a string, a number, a " +
+                        "function, a boolean or an object");
+    };
+
+    return {
+        isArguments: isArguments,
+        isElement: isElement,
+        isDate: isDate,
+        isNegZero: isNegZero,
+        identical: identical,
+        deepEqual: deepEqualCyclic,
+        match: match,
+        keys: keys
+    };
+});
+((typeof define === "function" && define.amd && function (m) {
+    define("formatio", ["samsam"], m);
+}) || (typeof module === "object" && function (m) {
+    module.exports = m(require("samsam"));
+}) || function (m) { this.formatio = m(this.samsam); }
+)(function (samsam) {
+    
+    var formatio = {
+        excludeConstructors: ["Object", /^.$/],
+        quoteStrings: true,
+        limitChildrenCount: 0
+    };
+
+    var hasOwn = Object.prototype.hasOwnProperty;
+
+    var specialObjects = [];
+    if (typeof global !== "undefined") {
+        specialObjects.push({ object: global, value: "[object global]" });
+    }
+    if (typeof document !== "undefined") {
+        specialObjects.push({
+            object: document,
+            value: "[object HTMLDocument]"
+        });
+    }
+    if (typeof window !== "undefined") {
+        specialObjects.push({ object: window, value: "[object Window]" });
+    }
+
+    function functionName(func) {
+        if (!func) { return ""; }
+        if (func.displayName) { return func.displayName; }
+        if (func.name) { return func.name; }
+        var matches = func.toString().match(/function\s+([^\(]+)/m);
+        return (matches && matches[1]) || "";
+    }
+
+    function constructorName(f, object) {
+        var name = functionName(object && object.constructor);
+        var excludes = f.excludeConstructors ||
+                formatio.excludeConstructors || [];
+
+        var i, l;
+        for (i = 0, l = excludes.length; i < l; ++i) {
+            if (typeof excludes[i] === "string" && excludes[i] === name) {
+                return "";
+            } else if (excludes[i].test && excludes[i].test(name)) {
+                return "";
+            }
+        }
+
+        return name;
+    }
+
+    function isCircular(object, objects) {
+        if (typeof object !== "object") { return false; }
+        var i, l;
+        for (i = 0, l = objects.length; i < l; ++i) {
+            if (objects[i] === object) { return true; }
+        }
+        return false;
+    }
+
+    function ascii(f, object, processed, indent) {
+        if (typeof object === "string") {
+            var qs = f.quoteStrings;
+            var quote = typeof qs !== "boolean" || qs;
+            return processed || quote ? '"' + object + '"' : object;
+        }
+
+        if (typeof object === "function" && !(object instanceof RegExp)) {
+            return ascii.func(object);
+        }
+
+        processed = processed || [];
+
+        if (isCircular(object, processed)) { return "[Circular]"; }
+
+        if (Object.prototype.toString.call(object) === "[object Array]") {
+            return ascii.array.call(f, object, processed);
+        }
+
+        if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
+        if (samsam.isElement(object)) { return ascii.element(object); }
+
+        if (typeof object.toString === "function" &&
+                object.toString !== Object.prototype.toString) {
+            return object.toString();
+        }
+
+        var i, l;
+        for (i = 0, l = specialObjects.length; i < l; i++) {
+            if (object === specialObjects[i].object) {
+                return specialObjects[i].value;
+            }
+        }
+
+        return ascii.object.call(f, object, processed, indent);
+    }
+
+    ascii.func = function (func) {
+        return "function " + functionName(func) + "() {}";
+    };
+
+    ascii.array = function (array, processed) {
+        processed = processed || [];
+        processed.push(array);
+        var pieces = [];
+        var i, l;
+        l = (this.limitChildrenCount > 0) ? 
+            Math.min(this.limitChildrenCount, array.length) : array.length;
+
+        for (i = 0; i < l; ++i) {
+            pieces.push(ascii(this, array[i], processed));
+        }
+
+        if(l < array.length)
+            pieces.push("[... " + (array.length - l) + " more elements]");
+
+        return "[" + pieces.join(", ") + "]";
+    };
+
+    ascii.object = function (object, processed, indent) {
+        processed = processed || [];
+        processed.push(object);
+        indent = indent || 0;
+        var pieces = [], properties = samsam.keys(object).sort();
+        var length = 3;
+        var prop, str, obj, i, k, l;
+        l = (this.limitChildrenCount > 0) ? 
+            Math.min(this.limitChildrenCount, properties.length) : properties.length;
+
+        for (i = 0; i < l; ++i) {
+            prop = properties[i];
+            obj = object[prop];
+
+            if (isCircular(obj, processed)) {
+                str = "[Circular]";
+            } else {
+                str = ascii(this, obj, processed, indent + 2);
+            }
+
+            str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
+            length += str.length;
+            pieces.push(str);
+        }
+
+        var cons = constructorName(this, object);
+        var prefix = cons ? "[" + cons + "] " : "";
+        var is = "";
+        for (i = 0, k = indent; i < k; ++i) { is += " "; }
+
+        if(l < properties.length)
+            pieces.push("[... " + (properties.length - l) + " more elements]");
+
+        if (length + indent > 80) {
+            return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
+                is + "}";
+        }
+        return prefix + "{ " + pieces.join(", ") + " }";
+    };
+
+    ascii.element = function (element) {
+        var tagName = element.tagName.toLowerCase();
+        var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
+
+        for (i = 0, l = attrs.length; i < l; ++i) {
+            attr = attrs.item(i);
+            attrName = attr.nodeName.toLowerCase().replace("html:", "");
+            val = attr.nodeValue;
+            if (attrName !== "contenteditable" || val !== "inherit") {
+                if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
+            }
+        }
+
+        var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
+        var content = element.innerHTML;
+
+        if (content.length > 20) {
+            content = content.substr(0, 20) + "[...]";
+        }
+
+        var res = formatted + pairs.join(" ") + ">" + content +
+                "</" + tagName + ">";
+
+        return res.replace(/ contentEditable="inherit"/, "");
+    };
+
+    function Formatio(options) {
+        for (var opt in options) {
+            this[opt] = options[opt];
+        }
+    }
+
+    Formatio.prototype = {
+        functionName: functionName,
+
+        configure: function (options) {
+            return new Formatio(options);
+        },
+
+        constructorName: function (object) {
+            return constructorName(this, object);
+        },
+
+        ascii: function (object, processed, indent) {
+            return ascii(this, object, processed, indent);
+        }
+    };
+
+    return Formatio.prototype;
+});
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.lolex=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+(function (global){
+/*global global, window*/
+/**
+ * @author Christian Johansen (christian@cjohansen.no) and contributors
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+
+(function (global) {
+    
+    // Make properties writable in IE, as per
+    // http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
+    // JSLint being anal
+    var glbl = global;
+
+    global.setTimeout = glbl.setTimeout;
+    global.clearTimeout = glbl.clearTimeout;
+    global.setInterval = glbl.setInterval;
+    global.clearInterval = glbl.clearInterval;
+    global.Date = glbl.Date;
+
+    // setImmediate is not a standard function
+    // avoid adding the prop to the window object if not present
+    if('setImmediate' in global) {
+        global.setImmediate = glbl.setImmediate;
+        global.clearImmediate = glbl.clearImmediate;
+    }
+
+    // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
+    // browsers, a number.
+    // see https://github.com/cjohansen/Sinon.JS/pull/436
+
+    var NOOP = function () { return undefined; };
+    var timeoutResult = setTimeout(NOOP, 0);
+    var addTimerReturnsObject = typeof timeoutResult === "object";
+    clearTimeout(timeoutResult);
+
+    var NativeDate = Date;
+    var uniqueTimerId = 1;
+
+    /**
+     * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
+     * number of milliseconds. This is used to support human-readable strings passed
+     * to clock.tick()
+     */
+    function parseTime(str) {
+        if (!str) {
+            return 0;
+        }
+
+        var strings = str.split(":");
+        var l = strings.length, i = l;
+        var ms = 0, parsed;
+
+        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
+            throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
+        }
+
+        while (i--) {
+            parsed = parseInt(strings[i], 10);
+
+            if (parsed >= 60) {
+                throw new Error("Invalid time " + str);
+            }
+
+            ms += parsed * Math.pow(60, (l - i - 1));
+        }
+
+        return ms * 1000;
+    }
+
+    /**
+     * Used to grok the `now` parameter to createClock.
+     */
+    function getEpoch(epoch) {
+        if (!epoch) { return 0; }
+        if (typeof epoch.getTime === "function") { return epoch.getTime(); }
+        if (typeof epoch === "number") { return epoch; }
+        throw new TypeError("now should be milliseconds since UNIX epoch");
+    }
+
+    function inRange(from, to, timer) {
+        return timer && timer.callAt >= from && timer.callAt <= to;
+    }
+
+    function mirrorDateProperties(target, source) {
+        var prop;
+        for (prop in source) {
+            if (source.hasOwnProperty(prop)) {
+                target[prop] = source[prop];
+            }
+        }
+
+        // set special now implementation
+        if (source.now) {
+            target.now = function now() {
+                return target.clock.now;
+            };
+        } else {
+            delete target.now;
+        }
+
+        // set special toSource implementation
+        if (source.toSource) {
+            target.toSource = function toSource() {
+                return source.toSource();
+            };
+        } else {
+            delete target.toSource;
+        }
+
+        // set special toString implementation
+        target.toString = function toString() {
+            return source.toString();
+        };
+
+        target.prototype = source.prototype;
+        target.parse = source.parse;
+        target.UTC = source.UTC;
+        target.prototype.toUTCString = source.prototype.toUTCString;
+
+        return target;
+    }
+
+    function createDate() {
+        function ClockDate(year, month, date, hour, minute, second, ms) {
+            // Defensive and verbose to avoid potential harm in passing
+            // explicit undefined when user does not pass argument
+            switch (arguments.length) {
+            case 0:
+                return new NativeDate(ClockDate.clock.now);
+            case 1:
+                return new NativeDate(year);
+            case 2:
+                return new NativeDate(year, month);
+            case 3:
+                return new NativeDate(year, month, date);
+            case 4:
+                return new NativeDate(year, month, date, hour);
+            case 5:
+                return new NativeDate(year, month, date, hour, minute);
+            case 6:
+                return new NativeDate(year, month, date, hour, minute, second);
+            default:
+                return new NativeDate(year, month, date, hour, minute, second, ms);
+            }
+        }
+
+        return mirrorDateProperties(ClockDate, NativeDate);
+    }
+
+    function addTimer(clock, timer) {
+        if (timer.func === undefined) {
+            throw new Error("Callback must be provided to timer calls");
+        }
+
+        if (!clock.timers) {
+            clock.timers = {};
+        }
+
+        timer.id = uniqueTimerId++;
+        timer.createdAt = clock.now;
+        timer.callAt = clock.now + (timer.delay || (clock.duringTick ? 1 : 0));
+
+        clock.timers[timer.id] = timer;
+
+        if (addTimerReturnsObject) {
+            return {
+                id: timer.id,
+                ref: NOOP,
+                unref: NOOP
+            };
+        }
+
+        return timer.id;
+    }
+
+
+    function compareTimers(a, b) {
+        // Sort first by absolute timing
+        if (a.callAt < b.callAt) {
+            return -1;
+        }
+        if (a.callAt > b.callAt) {
+            return 1;
+        }
+
+        // Sort next by immediate, immediate timers take precedence
+        if (a.immediate && !b.immediate) {
+            return -1;
+        }
+        if (!a.immediate && b.immediate) {
+            return 1;
+        }
+
+        // Sort next by creation time, earlier-created timers take precedence
+        if (a.createdAt < b.createdAt) {
+            return -1;
+        }
+        if (a.createdAt > b.createdAt) {
+            return 1;
+        }
+
+        // Sort next by id, lower-id timers take precedence
+        if (a.id < b.id) {
+            return -1;
+        }
+        if (a.id > b.id) {
+            return 1;
+        }
+
+        // As timer ids are unique, no fallback `0` is necessary
+    }
+
+    function firstTimerInRange(clock, from, to) {
+        var timers = clock.timers,
+            timer = null,
+            id,
+            isInRange;
+
+        for (id in timers) {
+            if (timers.hasOwnProperty(id)) {
+                isInRange = inRange(from, to, timers[id]);
+
+                if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
+                    timer = timers[id];
+                }
+            }
+        }
+
+        return timer;
+    }
+
+    function firstTimer(clock) {
+        var timers = clock.timers,
+            timer = null,
+            id;
+
+        for (id in timers) {
+            if (timers.hasOwnProperty(id)) {
+                if (!timer || compareTimers(timer, timers[id]) === 1) {
+                    timer = timers[id];
+                }
+            }
+        }
+
+        return timer;
+    }
+
+    function callTimer(clock, timer) {
+        var exception;
+
+        if (typeof timer.interval === "number") {
+            clock.timers[timer.id].callAt += timer.interval;
+        } else {
+            delete clock.timers[timer.id];
+        }
+
+        try {
+            if (typeof timer.func === "function") {
+                timer.func.apply(null, timer.args);
+            } else {
+                eval(timer.func);
+            }
+        } catch (e) {
+            exception = e;
+        }
+
+        if (!clock.timers[timer.id]) {
+            if (exception) {
+                throw exception;
+            }
+            return;
+        }
+
+        if (exception) {
+            throw exception;
+        }
+    }
+
+    function timerType(timer) {
+        if (timer.immediate) {
+            return "Immediate";
+        } else if (typeof timer.interval !== "undefined") {
+            return "Interval";
+        } else {
+            return "Timeout";
+        }
+    }
+
+    function clearTimer(clock, timerId, ttype) {
+        if (!timerId) {
+            // null appears to be allowed in most browsers, and appears to be
+            // relied upon by some libraries, like Bootstrap carousel
+            return;
+        }
+
+        if (!clock.timers) {
+            clock.timers = [];
+        }
+
+        // in Node, timerId is an object with .ref()/.unref(), and
+        // its .id field is the actual timer id.
+        if (typeof timerId === "object") {
+            timerId = timerId.id;
+        }
+
+        if (clock.timers.hasOwnProperty(timerId)) {
+            // check that the ID matches a timer of the correct type
+            var timer = clock.timers[timerId];
+            if (timerType(timer) === ttype) {
+                delete clock.timers[timerId];
+            } else {
+                               throw new Error("Cannot clear timer: timer created with set" + ttype + "() but cleared with clear" + timerType(timer) + "()");
+                       }
+        }
+    }
+
+    function uninstall(clock, target) {
+        var method,
+            i,
+            l;
+
+        for (i = 0, l = clock.methods.length; i < l; i++) {
+            method = clock.methods[i];
+
+            if (target[method].hadOwnProperty) {
+                target[method] = clock["_" + method];
+            } else {
+                try {
+                    delete target[method];
+                } catch (ignore) {}
+            }
+        }
+
+        // Prevent multiple executions which will completely remove these props
+        clock.methods = [];
+    }
+
+    function hijackMethod(target, method, clock) {
+        var prop;
+
+        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
+        clock["_" + method] = target[method];
+
+        if (method === "Date") {
+            var date = mirrorDateProperties(clock[method], target[method]);
+            target[method] = date;
+        } else {
+            target[method] = function () {
+                return clock[method].apply(clock, arguments);
+            };
+
+            for (prop in clock[method]) {
+                if (clock[method].hasOwnProperty(prop)) {
+                    target[method][prop] = clock[method][prop];
+                }
+            }
+        }
+
+        target[method].clock = clock;
+    }
+
+    var timers = {
+        setTimeout: setTimeout,
+        clearTimeout: clearTimeout,
+        setImmediate: global.setImmediate,
+        clearImmediate: global.clearImmediate,
+        setInterval: setInterval,
+        clearInterval: clearInterval,
+        Date: Date
+    };
+
+    var keys = Object.keys || function (obj) {
+        var ks = [],
+            key;
+
+        for (key in obj) {
+            if (obj.hasOwnProperty(key)) {
+                ks.push(key);
+            }
+        }
+
+        return ks;
+    };
+
+    exports.timers = timers;
+
+    function createClock(now) {
+        var clock = {
+            now: getEpoch(now),
+            timeouts: {},
+            Date: createDate()
+        };
+
+        clock.Date.clock = clock;
+
+        clock.setTimeout = function setTimeout(func, timeout) {
+            return addTimer(clock, {
+                func: func,
+                args: Array.prototype.slice.call(arguments, 2),
+                delay: timeout
+            });
+        };
+
+        clock.clearTimeout = function clearTimeout(timerId) {
+            return clearTimer(clock, timerId, "Timeout");
+        };
+
+        clock.setInterval = function setInterval(func, timeout) {
+            return addTimer(clock, {
+                func: func,
+                args: Array.prototype.slice.call(arguments, 2),
+                delay: timeout,
+                interval: timeout
+            });
+        };
+
+        clock.clearInterval = function clearInterval(timerId) {
+            return clearTimer(clock, timerId, "Interval");
+        };
+
+        clock.setImmediate = function setImmediate(func) {
+            return addTimer(clock, {
+                func: func,
+                args: Array.prototype.slice.call(arguments, 1),
+                immediate: true
+            });
+        };
+
+        clock.clearImmediate = function clearImmediate(timerId) {
+            return clearTimer(clock, timerId, "Immediate");
+        };
+
+        clock.tick = function tick(ms) {
+            ms = typeof ms === "number" ? ms : parseTime(ms);
+            var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
+            var timer = firstTimerInRange(clock, tickFrom, tickTo);
+            var oldNow;
+
+            clock.duringTick = true;
+
+            var firstException;
+            while (timer && tickFrom <= tickTo) {
+                if (clock.timers[timer.id]) {
+                    tickFrom = clock.now = timer.callAt;
+                    try {
+                        oldNow = clock.now;
+                        callTimer(clock, timer);
+                        // compensate for any setSystemTime() call during timer callback
+                        if (oldNow !== clock.now) {
+                            tickFrom += clock.now - oldNow;
+                            tickTo += clock.now - oldNow;
+                            previous += clock.now - oldNow;
+                        }
+                    } catch (e) {
+                        firstException = firstException || e;
+                    }
+                }
+
+                timer = firstTimerInRange(clock, previous, tickTo);
+                previous = tickFrom;
+            }
+
+            clock.duringTick = false;
+            clock.now = tickTo;
+
+            if (firstException) {
+                throw firstException;
+            }
+
+            return clock.now;
+        };
+
+        clock.next = function next() {
+            var timer = firstTimer(clock);
+            if (!timer) {
+                return clock.now;
+            }
+
+            clock.duringTick = true;
+            try {
+                clock.now = timer.callAt;
+                callTimer(clock, timer);
+                return clock.now;
+            } finally {
+                clock.duringTick = false;
+            }
+        };
+
+        clock.reset = function reset() {
+            clock.timers = {};
+        };
+
+        clock.setSystemTime = function setSystemTime(now) {
+            // determine time difference
+            var newNow = getEpoch(now);
+            var difference = newNow - clock.now;
+
+            // update 'system clock'
+            clock.now = newNow;
+
+            // update timers and intervals to keep them stable
+            for (var id in clock.timers) {
+                if (clock.timers.hasOwnProperty(id)) {
+                    var timer = clock.timers[id];
+                    timer.createdAt += difference;
+                    timer.callAt += difference;
+                }
+            }
+        };
+
+        return clock;
+    }
+    exports.createClock = createClock;
+
+    exports.install = function install(target, now, toFake) {
+        var i,
+            l;
+
+        if (typeof target === "number") {
+            toFake = now;
+            now = target;
+            target = null;
+        }
+
+        if (!target) {
+            target = global;
+        }
+
+        var clock = createClock(now);
+
+        clock.uninstall = function () {
+            uninstall(clock, target);
+        };
+
+        clock.methods = toFake || [];
+
+        if (clock.methods.length === 0) {
+            clock.methods = keys(timers);
+        }
+
+        for (i = 0, l = clock.methods.length; i < l; i++) {
+            hijackMethod(target, clock.methods[i], clock);
+        }
+
+        return clock;
+    };
+
+}(global || this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}]},{},[1])(1)
+});
+  })();
+  var define;
+/**
+ * Sinon core utilities. For internal use only.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+var sinon = (function () {
+"use strict";
+ // eslint-disable-line no-unused-vars
+    
+    var sinonModule;
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        sinonModule = module.exports = require("./sinon/util/core");
+        require("./sinon/extend");
+        require("./sinon/walk");
+        require("./sinon/typeOf");
+        require("./sinon/times_in_words");
+        require("./sinon/spy");
+        require("./sinon/call");
+        require("./sinon/behavior");
+        require("./sinon/stub");
+        require("./sinon/mock");
+        require("./sinon/collection");
+        require("./sinon/assert");
+        require("./sinon/sandbox");
+        require("./sinon/test");
+        require("./sinon/test_case");
+        require("./sinon/match");
+        require("./sinon/format");
+        require("./sinon/log_error");
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+    } else if (isNode) {
+        loadDependencies(require, module.exports, module);
+        sinonModule = module.exports;
+    } else {
+        sinonModule = {};
+    }
+
+    return sinonModule;
+}());
+
+/**
+ * @depend ../../sinon.js
+ */
+/**
+ * Sinon core utilities. For internal use only.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    var div = typeof document !== "undefined" && document.createElement("div");
+    var hasOwn = Object.prototype.hasOwnProperty;
+
+    function isDOMNode(obj) {
+        var success = false;
+
+        try {
+            obj.appendChild(div);
+            success = div.parentNode === obj;
+        } catch (e) {
+            return false;
+        } finally {
+            try {
+                obj.removeChild(div);
+            } catch (e) {
+                // Remove failed, not much we can do about that
+            }
+        }
+
+        return success;
+    }
+
+    function isElement(obj) {
+        return div && obj && obj.nodeType === 1 && isDOMNode(obj);
+    }
+
+    function isFunction(obj) {
+        return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
+    }
+
+    function isReallyNaN(val) {
+        return typeof val === "number" && isNaN(val);
+    }
+
+    function mirrorProperties(target, source) {
+        for (var prop in source) {
+            if (!hasOwn.call(target, prop)) {
+                target[prop] = source[prop];
+            }
+        }
+    }
+
+    function isRestorable(obj) {
+        return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
+    }
+
+    // Cheap way to detect if we have ES5 support.
+    var hasES5Support = "keys" in Object;
+
+    function makeApi(sinon) {
+        sinon.wrapMethod = function wrapMethod(object, property, method) {
+            if (!object) {
+                throw new TypeError("Should wrap property of object");
+            }
+
+            if (typeof method !== "function" && typeof method !== "object") {
+                throw new TypeError("Method wrapper should be a function or a property descriptor");
+            }
+
+            function checkWrappedMethod(wrappedMethod) {
+                var error;
+
+                if (!isFunction(wrappedMethod)) {
+                    error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
+                                        property + " as function");
+                } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
+                    error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
+                } else if (wrappedMethod.calledBefore) {
+                    var verb = wrappedMethod.returns ? "stubbed" : "spied on";
+                    error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
+                }
+
+                if (error) {
+                    if (wrappedMethod && wrappedMethod.stackTrace) {
+                        error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
+                    }
+                    throw error;
+                }
+            }
+
+            var error, wrappedMethod, i;
+
+            // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
+            // when using hasOwn.call on objects from other frames.
+            var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
+
+            if (hasES5Support) {
+                var methodDesc = (typeof method === "function") ? {value: method} : method;
+                var wrappedMethodDesc = sinon.getPropertyDescriptor(object, property);
+
+                if (!wrappedMethodDesc) {
+                    error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
+                                        property + " as function");
+                } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
+                    error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
+                }
+                if (error) {
+                    if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
+                        error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
+                    }
+                    throw error;
+                }
+
+                var types = sinon.objectKeys(methodDesc);
+                for (i = 0; i < types.length; i++) {
+                    wrappedMethod = wrappedMethodDesc[types[i]];
+                    checkWrappedMethod(wrappedMethod);
+                }
+
+                mirrorProperties(methodDesc, wrappedMethodDesc);
+                for (i = 0; i < types.length; i++) {
+                    mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
+                }
+                Object.defineProperty(object, property, methodDesc);
+            } else {
+                wrappedMethod = object[property];
+                checkWrappedMethod(wrappedMethod);
+                object[property] = method;
+                method.displayName = property;
+            }
+
+            method.displayName = property;
+
+            // Set up a stack trace which can be used later to find what line of
+            // code the original method was created on.
+            method.stackTrace = (new Error("Stack Trace for original")).stack;
+
+            method.restore = function () {
+                // For prototype properties try to reset by delete first.
+                // If this fails (ex: localStorage on mobile safari) then force a reset
+                // via direct assignment.
+                if (!owned) {
+                    // In some cases `delete` may throw an error
+                    try {
+                        delete object[property];
+                    } catch (e) {} // eslint-disable-line no-empty
+                    // For native code functions `delete` fails without throwing an error
+                    // on Chrome < 43, PhantomJS, etc.
+                } else if (hasES5Support) {
+                    Object.defineProperty(object, property, wrappedMethodDesc);
+                }
+
+                // Use strict equality comparison to check failures then force a reset
+                // via direct assignment.
+                if (object[property] === method) {
+                    object[property] = wrappedMethod;
+                }
+            };
+
+            method.restore.sinon = true;
+
+            if (!hasES5Support) {
+                mirrorProperties(method, wrappedMethod);
+            }
+
+            return method;
+        };
+
+        sinon.create = function create(proto) {
+            var F = function () {};
+            F.prototype = proto;
+            return new F();
+        };
+
+        sinon.deepEqual = function deepEqual(a, b) {
+            if (sinon.match && sinon.match.isMatcher(a)) {
+                return a.test(b);
+            }
+
+            if (typeof a !== "object" || typeof b !== "object") {
+                return isReallyNaN(a) && isReallyNaN(b) || a === b;
+            }
+
+            if (isElement(a) || isElement(b)) {
+                return a === b;
+            }
+
+            if (a === b) {
+                return true;
+            }
+
+            if ((a === null && b !== null) || (a !== null && b === null)) {
+                return false;
+            }
+
+            if (a instanceof RegExp && b instanceof RegExp) {
+                return (a.source === b.source) && (a.global === b.global) &&
+                    (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
+            }
+
+            var aString = Object.prototype.toString.call(a);
+            if (aString !== Object.prototype.toString.call(b)) {
+                return false;
+            }
+
+            if (aString === "[object Date]") {
+                return a.valueOf() === b.valueOf();
+            }
+
+            var prop;
+            var aLength = 0;
+            var bLength = 0;
+
+            if (aString === "[object Array]" && a.length !== b.length) {
+                return false;
+            }
+
+            for (prop in a) {
+                if (a.hasOwnProperty(prop)) {
+                    aLength += 1;
+
+                    if (!(prop in b)) {
+                        return false;
+                    }
+
+                    if (!deepEqual(a[prop], b[prop])) {
+                        return false;
+                    }
+                }
+            }
+
+            for (prop in b) {
+                if (b.hasOwnProperty(prop)) {
+                    bLength += 1;
+                }
+            }
+
+            return aLength === bLength;
+        };
+
+        sinon.functionName = function functionName(func) {
+            var name = func.displayName || func.name;
+
+            // Use function decomposition as a last resort to get function
+            // name. Does not rely on function decomposition to work - if it
+            // doesn't debugging will be slightly less informative
+            // (i.e. toString will say 'spy' rather than 'myFunc').
+            if (!name) {
+                var matches = func.toString().match(/function ([^\s\(]+)/);
+                name = matches && matches[1];
+            }
+
+            return name;
+        };
+
+        sinon.functionToString = function toString() {
+            if (this.getCall && this.callCount) {
+                var thisValue,
+                    prop;
+                var i = this.callCount;
+
+                while (i--) {
+                    thisValue = this.getCall(i).thisValue;
+
+                    for (prop in thisValue) {
+                        if (thisValue[prop] === this) {
+                            return prop;
+                        }
+                    }
+                }
+            }
+
+            return this.displayName || "sinon fake";
+        };
+
+        sinon.objectKeys = function objectKeys(obj) {
+            if (obj !== Object(obj)) {
+                throw new TypeError("sinon.objectKeys called on a non-object");
+            }
+
+            var keys = [];
+            var key;
+            for (key in obj) {
+                if (hasOwn.call(obj, key)) {
+                    keys.push(key);
+                }
+            }
+
+            return keys;
+        };
+
+        sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
+            var proto = object;
+            var descriptor;
+
+            while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
+                proto = Object.getPrototypeOf(proto);
+            }
+            return descriptor;
+        };
+
+        sinon.getConfig = function (custom) {
+            var config = {};
+            custom = custom || {};
+            var defaults = sinon.defaultConfig;
+
+            for (var prop in defaults) {
+                if (defaults.hasOwnProperty(prop)) {
+                    config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
+                }
+            }
+
+            return config;
+        };
+
+        sinon.defaultConfig = {
+            injectIntoThis: true,
+            injectInto: null,
+            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+            useFakeTimers: true,
+            useFakeServer: true
+        };
+
+        sinon.timesInWords = function timesInWords(count) {
+            return count === 1 && "once" ||
+                count === 2 && "twice" ||
+                count === 3 && "thrice" ||
+                (count || 0) + " times";
+        };
+
+        sinon.calledInOrder = function (spies) {
+            for (var i = 1, l = spies.length; i < l; i++) {
+                if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
+                    return false;
+                }
+            }
+
+            return true;
+        };
+
+        sinon.orderByFirstCall = function (spies) {
+            return spies.sort(function (a, b) {
+                // uuid, won't ever be equal
+                var aCall = a.getCall(0);
+                var bCall = b.getCall(0);
+                var aId = aCall && aCall.callId || -1;
+                var bId = bCall && bCall.callId || -1;
+
+                return aId < bId ? -1 : 1;
+            });
+        };
+
+        sinon.createStubInstance = function (constructor) {
+            if (typeof constructor !== "function") {
+                throw new TypeError("The constructor should be a function.");
+            }
+            return sinon.stub(sinon.create(constructor.prototype));
+        };
+
+        sinon.restore = function (object) {
+            if (object !== null && typeof object === "object") {
+                for (var prop in object) {
+                    if (isRestorable(object[prop])) {
+                        object[prop].restore();
+                    }
+                }
+            } else if (isRestorable(object)) {
+                object.restore();
+            }
+        };
+
+        return sinon;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports) {
+        makeApi(exports);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+
+        // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
+        var hasDontEnumBug = (function () {
+            var obj = {
+                constructor: function () {
+                    return "0";
+                },
+                toString: function () {
+                    return "1";
+                },
+                valueOf: function () {
+                    return "2";
+                },
+                toLocaleString: function () {
+                    return "3";
+                },
+                prototype: function () {
+                    return "4";
+                },
+                isPrototypeOf: function () {
+                    return "5";
+                },
+                propertyIsEnumerable: function () {
+                    return "6";
+                },
+                hasOwnProperty: function () {
+                    return "7";
+                },
+                length: function () {
+                    return "8";
+                },
+                unique: function () {
+                    return "9";
+                }
+            };
+
+            var result = [];
+            for (var prop in obj) {
+                if (obj.hasOwnProperty(prop)) {
+                    result.push(obj[prop]());
+                }
+            }
+            return result.join("") !== "0123456789";
+        })();
+
+        /* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
+         *         override properties in previous sources.
+         *
+         * target - The Object to extend
+         * sources - Objects to copy properties from.
+         *
+         * Returns the extended target
+         */
+        function extend(target /*, sources */) {
+            var sources = Array.prototype.slice.call(arguments, 1);
+            var source, i, prop;
+
+            for (i = 0; i < sources.length; i++) {
+                source = sources[i];
+
+                for (prop in source) {
+                    if (source.hasOwnProperty(prop)) {
+                        target[prop] = source[prop];
+                    }
+                }
+
+                // Make sure we copy (own) toString method even when in JScript with DontEnum bug
+                // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
+                if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
+                    target.toString = source.toString;
+                }
+            }
+
+            return target;
+        }
+
+        sinon.extend = extend;
+        return sinon.extend;
+    }
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        module.exports = makeApi(sinon);
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+
+        function timesInWords(count) {
+            switch (count) {
+                case 1:
+                    return "once";
+                case 2:
+                    return "twice";
+                case 3:
+                    return "thrice";
+                default:
+                    return (count || 0) + " times";
+            }
+        }
+
+        sinon.timesInWords = timesInWords;
+        return sinon.timesInWords;
+    }
+
+    function loadDependencies(require, exports, module) {
+        var core = require("./util/core");
+        module.exports = makeApi(core);
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+/**
+ * Format functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        function typeOf(value) {
+            if (value === null) {
+                return "null";
+            } else if (value === undefined) {
+                return "undefined";
+            }
+            var string = Object.prototype.toString.call(value);
+            return string.substring(8, string.length - 1).toLowerCase();
+        }
+
+        sinon.typeOf = typeOf;
+        return sinon.typeOf;
+    }
+
+    function loadDependencies(require, exports, module) {
+        var core = require("./util/core");
+        module.exports = makeApi(core);
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend typeOf.js
+ */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Match functions
+ *
+ * @author Maximilian Antoni (mail@maxantoni.de)
+ * @license BSD
+ *
+ * Copyright (c) 2012 Maximilian Antoni
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        function assertType(value, type, name) {
+            var actual = sinon.typeOf(value);
+            if (actual !== type) {
+                throw new TypeError("Expected type of " + name + " to be " +
+                    type + ", but was " + actual);
+            }
+        }
+
+        var matcher = {
+            toString: function () {
+                return this.message;
+            }
+        };
+
+        function isMatcher(object) {
+            return matcher.isPrototypeOf(object);
+        }
+
+        function matchObject(expectation, actual) {
+            if (actual === null || actual === undefined) {
+                return false;
+            }
+            for (var key in expectation) {
+                if (expectation.hasOwnProperty(key)) {
+                    var exp = expectation[key];
+                    var act = actual[key];
+                    if (isMatcher(exp)) {
+                        if (!exp.test(act)) {
+                            return false;
+                        }
+                    } else if (sinon.typeOf(exp) === "object") {
+                        if (!matchObject(exp, act)) {
+                            return false;
+                        }
+                    } else if (!sinon.deepEqual(exp, act)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+
+        function match(expectation, message) {
+            var m = sinon.create(matcher);
+            var type = sinon.typeOf(expectation);
+            switch (type) {
+            case "object":
+                if (typeof expectation.test === "function") {
+                    m.test = function (actual) {
+                        return expectation.test(actual) === true;
+                    };
+                    m.message = "match(" + sinon.functionName(expectation.test) + ")";
+                    return m;
+                }
+                var str = [];
+                for (var key in expectation) {
+                    if (expectation.hasOwnProperty(key)) {
+                        str.push(key + ": " + expectation[key]);
+                    }
+                }
+                m.test = function (actual) {
+                    return matchObject(expectation, actual);
+                };
+                m.message = "match(" + str.join(", ") + ")";
+                break;
+            case "number":
+                m.test = function (actual) {
+                    // we need type coercion here
+                    return expectation == actual; // eslint-disable-line eqeqeq
+                };
+                break;
+            case "string":
+                m.test = function (actual) {
+                    if (typeof actual !== "string") {
+                        return false;
+                    }
+                    return actual.indexOf(expectation) !== -1;
+                };
+                m.message = "match(\"" + expectation + "\")";
+                break;
+            case "regexp":
+                m.test = function (actual) {
+                    if (typeof actual !== "string") {
+                        return false;
+                    }
+                    return expectation.test(actual);
+                };
+                break;
+            case "function":
+                m.test = expectation;
+                if (message) {
+                    m.message = message;
+                } else {
+                    m.message = "match(" + sinon.functionName(expectation) + ")";
+                }
+                break;
+            default:
+                m.test = function (actual) {
+                    return sinon.deepEqual(expectation, actual);
+                };
+            }
+            if (!m.message) {
+                m.message = "match(" + expectation + ")";
+            }
+            return m;
+        }
+
+        matcher.or = function (m2) {
+            if (!arguments.length) {
+                throw new TypeError("Matcher expected");
+            } else if (!isMatcher(m2)) {
+                m2 = match(m2);
+            }
+            var m1 = this;
+            var or = sinon.create(matcher);
+            or.test = function (actual) {
+                return m1.test(actual) || m2.test(actual);
+            };
+            or.message = m1.message + ".or(" + m2.message + ")";
+            return or;
+        };
+
+        matcher.and = function (m2) {
+            if (!arguments.length) {
+                throw new TypeError("Matcher expected");
+            } else if (!isMatcher(m2)) {
+                m2 = match(m2);
+            }
+            var m1 = this;
+            var and = sinon.create(matcher);
+            and.test = function (actual) {
+                return m1.test(actual) && m2.test(actual);
+            };
+            and.message = m1.message + ".and(" + m2.message + ")";
+            return and;
+        };
+
+        match.isMatcher = isMatcher;
+
+        match.any = match(function () {
+            return true;
+        }, "any");
+
+        match.defined = match(function (actual) {
+            return actual !== null && actual !== undefined;
+        }, "defined");
+
+        match.truthy = match(function (actual) {
+            return !!actual;
+        }, "truthy");
+
+        match.falsy = match(function (actual) {
+            return !actual;
+        }, "falsy");
+
+        match.same = function (expectation) {
+            return match(function (actual) {
+                return expectation === actual;
+            }, "same(" + expectation + ")");
+        };
+
+        match.typeOf = function (type) {
+            assertType(type, "string", "type");
+            return match(function (actual) {
+                return sinon.typeOf(actual) === type;
+            }, "typeOf(\"" + type + "\")");
+        };
+
+        match.instanceOf = function (type) {
+            assertType(type, "function", "type");
+            return match(function (actual) {
+                return actual instanceof type;
+            }, "instanceOf(" + sinon.functionName(type) + ")");
+        };
+
+        function createPropertyMatcher(propertyTest, messagePrefix) {
+            return function (property, value) {
+                assertType(property, "string", "property");
+                var onlyProperty = arguments.length === 1;
+                var message = messagePrefix + "(\"" + property + "\"";
+                if (!onlyProperty) {
+                    message += ", " + value;
+                }
+                message += ")";
+                return match(function (actual) {
+                    if (actual === undefined || actual === null ||
+                            !propertyTest(actual, property)) {
+                        return false;
+                    }
+                    return onlyProperty || sinon.deepEqual(value, actual[property]);
+                }, message);
+            };
+        }
+
+        match.has = createPropertyMatcher(function (actual, property) {
+            if (typeof actual === "object") {
+                return property in actual;
+            }
+            return actual[property] !== undefined;
+        }, "has");
+
+        match.hasOwn = createPropertyMatcher(function (actual, property) {
+            return actual.hasOwnProperty(property);
+        }, "hasOwn");
+
+        match.bool = match.typeOf("boolean");
+        match.number = match.typeOf("number");
+        match.string = match.typeOf("string");
+        match.object = match.typeOf("object");
+        match.func = match.typeOf("function");
+        match.array = match.typeOf("array");
+        match.regexp = match.typeOf("regexp");
+        match.date = match.typeOf("date");
+
+        sinon.match = match;
+        return match;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        require("./typeOf");
+        module.exports = makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+/**
+ * Format functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+(function (sinonGlobal, formatio) {
+    
+    function makeApi(sinon) {
+        function valueFormatter(value) {
+            return "" + value;
+        }
+
+        function getFormatioFormatter() {
+            var formatter = formatio.configure({
+                    quoteStrings: false,
+                    limitChildrenCount: 250
+                });
+
+            function format() {
+                return formatter.ascii.apply(formatter, arguments);
+            }
+
+            return format;
+        }
+
+        function getNodeFormatter() {
+            try {
+                var util = require("util");
+            } catch (e) {
+                /* Node, but no util module - would be very old, but better safe than sorry */
+            }
+
+            function format(v) {
+                var isObjectWithNativeToString = typeof v === "object" && v.toString === Object.prototype.toString;
+                return isObjectWithNativeToString ? util.inspect(v) : v;
+            }
+
+            return util ? format : valueFormatter;
+        }
+
+        var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+        var formatter;
+
+        if (isNode) {
+            try {
+                formatio = require("formatio");
+            }
+            catch (e) {} // eslint-disable-line no-empty
+        }
+
+        if (formatio) {
+            formatter = getFormatioFormatter();
+        } else if (isNode) {
+            formatter = getNodeFormatter();
+        } else {
+            formatter = valueFormatter;
+        }
+
+        sinon.format = formatter;
+        return sinon.format;
+    }
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        module.exports = makeApi(sinon);
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon, // eslint-disable-line no-undef
+    typeof formatio === "object" && formatio // eslint-disable-line no-undef
+));
+
+/**
+  * @depend util/core.js
+  * @depend match.js
+  * @depend format.js
+  */
+/**
+  * Spy calls
+  *
+  * @author Christian Johansen (christian@cjohansen.no)
+  * @author Maximilian Antoni (mail@maxantoni.de)
+  * @license BSD
+  *
+  * Copyright (c) 2010-2013 Christian Johansen
+  * Copyright (c) 2013 Maximilian Antoni
+  */
+(function (sinonGlobal) {
+    
+    var slice = Array.prototype.slice;
+
+    function makeApi(sinon) {
+        function throwYieldError(proxy, text, args) {
+            var msg = sinon.functionName(proxy) + text;
+            if (args.length) {
+                msg += " Received [" + slice.call(args).join(", ") + "]";
+            }
+            throw new Error(msg);
+        }
+
+        var callProto = {
+            calledOn: function calledOn(thisValue) {
+                if (sinon.match && sinon.match.isMatcher(thisValue)) {
+                    return thisValue.test(this.thisValue);
+                }
+                return this.thisValue === thisValue;
+            },
+
+            calledWith: function calledWith() {
+                var l = arguments.length;
+                if (l > this.args.length) {
+                    return false;
+                }
+                for (var i = 0; i < l; i += 1) {
+                    if (!sinon.deepEqual(arguments[i], this.args[i])) {
+                        return false;
+                    }
+                }
+
+                return true;
+            },
+
+            calledWithMatch: function calledWithMatch() {
+                var l = arguments.length;
+                if (l > this.args.length) {
+                    return false;
+                }
+                for (var i = 0; i < l; i += 1) {
+                    var actual = this.args[i];
+                    var expectation = arguments[i];
+                    if (!sinon.match || !sinon.match(expectation).test(actual)) {
+                        return false;
+                    }
+                }
+                return true;
+            },
+
+            calledWithExactly: function calledWithExactly() {
+                return arguments.length === this.args.length &&
+                    this.calledWith.apply(this, arguments);
+            },
+
+            notCalledWith: function notCalledWith() {
+                return !this.calledWith.apply(this, arguments);
+            },
+
+            notCalledWithMatch: function notCalledWithMatch() {
+                return !this.calledWithMatch.apply(this, arguments);
+            },
+
+            returned: function returned(value) {
+                return sinon.deepEqual(value, this.returnValue);
+            },
+
+            threw: function threw(error) {
+                if (typeof error === "undefined" || !this.exception) {
+                    return !!this.exception;
+                }
+
+                return this.exception === error || this.exception.name === error;
+            },
+
+            calledWithNew: function calledWithNew() {
+                return this.proxy.prototype && this.thisValue instanceof this.proxy;
+            },
+
+            calledBefore: function (other) {
+                return this.callId < other.callId;
+            },
+
+            calledAfter: function (other) {
+                return this.callId > other.callId;
+            },
+
+            callArg: function (pos) {
+                this.args[pos]();
+            },
+
+            callArgOn: function (pos, thisValue) {
+                this.args[pos].apply(thisValue);
+            },
+
+            callArgWith: function (pos) {
+                this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
+            },
+
+            callArgOnWith: function (pos, thisValue) {
+                var args = slice.call(arguments, 2);
+                this.args[pos].apply(thisValue, args);
+            },
+
+            "yield": function () {
+                this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
+            },
+
+            yieldOn: function (thisValue) {
+                var args = this.args;
+                for (var i = 0, l = args.length; i < l; ++i) {
+                    if (typeof args[i] === "function") {
+                        args[i].apply(thisValue, slice.call(arguments, 1));
+                        return;
+                    }
+                }
+                throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
+            },
+
+            yieldTo: function (prop) {
+                this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
+            },
+
+            yieldToOn: function (prop, thisValue) {
+                var args = this.args;
+                for (var i = 0, l = args.length; i < l; ++i) {
+                    if (args[i] && typeof args[i][prop] === "function") {
+                        args[i][prop].apply(thisValue, slice.call(arguments, 2));
+                        return;
+                    }
+                }
+                throwYieldError(this.proxy, " cannot yield to '" + prop +
+                    "' since no callback was passed.", args);
+            },
+
+            getStackFrames: function () {
+                // Omit the error message and the two top stack frames in sinon itself:
+                return this.stack && this.stack.split("\n").slice(3);
+            },
+
+            toString: function () {
+                var callStr = this.proxy ? this.proxy.toString() + "(" : "";
+                var args = [];
+
+                if (!this.args) {
+                    return ":(";
+                }
+
+                for (var i = 0, l = this.args.length; i < l; ++i) {
+                    args.push(sinon.format(this.args[i]));
+                }
+
+                callStr = callStr + args.join(", ") + ")";
+
+                if (typeof this.returnValue !== "undefined") {
+                    callStr += " => " + sinon.format(this.returnValue);
+                }
+
+                if (this.exception) {
+                    callStr += " !" + this.exception.name;
+
+                    if (this.exception.message) {
+                        callStr += "(" + this.exception.message + ")";
+                    }
+                }
+                if (this.stack) {
+                    callStr += this.getStackFrames()[0].replace(/^\s*(?:at\s+|@)?/, " at ");
+
+                }
+
+                return callStr;
+            }
+        };
+
+        callProto.invokeCallback = callProto.yield;
+
+        function createSpyCall(spy, thisValue, args, returnValue, exception, id, stack) {
+            if (typeof id !== "number") {
+                throw new TypeError("Call id is not a number");
+            }
+            var proxyCall = sinon.create(callProto);
+            proxyCall.proxy = spy;
+            proxyCall.thisValue = thisValue;
+            proxyCall.args = args;
+            proxyCall.returnValue = returnValue;
+            proxyCall.exception = exception;
+            proxyCall.callId = id;
+            proxyCall.stack = stack;
+
+            return proxyCall;
+        }
+        createSpyCall.toString = callProto.toString; // used by mocks
+
+        sinon.spyCall = createSpyCall;
+        return createSpyCall;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        require("./match");
+        require("./format");
+        module.exports = makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+  * @depend times_in_words.js
+  * @depend util/core.js
+  * @depend extend.js
+  * @depend call.js
+  * @depend format.js
+  */
+/**
+  * Spy functions
+  *
+  * @author Christian Johansen (christian@cjohansen.no)
+  * @license BSD
+  *
+  * Copyright (c) 2010-2013 Christian Johansen
+  */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        var push = Array.prototype.push;
+        var slice = Array.prototype.slice;
+        var callId = 0;
+
+        function spy(object, property, types) {
+            if (!property && typeof object === "function") {
+                return spy.create(object);
+            }
+
+            if (!object && !property) {
+                return spy.create(function () { });
+            }
+
+            if (types) {
+                var methodDesc = sinon.getPropertyDescriptor(object, property);
+                for (var i = 0; i < types.length; i++) {
+                    methodDesc[types[i]] = spy.create(methodDesc[types[i]]);
+                }
+                return sinon.wrapMethod(object, property, methodDesc);
+            }
+
+            return sinon.wrapMethod(object, property, spy.create(object[property]));
+        }
+
+        function matchingFake(fakes, args, strict) {
+            if (!fakes) {
+                return undefined;
+            }
+
+            for (var i = 0, l = fakes.length; i < l; i++) {
+                if (fakes[i].matches(args, strict)) {
+                    return fakes[i];
+                }
+            }
+        }
+
+        function incrementCallCount() {
+            this.called = true;
+            this.callCount += 1;
+            this.notCalled = false;
+            this.calledOnce = this.callCount === 1;
+            this.calledTwice = this.callCount === 2;
+            this.calledThrice = this.callCount === 3;
+        }
+
+        function createCallProperties() {
+            this.firstCall = this.getCall(0);
+            this.secondCall = this.getCall(1);
+            this.thirdCall = this.getCall(2);
+            this.lastCall = this.getCall(this.callCount - 1);
+        }
+
+        var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
+        function createProxy(func, proxyLength) {
+            // Retain the function length:
+            var p;
+            if (proxyLength) {
+                eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) + // eslint-disable-line no-eval
+                    ") { return p.invoke(func, this, slice.call(arguments)); });");
+            } else {
+                p = function proxy() {
+                    return p.invoke(func, this, slice.call(arguments));
+                };
+            }
+            p.isSinonProxy = true;
+            return p;
+        }
+
+        var uuid = 0;
+
+        // Public API
+        var spyApi = {
+            reset: function () {
+                if (this.invoking) {
+                    var err = new Error("Cannot reset Sinon function while invoking it. " +
+                                        "Move the call to .reset outside of the callback.");
+                    err.name = "InvalidResetException";
+                    throw err;
+                }
+
+                this.called = false;
+                this.notCalled = true;
+                this.calledOnce = false;
+                this.calledTwice = false;
+                this.calledThrice = false;
+                this.callCount = 0;
+                this.firstCall = null;
+                this.secondCall = null;
+                this.thirdCall = null;
+                this.lastCall = null;
+                this.args = [];
+                this.returnValues = [];
+                this.thisValues = [];
+                this.exceptions = [];
+                this.callIds = [];
+                this.stacks = [];
+                if (this.fakes) {
+                    for (var i = 0; i < this.fakes.length; i++) {
+                        this.fakes[i].reset();
+                    }
+                }
+
+                return this;
+            },
+
+            create: function create(func, spyLength) {
+                var name;
+
+                if (typeof func !== "function") {
+                    func = function () { };
+                } else {
+                    name = sinon.functionName(func);
+                }
+
+                if (!spyLength) {
+                    spyLength = func.length;
+                }
+
+                var proxy = createProxy(func, spyLength);
+
+                sinon.extend(proxy, spy);
+                delete proxy.create;
+                sinon.extend(proxy, func);
+
+                proxy.reset();
+                proxy.prototype = func.prototype;
+                proxy.displayName = name || "spy";
+                proxy.toString = sinon.functionToString;
+                proxy.instantiateFake = sinon.spy.create;
+                proxy.id = "spy#" + uuid++;
+
+                return proxy;
+            },
+
+            invoke: function invoke(func, thisValue, args) {
+                var matching = matchingFake(this.fakes, args);
+                var exception, returnValue;
+
+                incrementCallCount.call(this);
+                push.call(this.thisValues, thisValue);
+                push.call(this.args, args);
+                push.call(this.callIds, callId++);
+
+                // Make call properties available from within the spied function:
+                createCallProperties.call(this);
+
+                try {
+                    this.invoking = true;
+
+                    if (matching) {
+                        returnValue = matching.invoke(func, thisValue, args);
+                    } else {
+                        returnValue = (this.func || func).apply(thisValue, args);
+                    }
+
+                    var thisCall = this.getCall(this.callCount - 1);
+                    if (thisCall.calledWithNew() && typeof returnValue !== "object") {
+                        returnValue = thisValue;
+                    }
+                } catch (e) {
+                    exception = e;
+                } finally {
+                    delete this.invoking;
+                }
+
+                push.call(this.exceptions, exception);
+                push.call(this.returnValues, returnValue);
+                push.call(this.stacks, new Error().stack);
+
+                // Make return value and exception available in the calls:
+                createCallProperties.call(this);
+
+                if (exception !== undefined) {
+                    throw exception;
+                }
+
+                return returnValue;
+            },
+
+            named: function named(name) {
+                this.displayName = name;
+                return this;
+            },
+
+            getCall: function getCall(i) {
+                if (i < 0 || i >= this.callCount) {
+                    return null;
+                }
+
+                return sinon.spyCall(this, this.thisValues[i], this.args[i],
+                                        this.returnValues[i], this.exceptions[i],
+                                        this.callIds[i], this.stacks[i]);
+            },
+
+            getCalls: function () {
+                var calls = [];
+                var i;
+
+                for (i = 0; i < this.callCount; i++) {
+                    calls.push(this.getCall(i));
+                }
+
+                return calls;
+            },
+
+            calledBefore: function calledBefore(spyFn) {
+                if (!this.called) {
+                    return false;
+                }
+
+                if (!spyFn.called) {
+                    return true;
+                }
+
+                return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
+            },
+
+            calledAfter: function calledAfter(spyFn) {
+                if (!this.called || !spyFn.called) {
+                    return false;
+                }
+
+                return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
+            },
+
+            withArgs: function () {
+                var args = slice.call(arguments);
+
+                if (this.fakes) {
+                    var match = matchingFake(this.fakes, args, true);
+
+                    if (match) {
+                        return match;
+                    }
+                } else {
+                    this.fakes = [];
+                }
+
+                var original = this;
+                var fake = this.instantiateFake();
+                fake.matchingAguments = args;
+                fake.parent = this;
+                push.call(this.fakes, fake);
+
+                fake.withArgs = function () {
+                    return original.withArgs.apply(original, arguments);
+                };
+
+                for (var i = 0; i < this.args.length; i++) {
+                    if (fake.matches(this.args[i])) {
+                        incrementCallCount.call(fake);
+                        push.call(fake.thisValues, this.thisValues[i]);
+                        push.call(fake.args, this.args[i]);
+                        push.call(fake.returnValues, this.returnValues[i]);
+                        push.call(fake.exceptions, this.exceptions[i]);
+                        push.call(fake.callIds, this.callIds[i]);
+                    }
+                }
+                createCallProperties.call(fake);
+
+                return fake;
+            },
+
+            matches: function (args, strict) {
+                var margs = this.matchingAguments;
+
+                if (margs.length <= args.length &&
+                    sinon.deepEqual(margs, args.slice(0, margs.length))) {
+                    return !strict || margs.length === args.length;
+                }
+            },
+
+            printf: function (format) {
+                var spyInstance = this;
+                var args = slice.call(arguments, 1);
+                var formatter;
+
+                return (format || "").replace(/%(.)/g, function (match, specifyer) {
+                    formatter = spyApi.formatters[specifyer];
+
+                    if (typeof formatter === "function") {
+                        return formatter.call(null, spyInstance, args);
+                    } else if (!isNaN(parseInt(specifyer, 10))) {
+                        return sinon.format(args[specifyer - 1]);
+                    }
+
+                    return "%" + specifyer;
+                });
+            }
+        };
+
+        function delegateToCalls(method, matchAny, actual, notCalled) {
+            spyApi[method] = function () {
+                if (!this.called) {
+                    if (notCalled) {
+                        return notCalled.apply(this, arguments);
+                    }
+                    return false;
+                }
+
+                var currentCall;
+                var matches = 0;
+
+                for (var i = 0, l = this.callCount; i < l; i += 1) {
+                    currentCall = this.getCall(i);
+
+                    if (currentCall[actual || method].apply(currentCall, arguments)) {
+                        matches += 1;
+
+                        if (matchAny) {
+                            return true;
+                        }
+                    }
+                }
+
+                return matches === this.callCount;
+            };
+        }
+
+        delegateToCalls("calledOn", true);
+        delegateToCalls("alwaysCalledOn", false, "calledOn");
+        delegateToCalls("calledWith", true);
+        delegateToCalls("calledWithMatch", true);
+        delegateToCalls("alwaysCalledWith", false, "calledWith");
+        delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
+        delegateToCalls("calledWithExactly", true);
+        delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
+        delegateToCalls("neverCalledWith", false, "notCalledWith", function () {
+            return true;
+        });
+        delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () {
+            return true;
+        });
+        delegateToCalls("threw", true);
+        delegateToCalls("alwaysThrew", false, "threw");
+        delegateToCalls("returned", true);
+        delegateToCalls("alwaysReturned", false, "returned");
+        delegateToCalls("calledWithNew", true);
+        delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
+        delegateToCalls("callArg", false, "callArgWith", function () {
+            throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+        });
+        spyApi.callArgWith = spyApi.callArg;
+        delegateToCalls("callArgOn", false, "callArgOnWith", function () {
+            throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+        });
+        spyApi.callArgOnWith = spyApi.callArgOn;
+        delegateToCalls("yield", false, "yield", function () {
+            throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+        });
+        // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
+        spyApi.invokeCallback = spyApi.yield;
+        delegateToCalls("yieldOn", false, "yieldOn", function () {
+            throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+        });
+        delegateToCalls("yieldTo", false, "yieldTo", function (property) {
+            throw new Error(this.toString() + " cannot yield to '" + property +
+                "' since it was not yet invoked.");
+        });
+        delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
+            throw new Error(this.toString() + " cannot yield to '" + property +
+                "' since it was not yet invoked.");
+        });
+
+        spyApi.formatters = {
+            c: function (spyInstance) {
+                return sinon.timesInWords(spyInstance.callCount);
+            },
+
+            n: function (spyInstance) {
+                return spyInstance.toString();
+            },
+
+            C: function (spyInstance) {
+                var calls = [];
+
+                for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
+                    var stringifiedCall = "    " + spyInstance.getCall(i).toString();
+                    if (/\n/.test(calls[i - 1])) {
+                        stringifiedCall = "\n" + stringifiedCall;
+                    }
+                    push.call(calls, stringifiedCall);
+                }
+
+                return calls.length > 0 ? "\n" + calls.join("\n") : "";
+            },
+
+            t: function (spyInstance) {
+                var objects = [];
+
+                for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
+                    push.call(objects, sinon.format(spyInstance.thisValues[i]));
+                }
+
+                return objects.join(", ");
+            },
+
+            "*": function (spyInstance, args) {
+                var formatted = [];
+
+                for (var i = 0, l = args.length; i < l; ++i) {
+                    push.call(formatted, sinon.format(args[i]));
+                }
+
+                return formatted.join(", ");
+            }
+        };
+
+        sinon.extend(spy, spyApi);
+
+        spy.spyCall = sinon.spyCall;
+        sinon.spy = spy;
+
+        return spy;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var core = require("./util/core");
+        require("./call");
+        require("./extend");
+        require("./times_in_words");
+        require("./format");
+        module.exports = makeApi(core);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend extend.js
+ */
+/**
+ * Stub behavior
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Tim Fischbach (mail@timfischbach.de)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    var slice = Array.prototype.slice;
+    var join = Array.prototype.join;
+    var useLeftMostCallback = -1;
+    var useRightMostCallback = -2;
+
+    var nextTick = (function () {
+        if (typeof process === "object" && typeof process.nextTick === "function") {
+            return process.nextTick;
+        }
+
+        if (typeof setImmediate === "function") {
+            return setImmediate;
+        }
+
+        return function (callback) {
+            setTimeout(callback, 0);
+        };
+    })();
+
+    function throwsException(error, message) {
+        if (typeof error === "string") {
+            this.exception = new Error(message || "");
+            this.exception.name = error;
+        } else if (!error) {
+            this.exception = new Error("Error");
+        } else {
+            this.exception = error;
+        }
+
+        return this;
+    }
+
+    function getCallback(behavior, args) {
+        var callArgAt = behavior.callArgAt;
+
+        if (callArgAt >= 0) {
+            return args[callArgAt];
+        }
+
+        var argumentList;
+
+        if (callArgAt === useLeftMostCallback) {
+            argumentList = args;
+        }
+
+        if (callArgAt === useRightMostCallback) {
+            argumentList = slice.call(args).reverse();
+        }
+
+        var callArgProp = behavior.callArgProp;
+
+        for (var i = 0, l = argumentList.length; i < l; ++i) {
+            if (!callArgProp && typeof argumentList[i] === "function") {
+                return argumentList[i];
+            }
+
+            if (callArgProp && argumentList[i] &&
+                typeof argumentList[i][callArgProp] === "function") {
+                return argumentList[i][callArgProp];
+            }
+        }
+
+        return null;
+    }
+
+    function makeApi(sinon) {
+        function getCallbackError(behavior, func, args) {
+            if (behavior.callArgAt < 0) {
+                var msg;
+
+                if (behavior.callArgProp) {
+                    msg = sinon.functionName(behavior.stub) +
+                        " expected to yield to '" + behavior.callArgProp +
+                        "', but no object with such a property was passed.";
+                } else {
+                    msg = sinon.functionName(behavior.stub) +
+                        " expected to yield, but no callback was passed.";
+                }
+
+                if (args.length > 0) {
+                    msg += " Received [" + join.call(args, ", ") + "]";
+                }
+
+                return msg;
+            }
+
+            return "argument at index " + behavior.callArgAt + " is not a function: " + func;
+        }
+
+        function callCallback(behavior, args) {
+            if (typeof behavior.callArgAt === "number") {
+                var func = getCallback(behavior, args);
+
+                if (typeof func !== "function") {
+                    throw new TypeError(getCallbackError(behavior, func, args));
+                }
+
+                if (behavior.callbackAsync) {
+                    nextTick(function () {
+                        func.apply(behavior.callbackContext, behavior.callbackArguments);
+                    });
+                } else {
+                    func.apply(behavior.callbackContext, behavior.callbackArguments);
+                }
+            }
+        }
+
+        var proto = {
+            create: function create(stub) {
+                var behavior = sinon.extend({}, sinon.behavior);
+                delete behavior.create;
+                behavior.stub = stub;
+
+                return behavior;
+            },
+
+            isPresent: function isPresent() {
+                return (typeof this.callArgAt === "number" ||
+                        this.exception ||
+                        typeof this.returnArgAt === "number" ||
+                        this.returnThis ||
+                        this.returnValueDefined);
+            },
+
+            invoke: function invoke(context, args) {
+                callCallback(this, args);
+
+                if (this.exception) {
+                    throw this.exception;
+                } else if (typeof this.returnArgAt === "number") {
+                    return args[this.returnArgAt];
+                } else if (this.returnThis) {
+                    return context;
+                }
+
+                return this.returnValue;
+            },
+
+            onCall: function onCall(index) {
+                return this.stub.onCall(index);
+            },
+
+            onFirstCall: function onFirstCall() {
+                return this.stub.onFirstCall();
+            },
+
+            onSecondCall: function onSecondCall() {
+                return this.stub.onSecondCall();
+            },
+
+            onThirdCall: function onThirdCall() {
+                return this.stub.onThirdCall();
+            },
+
+            withArgs: function withArgs(/* arguments */) {
+                throw new Error(
+                    "Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" " +
+                    "is not supported. Use \"stub.withArgs(...).onCall(...)\" " +
+                    "to define sequential behavior for calls with certain arguments."
+                );
+            },
+
+            callsArg: function callsArg(pos) {
+                if (typeof pos !== "number") {
+                    throw new TypeError("argument index is not number");
+                }
+
+                this.callArgAt = pos;
+                this.callbackArguments = [];
+                this.callbackContext = undefined;
+                this.callArgProp = undefined;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            callsArgOn: function callsArgOn(pos, context) {
+                if (typeof pos !== "number") {
+                    throw new TypeError("argument index is not number");
+                }
+                if (typeof context !== "object") {
+                    throw new TypeError("argument context is not an object");
+                }
+
+                this.callArgAt = pos;
+                this.callbackArguments = [];
+                this.callbackContext = context;
+                this.callArgProp = undefined;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            callsArgWith: function callsArgWith(pos) {
+                if (typeof pos !== "number") {
+                    throw new TypeError("argument index is not number");
+                }
+
+                this.callArgAt = pos;
+                this.callbackArguments = slice.call(arguments, 1);
+                this.callbackContext = undefined;
+                this.callArgProp = undefined;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            callsArgOnWith: function callsArgWith(pos, context) {
+                if (typeof pos !== "number") {
+                    throw new TypeError("argument index is not number");
+                }
+                if (typeof context !== "object") {
+                    throw new TypeError("argument context is not an object");
+                }
+
+                this.callArgAt = pos;
+                this.callbackArguments = slice.call(arguments, 2);
+                this.callbackContext = context;
+                this.callArgProp = undefined;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            yields: function () {
+                this.callArgAt = useLeftMostCallback;
+                this.callbackArguments = slice.call(arguments, 0);
+                this.callbackContext = undefined;
+                this.callArgProp = undefined;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            yieldsRight: function () {
+                this.callArgAt = useRightMostCallback;
+                this.callbackArguments = slice.call(arguments, 0);
+                this.callbackContext = undefined;
+                this.callArgProp = undefined;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            yieldsOn: function (context) {
+                if (typeof context !== "object") {
+                    throw new TypeError("argument context is not an object");
+                }
+
+                this.callArgAt = useLeftMostCallback;
+                this.callbackArguments = slice.call(arguments, 1);
+                this.callbackContext = context;
+                this.callArgProp = undefined;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            yieldsTo: function (prop) {
+                this.callArgAt = useLeftMostCallback;
+                this.callbackArguments = slice.call(arguments, 1);
+                this.callbackContext = undefined;
+                this.callArgProp = prop;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            yieldsToOn: function (prop, context) {
+                if (typeof context !== "object") {
+                    throw new TypeError("argument context is not an object");
+                }
+
+                this.callArgAt = useLeftMostCallback;
+                this.callbackArguments = slice.call(arguments, 2);
+                this.callbackContext = context;
+                this.callArgProp = prop;
+                this.callbackAsync = false;
+
+                return this;
+            },
+
+            throws: throwsException,
+            throwsException: throwsException,
+
+            returns: function returns(value) {
+                this.returnValue = value;
+                this.returnValueDefined = true;
+                this.exception = undefined;
+
+                return this;
+            },
+
+            returnsArg: function returnsArg(pos) {
+                if (typeof pos !== "number") {
+                    throw new TypeError("argument index is not number");
+                }
+
+                this.returnArgAt = pos;
+
+                return this;
+            },
+
+            returnsThis: function returnsThis() {
+                this.returnThis = true;
+
+                return this;
+            }
+        };
+
+        function createAsyncVersion(syncFnName) {
+            return function () {
+                var result = this[syncFnName].apply(this, arguments);
+                this.callbackAsync = true;
+                return result;
+            };
+        }
+
+        // create asynchronous versions of callsArg* and yields* methods
+        for (var method in proto) {
+            // need to avoid creating anotherasync versions of the newly added async methods
+            if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/) && !method.match(/Async/)) {
+                proto[method + "Async"] = createAsyncVersion(method);
+            }
+        }
+
+        sinon.behavior = proto;
+        return proto;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        require("./extend");
+        module.exports = makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        function walkInternal(obj, iterator, context, originalObj, seen) {
+            var proto, prop;
+
+            if (typeof Object.getOwnPropertyNames !== "function") {
+                // We explicitly want to enumerate through all of the prototype's properties
+                // in this case, therefore we deliberately leave out an own property check.
+                /* eslint-disable guard-for-in */
+                for (prop in obj) {
+                    iterator.call(context, obj[prop], prop, obj);
+                }
+                /* eslint-enable guard-for-in */
+
+                return;
+            }
+
+            Object.getOwnPropertyNames(obj).forEach(function (k) {
+                if (!seen[k]) {
+                    seen[k] = true;
+                    var target = typeof Object.getOwnPropertyDescriptor(obj, k).get === "function" ?
+                        originalObj : obj;
+                    iterator.call(context, target[k], k, target);
+                }
+            });
+
+            proto = Object.getPrototypeOf(obj);
+            if (proto) {
+                walkInternal(proto, iterator, context, originalObj, seen);
+            }
+        }
+
+        /* Public: walks the prototype chain of an object and iterates over every own property
+         * name encountered. The iterator is called in the same fashion that Array.prototype.forEach
+         * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional
+         * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will
+         * default to using a simple for..in loop.
+         *
+         * obj - The object to walk the prototype chain for.
+         * iterator - The function to be called on each pass of the walk.
+         * context - (Optional) When given, the iterator will be called with this object as the receiver.
+         */
+        function walk(obj, iterator, context) {
+            return walkInternal(obj, iterator, context, obj, {});
+        }
+
+        sinon.walk = walk;
+        return sinon.walk;
+    }
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        module.exports = makeApi(sinon);
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend extend.js
+ * @depend spy.js
+ * @depend behavior.js
+ * @depend walk.js
+ */
+/**
+ * Stub functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        function stub(object, property, func) {
+            if (!!func && typeof func !== "function" && typeof func !== "object") {
+                throw new TypeError("Custom stub should be a function or a property descriptor");
+            }
+
+            var wrapper;
+
+            if (func) {
+                if (typeof func === "function") {
+                    wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
+                } else {
+                    wrapper = func;
+                    if (sinon.spy && sinon.spy.create) {
+                        var types = sinon.objectKeys(wrapper);
+                        for (var i = 0; i < types.length; i++) {
+                            wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
+                        }
+                    }
+                }
+            } else {
+                var stubLength = 0;
+                if (typeof object === "object" && typeof object[property] === "function") {
+                    stubLength = object[property].length;
+                }
+                wrapper = stub.create(stubLength);
+            }
+
+            if (!object && typeof property === "undefined") {
+                return sinon.stub.create();
+            }
+
+            if (typeof property === "undefined" && typeof object === "object") {
+                sinon.walk(object || {}, function (value, prop, propOwner) {
+                    // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object
+                    // is not Object.prototype
+                    if (
+                        propOwner !== Object.prototype &&
+                        prop !== "constructor" &&
+                        typeof sinon.getPropertyDescriptor(propOwner, prop).value === "function"
+                    ) {
+                        stub(object, prop);
+                    }
+                });
+
+                return object;
+            }
+
+            return sinon.wrapMethod(object, property, wrapper);
+        }
+
+
+        /*eslint-disable no-use-before-define*/
+        function getParentBehaviour(stubInstance) {
+            return (stubInstance.parent && getCurrentBehavior(stubInstance.parent));
+        }
+
+        function getDefaultBehavior(stubInstance) {
+            return stubInstance.defaultBehavior ||
+                    getParentBehaviour(stubInstance) ||
+                    sinon.behavior.create(stubInstance);
+        }
+
+        function getCurrentBehavior(stubInstance) {
+            var behavior = stubInstance.behaviors[stubInstance.callCount - 1];
+            return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stubInstance);
+        }
+        /*eslint-enable no-use-before-define*/
+
+        var uuid = 0;
+
+        var proto = {
+            create: function create(stubLength) {
+                var functionStub = function () {
+                    return getCurrentBehavior(functionStub).invoke(this, arguments);
+                };
+
+                functionStub.id = "stub#" + uuid++;
+                var orig = functionStub;
+                functionStub = sinon.spy.create(functionStub, stubLength);
+                functionStub.func = orig;
+
+                sinon.extend(functionStub, stub);
+                functionStub.instantiateFake = sinon.stub.create;
+                functionStub.displayName = "stub";
+                functionStub.toString = sinon.functionToString;
+
+                functionStub.defaultBehavior = null;
+                functionStub.behaviors = [];
+
+                return functionStub;
+            },
+
+            resetBehavior: function () {
+                var i;
+
+                this.defaultBehavior = null;
+                this.behaviors = [];
+
+                delete this.returnValue;
+                delete this.returnArgAt;
+                this.returnThis = false;
+
+                if (this.fakes) {
+                    for (i = 0; i < this.fakes.length; i++) {
+                        this.fakes[i].resetBehavior();
+                    }
+                }
+            },
+
+            onCall: function onCall(index) {
+                if (!this.behaviors[index]) {
+                    this.behaviors[index] = sinon.behavior.create(this);
+                }
+
+                return this.behaviors[index];
+            },
+
+            onFirstCall: function onFirstCall() {
+                return this.onCall(0);
+            },
+
+            onSecondCall: function onSecondCall() {
+                return this.onCall(1);
+            },
+
+            onThirdCall: function onThirdCall() {
+                return this.onCall(2);
+            }
+        };
+
+        function createBehavior(behaviorMethod) {
+            return function () {
+                this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
+                this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
+                return this;
+            };
+        }
+
+        for (var method in sinon.behavior) {
+            if (sinon.behavior.hasOwnProperty(method) &&
+                !proto.hasOwnProperty(method) &&
+                method !== "create" &&
+                method !== "withArgs" &&
+                method !== "invoke") {
+                proto[method] = createBehavior(method);
+            }
+        }
+
+        sinon.extend(stub, proto);
+        sinon.stub = stub;
+
+        return stub;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var core = require("./util/core");
+        require("./behavior");
+        require("./spy");
+        require("./extend");
+        module.exports = makeApi(core);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend times_in_words.js
+ * @depend util/core.js
+ * @depend call.js
+ * @depend extend.js
+ * @depend match.js
+ * @depend spy.js
+ * @depend stub.js
+ * @depend format.js
+ */
+/**
+ * Mock functions.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        var push = [].push;
+        var match = sinon.match;
+
+        function mock(object) {
+            // if (typeof console !== undefined && console.warn) {
+            //     console.warn("mock will be removed from Sinon.JS v2.0");
+            // }
+
+            if (!object) {
+                return sinon.expectation.create("Anonymous mock");
+            }
+
+            return mock.create(object);
+        }
+
+        function each(collection, callback) {
+            if (!collection) {
+                return;
+            }
+
+            for (var i = 0, l = collection.length; i < l; i += 1) {
+                callback(collection[i]);
+            }
+        }
+
+        function arrayEquals(arr1, arr2, compareLength) {
+            if (compareLength && (arr1.length !== arr2.length)) {
+                return false;
+            }
+
+            for (var i = 0, l = arr1.length; i < l; i++) {
+                if (!sinon.deepEqual(arr1[i], arr2[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        sinon.extend(mock, {
+            create: function create(object) {
+                if (!object) {
+                    throw new TypeError("object is null");
+                }
+
+                var mockObject = sinon.extend({}, mock);
+                mockObject.object = object;
+                delete mockObject.create;
+
+                return mockObject;
+            },
+
+            expects: function expects(method) {
+                if (!method) {
+                    throw new TypeError("method is falsy");
+                }
+
+                if (!this.expectations) {
+                    this.expectations = {};
+                    this.proxies = [];
+                }
+
+                if (!this.expectations[method]) {
+                    this.expectations[method] = [];
+                    var mockObject = this;
+
+                    sinon.wrapMethod(this.object, method, function () {
+                        return mockObject.invokeMethod(method, this, arguments);
+                    });
+
+                    push.call(this.proxies, method);
+                }
+
+                var expectation = sinon.expectation.create(method);
+                push.call(this.expectations[method], expectation);
+
+                return expectation;
+            },
+
+            restore: function restore() {
+                var object = this.object;
+
+                each(this.proxies, function (proxy) {
+                    if (typeof object[proxy].restore === "function") {
+                        object[proxy].restore();
+                    }
+                });
+            },
+
+            verify: function verify() {
+                var expectations = this.expectations || {};
+                var messages = [];
+                var met = [];
+
+                each(this.proxies, function (proxy) {
+                    each(expectations[proxy], function (expectation) {
+                        if (!expectation.met()) {
+                            push.call(messages, expectation.toString());
+                        } else {
+                            push.call(met, expectation.toString());
+                        }
+                    });
+                });
+
+                this.restore();
+
+                if (messages.length > 0) {
+                    sinon.expectation.fail(messages.concat(met).join("\n"));
+                } else if (met.length > 0) {
+                    sinon.expectation.pass(messages.concat(met).join("\n"));
+                }
+
+                return true;
+            },
+
+            invokeMethod: function invokeMethod(method, thisValue, args) {
+                var expectations = this.expectations && this.expectations[method] ? this.expectations[method] : [];
+                var expectationsWithMatchingArgs = [];
+                var currentArgs = args || [];
+                var i, available;
+
+                for (i = 0; i < expectations.length; i += 1) {
+                    var expectedArgs = expectations[i].expectedArguments || [];
+                    if (arrayEquals(expectedArgs, currentArgs, expectations[i].expectsExactArgCount)) {
+                        expectationsWithMatchingArgs.push(expectations[i]);
+                    }
+                }
+
+                for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
+                    if (!expectationsWithMatchingArgs[i].met() &&
+                        expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
+                        return expectationsWithMatchingArgs[i].apply(thisValue, args);
+                    }
+                }
+
+                var messages = [];
+                var exhausted = 0;
+
+                for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
+                    if (expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
+                        available = available || expectationsWithMatchingArgs[i];
+                    } else {
+                        exhausted += 1;
+                    }
+                }
+
+                if (available && exhausted === 0) {
+                    return available.apply(thisValue, args);
+                }
+
+                for (i = 0; i < expectations.length; i += 1) {
+                    push.call(messages, "    " + expectations[i].toString());
+                }
+
+                messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
+                    proxy: method,
+                    args: args
+                }));
+
+                sinon.expectation.fail(messages.join("\n"));
+            }
+        });
+
+        var times = sinon.timesInWords;
+        var slice = Array.prototype.slice;
+
+        function callCountInWords(callCount) {
+            if (callCount === 0) {
+                return "never called";
+            }
+
+            return "called " + times(callCount);
+        }
+
+        function expectedCallCountInWords(expectation) {
+            var min = expectation.minCalls;
+            var max = expectation.maxCalls;
+
+            if (typeof min === "number" && typeof max === "number") {
+                var str = times(min);
+
+                if (min !== max) {
+                    str = "at least " + str + " and at most " + times(max);
+                }
+
+                return str;
+            }
+
+            if (typeof min === "number") {
+                return "at least " + times(min);
+            }
+
+            return "at most " + times(max);
+        }
+
+        function receivedMinCalls(expectation) {
+            var hasMinLimit = typeof expectation.minCalls === "number";
+            return !hasMinLimit || expectation.callCount >= expectation.minCalls;
+        }
+
+        function receivedMaxCalls(expectation) {
+            if (typeof expectation.maxCalls !== "number") {
+                return false;
+            }
+
+            return expectation.callCount === expectation.maxCalls;
+        }
+
+        function verifyMatcher(possibleMatcher, arg) {
+            var isMatcher = match && match.isMatcher(possibleMatcher);
+
+            return isMatcher && possibleMatcher.test(arg) || true;
+        }
+
+        sinon.expectation = {
+            minCalls: 1,
+            maxCalls: 1,
+
+            create: function create(methodName) {
+                var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
+                delete expectation.create;
+                expectation.method = methodName;
+
+                return expectation;
+            },
+
+            invoke: function invoke(func, thisValue, args) {
+                this.verifyCallAllowed(thisValue, args);
+
+                return sinon.spy.invoke.apply(this, arguments);
+            },
+
+            atLeast: function atLeast(num) {
+                if (typeof num !== "number") {
+                    throw new TypeError("'" + num + "' is not number");
+                }
+
+                if (!this.limitsSet) {
+                    this.maxCalls = null;
+                    this.limitsSet = true;
+                }
+
+                this.minCalls = num;
+
+                return this;
+            },
+
+            atMost: function atMost(num) {
+                if (typeof num !== "number") {
+                    throw new TypeError("'" + num + "' is not number");
+                }
+
+                if (!this.limitsSet) {
+                    this.minCalls = null;
+                    this.limitsSet = true;
+                }
+
+                this.maxCalls = num;
+
+                return this;
+            },
+
+            never: function never() {
+                return this.exactly(0);
+            },
+
+            once: function once() {
+                return this.exactly(1);
+            },
+
+            twice: function twice() {
+                return this.exactly(2);
+            },
+
+            thrice: function thrice() {
+                return this.exactly(3);
+            },
+
+            exactly: function exactly(num) {
+                if (typeof num !== "number") {
+                    throw new TypeError("'" + num + "' is not a number");
+                }
+
+                this.atLeast(num);
+                return this.atMost(num);
+            },
+
+            met: function met() {
+                return !this.failed && receivedMinCalls(this);
+            },
+
+            verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
+                if (receivedMaxCalls(this)) {
+                    this.failed = true;
+                    sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
+                }
+
+                if ("expectedThis" in this && this.expectedThis !== thisValue) {
+                    sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
+                        this.expectedThis);
+                }
+
+                if (!("expectedArguments" in this)) {
+                    return;
+                }
+
+                if (!args) {
+                    sinon.expectation.fail(this.method + " received no arguments, expected " +
+                        sinon.format(this.expectedArguments));
+                }
+
+                if (args.length < this.expectedArguments.length) {
+                    sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
+                        "), expected " + sinon.format(this.expectedArguments));
+                }
+
+                if (this.expectsExactArgCount &&
+                    args.length !== this.expectedArguments.length) {
+                    sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
+                        "), expected " + sinon.format(this.expectedArguments));
+                }
+
+                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+
+                    if (!verifyMatcher(this.expectedArguments[i], args[i])) {
+                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+                            ", didn't match " + this.expectedArguments.toString());
+                    }
+
+                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+                            ", expected " + sinon.format(this.expectedArguments));
+                    }
+                }
+            },
+
+            allowsCall: function allowsCall(thisValue, args) {
+                if (this.met() && receivedMaxCalls(this)) {
+                    return false;
+                }
+
+                if ("expectedThis" in this && this.expectedThis !== thisValue) {
+                    return false;
+                }
+
+                if (!("expectedArguments" in this)) {
+                    return true;
+                }
+
+                args = args || [];
+
+                if (args.length < this.expectedArguments.length) {
+                    return false;
+                }
+
+                if (this.expectsExactArgCount &&
+                    args.length !== this.expectedArguments.length) {
+                    return false;
+                }
+
+                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+                    if (!verifyMatcher(this.expectedArguments[i], args[i])) {
+                        return false;
+                    }
+
+                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+                        return false;
+                    }
+                }
+
+                return true;
+            },
+
+            withArgs: function withArgs() {
+                this.expectedArguments = slice.call(arguments);
+                return this;
+            },
+
+            withExactArgs: function withExactArgs() {
+                this.withArgs.apply(this, arguments);
+                this.expectsExactArgCount = true;
+                return this;
+            },
+
+            on: function on(thisValue) {
+                this.expectedThis = thisValue;
+                return this;
+            },
+
+            toString: function () {
+                var args = (this.expectedArguments || []).slice();
+
+                if (!this.expectsExactArgCount) {
+                    push.call(args, "[...]");
+                }
+
+                var callStr = sinon.spyCall.toString.call({
+                    proxy: this.method || "anonymous mock expectation",
+                    args: args
+                });
+
+                var message = callStr.replace(", [...", "[, ...") + " " +
+                    expectedCallCountInWords(this);
+
+                if (this.met()) {
+                    return "Expectation met: " + message;
+                }
+
+                return "Expected " + message + " (" +
+                    callCountInWords(this.callCount) + ")";
+            },
+
+            verify: function verify() {
+                if (!this.met()) {
+                    sinon.expectation.fail(this.toString());
+                } else {
+                    sinon.expectation.pass(this.toString());
+                }
+
+                return true;
+            },
+
+            pass: function pass(message) {
+                sinon.assert.pass(message);
+            },
+
+            fail: function fail(message) {
+                var exception = new Error(message);
+                exception.name = "ExpectationError";
+
+                throw exception;
+            }
+        };
+
+        sinon.mock = mock;
+        return mock;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        require("./times_in_words");
+        require("./call");
+        require("./extend");
+        require("./match");
+        require("./spy");
+        require("./stub");
+        require("./format");
+
+        module.exports = makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend spy.js
+ * @depend stub.js
+ * @depend mock.js
+ */
+/**
+ * Collections of stubs, spies and mocks.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    var push = [].push;
+    var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+    function getFakes(fakeCollection) {
+        if (!fakeCollection.fakes) {
+            fakeCollection.fakes = [];
+        }
+
+        return fakeCollection.fakes;
+    }
+
+    function each(fakeCollection, method) {
+        var fakes = getFakes(fakeCollection);
+
+        for (var i = 0, l = fakes.length; i < l; i += 1) {
+            if (typeof fakes[i][method] === "function") {
+                fakes[i][method]();
+            }
+        }
+    }
+
+    function compact(fakeCollection) {
+        var fakes = getFakes(fakeCollection);
+        var i = 0;
+        while (i < fakes.length) {
+            fakes.splice(i, 1);
+        }
+    }
+
+    function makeApi(sinon) {
+        var collection = {
+            verify: function resolve() {
+                each(this, "verify");
+            },
+
+            restore: function restore() {
+                each(this, "restore");
+                compact(this);
+            },
+
+            reset: function restore() {
+                each(this, "reset");
+            },
+
+            verifyAndRestore: function verifyAndRestore() {
+                var exception;
+
+                try {
+                    this.verify();
+                } catch (e) {
+                    exception = e;
+                }
+
+                this.restore();
+
+                if (exception) {
+                    throw exception;
+                }
+            },
+
+            add: function add(fake) {
+                push.call(getFakes(this), fake);
+                return fake;
+            },
+
+            spy: function spy() {
+                return this.add(sinon.spy.apply(sinon, arguments));
+            },
+
+            stub: function stub(object, property, value) {
+                if (property) {
+                    var original = object[property];
+
+                    if (typeof original !== "function") {
+                        if (!hasOwnProperty.call(object, property)) {
+                            throw new TypeError("Cannot stub non-existent own property " + property);
+                        }
+
+                        object[property] = value;
+
+                        return this.add({
+                            restore: function () {
+                                object[property] = original;
+                            }
+                        });
+                    }
+                }
+                if (!property && !!object && typeof object === "object") {
+                    var stubbedObj = sinon.stub.apply(sinon, arguments);
+
+                    for (var prop in stubbedObj) {
+                        if (typeof stubbedObj[prop] === "function") {
+                            this.add(stubbedObj[prop]);
+                        }
+                    }
+
+                    return stubbedObj;
+                }
+
+                return this.add(sinon.stub.apply(sinon, arguments));
+            },
+
+            mock: function mock() {
+                return this.add(sinon.mock.apply(sinon, arguments));
+            },
+
+            inject: function inject(obj) {
+                var col = this;
+
+                obj.spy = function () {
+                    return col.spy.apply(col, arguments);
+                };
+
+                obj.stub = function () {
+                    return col.stub.apply(col, arguments);
+                };
+
+                obj.mock = function () {
+                    return col.mock.apply(col, arguments);
+                };
+
+                return obj;
+            }
+        };
+
+        sinon.collection = collection;
+        return collection;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        require("./mock");
+        require("./spy");
+        require("./stub");
+        module.exports = makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * Fake timer API
+ * setTimeout
+ * setInterval
+ * clearTimeout
+ * clearInterval
+ * tick
+ * reset
+ * Date
+ *
+ * Inspired by jsUnitMockTimeOut from JsUnit
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function () {
+    
+    function makeApi(s, lol) {
+        /*global lolex */
+        var llx = typeof lolex !== "undefined" ? lolex : lol;
+
+        s.useFakeTimers = function () {
+            var now;
+            var methods = Array.prototype.slice.call(arguments);
+
+            if (typeof methods[0] === "string") {
+                now = 0;
+            } else {
+                now = methods.shift();
+            }
+
+            var clock = llx.install(now || 0, methods);
+            clock.restore = clock.uninstall;
+            return clock;
+        };
+
+        s.clock = {
+            create: function (now) {
+                return llx.createClock(now);
+            }
+        };
+
+        s.timers = {
+            setTimeout: setTimeout,
+            clearTimeout: clearTimeout,
+            setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
+            clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
+            setInterval: setInterval,
+            clearInterval: clearInterval,
+            Date: Date
+        };
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, epxorts, module, lolex) {
+        var core = require("./core");
+        makeApi(core, lolex);
+        module.exports = core;
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+    } else if (isNode) {
+        loadDependencies(require, module.exports, module, require("lolex"));
+    } else {
+        makeApi(sinon); // eslint-disable-line no-undef
+    }
+}());
+
+/**
+ * Minimal Event interface implementation
+ *
+ * Original implementation by Sven Fuchs: https://gist.github.com/995028
+ * Modifications and tests by Christian Johansen.
+ *
+ * @author Sven Fuchs (svenfuchs@artweb-design.de)
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2011 Sven Fuchs, Christian Johansen
+ */
+if (typeof sinon === "undefined") {
+    this.sinon = {};
+}
+
+(function () {
+    
+    var push = [].push;
+
+    function makeApi(sinon) {
+        sinon.Event = function Event(type, bubbles, cancelable, target) {
+            this.initEvent(type, bubbles, cancelable, target);
+        };
+
+        sinon.Event.prototype = {
+            initEvent: function (type, bubbles, cancelable, target) {
+                this.type = type;
+                this.bubbles = bubbles;
+                this.cancelable = cancelable;
+                this.target = target;
+            },
+
+            stopPropagation: function () {},
+
+            preventDefault: function () {
+                this.defaultPrevented = true;
+            }
+        };
+
+        sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
+            this.initEvent(type, false, false, target);
+            this.loaded = progressEventRaw.loaded || null;
+            this.total = progressEventRaw.total || null;
+            this.lengthComputable = !!progressEventRaw.total;
+        };
+
+        sinon.ProgressEvent.prototype = new sinon.Event();
+
+        sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
+
+        sinon.CustomEvent = function CustomEvent(type, customData, target) {
+            this.initEvent(type, false, false, target);
+            this.detail = customData.detail || null;
+        };
+
+        sinon.CustomEvent.prototype = new sinon.Event();
+
+        sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
+
+        sinon.EventTarget = {
+            addEventListener: function addEventListener(event, listener) {
+                this.eventListeners = this.eventListeners || {};
+                this.eventListeners[event] = this.eventListeners[event] || [];
+                push.call(this.eventListeners[event], listener);
+            },
+
+            removeEventListener: function removeEventListener(event, listener) {
+                var listeners = this.eventListeners && this.eventListeners[event] || [];
+
+                for (var i = 0, l = listeners.length; i < l; ++i) {
+                    if (listeners[i] === listener) {
+                        return listeners.splice(i, 1);
+                    }
+                }
+            },
+
+            dispatchEvent: function dispatchEvent(event) {
+                var type = event.type;
+                var listeners = this.eventListeners && this.eventListeners[type] || [];
+
+                for (var i = 0; i < listeners.length; i++) {
+                    if (typeof listeners[i] === "function") {
+                        listeners[i].call(this, event);
+                    } else {
+                        listeners[i].handleEvent(event);
+                    }
+                }
+
+                return !!event.defaultPrevented;
+            }
+        };
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require) {
+        var sinon = require("./core");
+        makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+    } else if (isNode) {
+        loadDependencies(require);
+    } else {
+        makeApi(sinon); // eslint-disable-line no-undef
+    }
+}());
+
+/**
+ * @depend util/core.js
+ */
+/**
+ * Logs errors
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    // cache a reference to setTimeout, so that our reference won't be stubbed out
+    // when using fake timers and errors will still get logged
+    // https://github.com/cjohansen/Sinon.JS/issues/381
+    var realSetTimeout = setTimeout;
+
+    function makeApi(sinon) {
+
+        function log() {}
+
+        function logError(label, err) {
+            var msg = label + " threw exception: ";
+
+            function throwLoggedError() {
+                err.message = msg + err.message;
+                throw err;
+            }
+
+            sinon.log(msg + "[" + err.name + "] " + err.message);
+
+            if (err.stack) {
+                sinon.log(err.stack);
+            }
+
+            if (logError.useImmediateExceptions) {
+                throwLoggedError();
+            } else {
+                logError.setTimeout(throwLoggedError, 0);
+            }
+        }
+
+        // When set to true, any errors logged will be thrown immediately;
+        // If set to false, the errors will be thrown in separate execution frame.
+        logError.useImmediateExceptions = false;
+
+        // wrap realSetTimeout with something we can stub in tests
+        logError.setTimeout = function (func, timeout) {
+            realSetTimeout(func, timeout);
+        };
+
+        var exports = {};
+        exports.log = sinon.log = log;
+        exports.logError = sinon.logError = logError;
+
+        return exports;
+    }
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        module.exports = makeApi(sinon);
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend core.js
+ * @depend ../extend.js
+ * @depend event.js
+ * @depend ../log_error.js
+ */
+/**
+ * Fake XDomainRequest object
+ */
+
+/**
+ * Returns the global to prevent assigning values to 'this' when this is undefined.
+ * This can occur when files are interpreted by node in strict mode.
+ * @private
+ */
+function getGlobal() {
+    
+    return typeof window !== "undefined" ? window : global;
+}
+
+if (typeof sinon === "undefined") {
+    if (typeof this === "undefined") {
+        getGlobal().sinon = {};
+    } else {
+        this.sinon = {};
+    }
+}
+
+// wrapper for global
+(function (global) {
+    
+    var xdr = { XDomainRequest: global.XDomainRequest };
+    xdr.GlobalXDomainRequest = global.XDomainRequest;
+    xdr.supportsXDR = typeof xdr.GlobalXDomainRequest !== "undefined";
+    xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
+
+    function makeApi(sinon) {
+        sinon.xdr = xdr;
+
+        function FakeXDomainRequest() {
+            this.readyState = FakeXDomainRequest.UNSENT;
+            this.requestBody = null;
+            this.requestHeaders = {};
+            this.status = 0;
+            this.timeout = null;
+
+            if (typeof FakeXDomainRequest.onCreate === "function") {
+                FakeXDomainRequest.onCreate(this);
+            }
+        }
+
+        function verifyState(x) {
+            if (x.readyState !== FakeXDomainRequest.OPENED) {
+                throw new Error("INVALID_STATE_ERR");
+            }
+
+            if (x.sendFlag) {
+                throw new Error("INVALID_STATE_ERR");
+            }
+        }
+
+        function verifyRequestSent(x) {
+            if (x.readyState === FakeXDomainRequest.UNSENT) {
+                throw new Error("Request not sent");
+            }
+            if (x.readyState === FakeXDomainRequest.DONE) {
+                throw new Error("Request done");
+            }
+        }
+
+        function verifyResponseBodyType(body) {
+            if (typeof body !== "string") {
+                var error = new Error("Attempted to respond to fake XDomainRequest with " +
+                                    body + ", which is not a string.");
+                error.name = "InvalidBodyException";
+                throw error;
+            }
+        }
+
+        sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
+            open: function open(method, url) {
+                this.method = method;
+                this.url = url;
+
+                this.responseText = null;
+                this.sendFlag = false;
+
+                this.readyStateChange(FakeXDomainRequest.OPENED);
+            },
+
+            readyStateChange: function readyStateChange(state) {
+                this.readyState = state;
+                var eventName = "";
+                switch (this.readyState) {
+                case FakeXDomainRequest.UNSENT:
+                    break;
+                case FakeXDomainRequest.OPENED:
+                    break;
+                case FakeXDomainRequest.LOADING:
+                    if (this.sendFlag) {
+                        //raise the progress event
+                        eventName = "onprogress";
+                    }
+                    break;
+                case FakeXDomainRequest.DONE:
+                    if (this.isTimeout) {
+                        eventName = "ontimeout";
+                    } else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
+                        eventName = "onerror";
+                    } else {
+                        eventName = "onload";
+                    }
+                    break;
+                }
+
+                // raising event (if defined)
+                if (eventName) {
+                    if (typeof this[eventName] === "function") {
+                        try {
+                            this[eventName]();
+                        } catch (e) {
+                            sinon.logError("Fake XHR " + eventName + " handler", e);
+                        }
+                    }
+                }
+            },
+
+            send: function send(data) {
+                verifyState(this);
+
+                if (!/^(get|head)$/i.test(this.method)) {
+                    this.requestBody = data;
+                }
+                this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+
+                this.errorFlag = false;
+                this.sendFlag = true;
+                this.readyStateChange(FakeXDomainRequest.OPENED);
+
+                if (typeof this.onSend === "function") {
+                    this.onSend(this);
+                }
+            },
+
+            abort: function abort() {
+                this.aborted = true;
+                this.responseText = null;
+                this.errorFlag = true;
+
+                if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
+                    this.readyStateChange(sinon.FakeXDomainRequest.DONE);
+                    this.sendFlag = false;
+                }
+            },
+
+            setResponseBody: function setResponseBody(body) {
+                verifyRequestSent(this);
+                verifyResponseBodyType(body);
+
+                var chunkSize = this.chunkSize || 10;
+                var index = 0;
+                this.responseText = "";
+
+                do {
+                    this.readyStateChange(FakeXDomainRequest.LOADING);
+                    this.responseText += body.substring(index, index + chunkSize);
+                    index += chunkSize;
+                } while (index < body.length);
+
+                this.readyStateChange(FakeXDomainRequest.DONE);
+            },
+
+            respond: function respond(status, contentType, body) {
+                // content-type ignored, since XDomainRequest does not carry this
+                // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
+                // test integration across browsers
+                this.status = typeof status === "number" ? status : 200;
+                this.setResponseBody(body || "");
+            },
+
+            simulatetimeout: function simulatetimeout() {
+                this.status = 0;
+                this.isTimeout = true;
+                // Access to this should actually throw an error
+                this.responseText = undefined;
+                this.readyStateChange(FakeXDomainRequest.DONE);
+            }
+        });
+
+        sinon.extend(FakeXDomainRequest, {
+            UNSENT: 0,
+            OPENED: 1,
+            LOADING: 3,
+            DONE: 4
+        });
+
+        sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
+            sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
+                if (xdr.supportsXDR) {
+                    global.XDomainRequest = xdr.GlobalXDomainRequest;
+                }
+
+                delete sinon.FakeXDomainRequest.restore;
+
+                if (keepOnCreate !== true) {
+                    delete sinon.FakeXDomainRequest.onCreate;
+                }
+            };
+            if (xdr.supportsXDR) {
+                global.XDomainRequest = sinon.FakeXDomainRequest;
+            }
+            return sinon.FakeXDomainRequest;
+        };
+
+        sinon.FakeXDomainRequest = FakeXDomainRequest;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./core");
+        require("../extend");
+        require("./event");
+        require("../log_error");
+        makeApi(sinon);
+        module.exports = sinon;
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+    } else if (isNode) {
+        loadDependencies(require, module.exports, module);
+    } else {
+        makeApi(sinon); // eslint-disable-line no-undef
+    }
+})(typeof global !== "undefined" ? global : self);
+
+/**
+ * @depend core.js
+ * @depend ../extend.js
+ * @depend event.js
+ * @depend ../log_error.js
+ */
+/**
+ * Fake XMLHttpRequest object
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal, global) {
+    
+    function getWorkingXHR(globalScope) {
+        var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined";
+        if (supportsXHR) {
+            return globalScope.XMLHttpRequest;
+        }
+
+        var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined";
+        if (supportsActiveX) {
+            return function () {
+                return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");
+            };
+        }
+
+        return false;
+    }
+
+    var supportsProgress = typeof ProgressEvent !== "undefined";
+    var supportsCustomEvent = typeof CustomEvent !== "undefined";
+    var supportsFormData = typeof FormData !== "undefined";
+    var supportsArrayBuffer = typeof ArrayBuffer !== "undefined";
+    var supportsBlob = typeof Blob === "function";
+    var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
+    sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
+    sinonXhr.GlobalActiveXObject = global.ActiveXObject;
+    sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject !== "undefined";
+    sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined";
+    sinonXhr.workingXHR = getWorkingXHR(global);
+    sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
+
+    var unsafeHeaders = {
+        "Accept-Charset": true,
+        "Accept-Encoding": true,
+        Connection: true,
+        "Content-Length": true,
+        Cookie: true,
+        Cookie2: true,
+        "Content-Transfer-Encoding": true,
+        Date: true,
+        Expect: true,
+        Host: true,
+        "Keep-Alive": true,
+        Referer: true,
+        TE: true,
+        Trailer: true,
+        "Transfer-Encoding": true,
+        Upgrade: true,
+        "User-Agent": true,
+        Via: true
+    };
+
+    // An upload object is created for each
+    // FakeXMLHttpRequest and allows upload
+    // events to be simulated using uploadProgress
+    // and uploadError.
+    function UploadProgress() {
+        this.eventListeners = {
+            progress: [],
+            load: [],
+            abort: [],
+            error: []
+        };
+    }
+
+    UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
+        this.eventListeners[event].push(listener);
+    };
+
+    UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
+        var listeners = this.eventListeners[event] || [];
+
+        for (var i = 0, l = listeners.length; i < l; ++i) {
+            if (listeners[i] === listener) {
+                return listeners.splice(i, 1);
+            }
+        }
+    };
+
+    UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
+        var listeners = this.eventListeners[event.type] || [];
+
+        for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
+            listener(event);
+        }
+    };
+
+    // Note that for FakeXMLHttpRequest to work pre ES5
+    // we lose some of the alignment with the spec.
+    // To ensure as close a match as possible,
+    // set responseType before calling open, send or respond;
+    function FakeXMLHttpRequest() {
+        this.readyState = FakeXMLHttpRequest.UNSENT;
+        this.requestHeaders = {};
+        this.requestBody = null;
+        this.status = 0;
+        this.statusText = "";
+        this.upload = new UploadProgress();
+        this.responseType = "";
+        this.response = "";
+        if (sinonXhr.supportsCORS) {
+            this.withCredentials = false;
+        }
+
+        var xhr = this;
+        var events = ["loadstart", "load", "abort", "loadend"];
+
+        function addEventListener(eventName) {
+            xhr.addEventListener(eventName, function (event) {
+                var listener = xhr["on" + eventName];
+
+                if (listener && typeof listener === "function") {
+                    listener.call(this, event);
+                }
+            });
+        }
+
+        for (var i = events.length - 1; i >= 0; i--) {
+            addEventListener(events[i]);
+        }
+
+        if (typeof FakeXMLHttpRequest.onCreate === "function") {
+            FakeXMLHttpRequest.onCreate(this);
+        }
+    }
+
+    function verifyState(xhr) {
+        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+
+        if (xhr.sendFlag) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+    }
+
+    function getHeader(headers, header) {
+        header = header.toLowerCase();
+
+        for (var h in headers) {
+            if (h.toLowerCase() === header) {
+                return h;
+            }
+        }
+
+        return null;
+    }
+
+    // filtering to enable a white-list version of Sinon FakeXhr,
+    // where whitelisted requests are passed through to real XHR
+    function each(collection, callback) {
+        if (!collection) {
+            return;
+        }
+
+        for (var i = 0, l = collection.length; i < l; i += 1) {
+            callback(collection[i]);
+        }
+    }
+    function some(collection, callback) {
+        for (var index = 0; index < collection.length; index++) {
+            if (callback(collection[index]) === true) {
+                return true;
+            }
+        }
+        return false;
+    }
+    // largest arity in XHR is 5 - XHR#open
+    var apply = function (obj, method, args) {
+        switch (args.length) {
+        case 0: return obj[method]();
+        case 1: return obj[method](args[0]);
+        case 2: return obj[method](args[0], args[1]);
+        case 3: return obj[method](args[0], args[1], args[2]);
+        case 4: return obj[method](args[0], args[1], args[2], args[3]);
+        case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
+        }
+    };
+
+    FakeXMLHttpRequest.filters = [];
+    FakeXMLHttpRequest.addFilter = function addFilter(fn) {
+        this.filters.push(fn);
+    };
+    var IE6Re = /MSIE 6/;
+    FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
+        var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap
+
+        each([
+            "open",
+            "setRequestHeader",
+            "send",
+            "abort",
+            "getResponseHeader",
+            "getAllResponseHeaders",
+            "addEventListener",
+            "overrideMimeType",
+            "removeEventListener"
+        ], function (method) {
+            fakeXhr[method] = function () {
+                return apply(xhr, method, arguments);
+            };
+        });
+
+        var copyAttrs = function (args) {
+            each(args, function (attr) {
+                try {
+                    fakeXhr[attr] = xhr[attr];
+                } catch (e) {
+                    if (!IE6Re.test(navigator.userAgent)) {
+                        throw e;
+                    }
+                }
+            });
+        };
+
+        var stateChange = function stateChange() {
+            fakeXhr.readyState = xhr.readyState;
+            if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                copyAttrs(["status", "statusText"]);
+            }
+            if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
+                copyAttrs(["responseText", "response"]);
+            }
+            if (xhr.readyState === FakeXMLHttpRequest.DONE) {
+                copyAttrs(["responseXML"]);
+            }
+            if (fakeXhr.onreadystatechange) {
+                fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
+            }
+        };
+
+        if (xhr.addEventListener) {
+            for (var event in fakeXhr.eventListeners) {
+                if (fakeXhr.eventListeners.hasOwnProperty(event)) {
+
+                    /*eslint-disable no-loop-func*/
+                    each(fakeXhr.eventListeners[event], function (handler) {
+                        xhr.addEventListener(event, handler);
+                    });
+                    /*eslint-enable no-loop-func*/
+                }
+            }
+            xhr.addEventListener("readystatechange", stateChange);
+        } else {
+            xhr.onreadystatechange = stateChange;
+        }
+        apply(xhr, "open", xhrArgs);
+    };
+    FakeXMLHttpRequest.useFilters = false;
+
+    function verifyRequestOpened(xhr) {
+        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
+            throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
+        }
+    }
+
+    function verifyRequestSent(xhr) {
+        if (xhr.readyState === FakeXMLHttpRequest.DONE) {
+            throw new Error("Request done");
+        }
+    }
+
+    function verifyHeadersReceived(xhr) {
+        if (xhr.async && xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED) {
+            throw new Error("No headers received");
+        }
+    }
+
+    function verifyResponseBodyType(body) {
+        if (typeof body !== "string") {
+            var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
+                                 body + ", which is not a string.");
+            error.name = "InvalidBodyException";
+            throw error;
+        }
+    }
+
+    function convertToArrayBuffer(body) {
+        var buffer = new ArrayBuffer(body.length);
+        var view = new Uint8Array(buffer);
+        for (var i = 0; i < body.length; i++) {
+            var charCode = body.charCodeAt(i);
+            if (charCode >= 256) {
+                throw new TypeError("arraybuffer or blob responseTypes require binary string, " +
+                                    "invalid character " + body[i] + " found.");
+            }
+            view[i] = charCode;
+        }
+        return buffer;
+    }
+
+    function isXmlContentType(contentType) {
+        return !contentType || /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType);
+    }
+
+    function convertResponseBody(responseType, contentType, body) {
+        if (responseType === "" || responseType === "text") {
+            return body;
+        } else if (supportsArrayBuffer && responseType === "arraybuffer") {
+            return convertToArrayBuffer(body);
+        } else if (responseType === "json") {
+            try {
+                return JSON.parse(body);
+            } catch (e) {
+                // Return parsing failure as null
+                return null;
+            }
+        } else if (supportsBlob && responseType === "blob") {
+            var blobOptions = {};
+            if (contentType) {
+                blobOptions.type = contentType;
+            }
+            return new Blob([convertToArrayBuffer(body)], blobOptions);
+        } else if (responseType === "document") {
+            if (isXmlContentType(contentType)) {
+                return FakeXMLHttpRequest.parseXML(body);
+            }
+            return null;
+        }
+        throw new Error("Invalid responseType " + responseType);
+    }
+
+    function clearResponse(xhr) {
+        if (xhr.responseType === "" || xhr.responseType === "text") {
+            xhr.response = xhr.responseText = "";
+        } else {
+            xhr.response = xhr.responseText = null;
+        }
+        xhr.responseXML = null;
+    }
+
+    FakeXMLHttpRequest.parseXML = function parseXML(text) {
+        // Treat empty string as parsing failure
+        if (text !== "") {
+            try {
+                if (typeof DOMParser !== "undefined") {
+                    var parser = new DOMParser();
+                    return parser.parseFromString(text, "text/xml");
+                }
+                var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
+                xmlDoc.async = "false";
+                xmlDoc.loadXML(text);
+                return xmlDoc;
+            } catch (e) {
+                // Unable to parse XML - no biggie
+            }
+        }
+
+        return null;
+    };
+
+    FakeXMLHttpRequest.statusCodes = {
+        100: "Continue",
+        101: "Switching Protocols",
+        200: "OK",
+        201: "Created",
+        202: "Accepted",
+        203: "Non-Authoritative Information",
+        204: "No Content",
+        205: "Reset Content",
+        206: "Partial Content",
+        207: "Multi-Status",
+        300: "Multiple Choice",
+        301: "Moved Permanently",
+        302: "Found",
+        303: "See Other",
+        304: "Not Modified",
+        305: "Use Proxy",
+        307: "Temporary Redirect",
+        400: "Bad Request",
+        401: "Unauthorized",
+        402: "Payment Required",
+        403: "Forbidden",
+        404: "Not Found",
+        405: "Method Not Allowed",
+        406: "Not Acceptable",
+        407: "Proxy Authentication Required",
+        408: "Request Timeout",
+        409: "Conflict",
+        410: "Gone",
+        411: "Length Required",
+        412: "Precondition Failed",
+        413: "Request Entity Too Large",
+        414: "Request-URI Too Long",
+        415: "Unsupported Media Type",
+        416: "Requested Range Not Satisfiable",
+        417: "Expectation Failed",
+        422: "Unprocessable Entity",
+        500: "Internal Server Error",
+        501: "Not Implemented",
+        502: "Bad Gateway",
+        503: "Service Unavailable",
+        504: "Gateway Timeout",
+        505: "HTTP Version Not Supported"
+    };
+
+    function makeApi(sinon) {
+        sinon.xhr = sinonXhr;
+
+        sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
+            async: true,
+
+            open: function open(method, url, async, username, password) {
+                this.method = method;
+                this.url = url;
+                this.async = typeof async === "boolean" ? async : true;
+                this.username = username;
+                this.password = password;
+                clearResponse(this);
+                this.requestHeaders = {};
+                this.sendFlag = false;
+
+                if (FakeXMLHttpRequest.useFilters === true) {
+                    var xhrArgs = arguments;
+                    var defake = some(FakeXMLHttpRequest.filters, function (filter) {
+                        return filter.apply(this, xhrArgs);
+                    });
+                    if (defake) {
+                        return FakeXMLHttpRequest.defake(this, arguments);
+                    }
+                }
+                this.readyStateChange(FakeXMLHttpRequest.OPENED);
+            },
+
+            readyStateChange: function readyStateChange(state) {
+                this.readyState = state;
+
+                var readyStateChangeEvent = new sinon.Event("readystatechange", false, false, this);
+
+                if (typeof this.onreadystatechange === "function") {
+                    try {
+                        this.onreadystatechange(readyStateChangeEvent);
+                    } catch (e) {
+                        sinon.logError("Fake XHR onreadystatechange handler", e);
+                    }
+                }
+
+                switch (this.readyState) {
+                    case FakeXMLHttpRequest.DONE:
+                        if (supportsProgress) {
+                            this.upload.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
+                            this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
+                        }
+                        this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
+                        this.dispatchEvent(new sinon.Event("load", false, false, this));
+                        this.dispatchEvent(new sinon.Event("loadend", false, false, this));
+                        break;
+                }
+
+                this.dispatchEvent(readyStateChangeEvent);
+            },
+
+            setRequestHeader: function setRequestHeader(header, value) {
+                verifyState(this);
+
+                if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
+                    throw new Error("Refused to set unsafe header \"" + header + "\"");
+                }
+
+                if (this.requestHeaders[header]) {
+                    this.requestHeaders[header] += "," + value;
+                } else {
+                    this.requestHeaders[header] = value;
+                }
+            },
+
+            // Helps testing
+            setResponseHeaders: function setResponseHeaders(headers) {
+                verifyRequestOpened(this);
+                this.responseHeaders = {};
+
+                for (var header in headers) {
+                    if (headers.hasOwnProperty(header)) {
+                        this.responseHeaders[header] = headers[header];
+                    }
+                }
+
+                if (this.async) {
+                    this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
+                } else {
+                    this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
+                }
+            },
+
+            // Currently treats ALL data as a DOMString (i.e. no Document)
+            send: function send(data) {
+                verifyState(this);
+
+                if (!/^(get|head)$/i.test(this.method)) {
+                    var contentType = getHeader(this.requestHeaders, "Content-Type");
+                    if (this.requestHeaders[contentType]) {
+                        var value = this.requestHeaders[contentType].split(";");
+                        this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
+                    } else if (supportsFormData && !(data instanceof FormData)) {
+                        this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+                    }
+
+                    this.requestBody = data;
+                }
+
+                this.errorFlag = false;
+                this.sendFlag = this.async;
+                clearResponse(this);
+                this.readyStateChange(FakeXMLHttpRequest.OPENED);
+
+                if (typeof this.onSend === "function") {
+                    this.onSend(this);
+                }
+
+                this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
+            },
+
+            abort: function abort() {
+                this.aborted = true;
+                clearResponse(this);
+                this.errorFlag = true;
+                this.requestHeaders = {};
+                this.responseHeaders = {};
+
+                if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
+                    this.readyStateChange(FakeXMLHttpRequest.DONE);
+                    this.sendFlag = false;
+                }
+
+                this.readyState = FakeXMLHttpRequest.UNSENT;
+
+                this.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+                this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+                if (typeof this.onerror === "function") {
+                    this.onerror();
+                }
+            },
+
+            getResponseHeader: function getResponseHeader(header) {
+                if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                    return null;
+                }
+
+                if (/^Set-Cookie2?$/i.test(header)) {
+                    return null;
+                }
+
+                header = getHeader(this.responseHeaders, header);
+
+                return this.responseHeaders[header] || null;
+            },
+
+            getAllResponseHeaders: function getAllResponseHeaders() {
+                if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                    return "";
+                }
+
+                var headers = "";
+
+                for (var header in this.responseHeaders) {
+                    if (this.responseHeaders.hasOwnProperty(header) &&
+                        !/^Set-Cookie2?$/i.test(header)) {
+                        headers += header + ": " + this.responseHeaders[header] + "\r\n";
+                    }
+                }
+
+                return headers;
+            },
+
+            setResponseBody: function setResponseBody(body) {
+                verifyRequestSent(this);
+                verifyHeadersReceived(this);
+                verifyResponseBodyType(body);
+                var contentType = this.getResponseHeader("Content-Type");
+
+                var isTextResponse = this.responseType === "" || this.responseType === "text";
+                clearResponse(this);
+                if (this.async) {
+                    var chunkSize = this.chunkSize || 10;
+                    var index = 0;
+
+                    do {
+                        this.readyStateChange(FakeXMLHttpRequest.LOADING);
+
+                        if (isTextResponse) {
+                            this.responseText = this.response += body.substring(index, index + chunkSize);
+                        }
+                        index += chunkSize;
+                    } while (index < body.length);
+                }
+
+                this.response = convertResponseBody(this.responseType, contentType, body);
+                if (isTextResponse) {
+                    this.responseText = this.response;
+                }
+
+                if (this.responseType === "document") {
+                    this.responseXML = this.response;
+                } else if (this.responseType === "" && isXmlContentType(contentType)) {
+                    this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
+                }
+                this.readyStateChange(FakeXMLHttpRequest.DONE);
+            },
+
+            respond: function respond(status, headers, body) {
+                this.status = typeof status === "number" ? status : 200;
+                this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
+                this.setResponseHeaders(headers || {});
+                this.setResponseBody(body || "");
+            },
+
+            uploadProgress: function uploadProgress(progressEventRaw) {
+                if (supportsProgress) {
+                    this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
+                }
+            },
+
+            downloadProgress: function downloadProgress(progressEventRaw) {
+                if (supportsProgress) {
+                    this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
+                }
+            },
+
+            uploadError: function uploadError(error) {
+                if (supportsCustomEvent) {
+                    this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
+                }
+            }
+        });
+
+        sinon.extend(FakeXMLHttpRequest, {
+            UNSENT: 0,
+            OPENED: 1,
+            HEADERS_RECEIVED: 2,
+            LOADING: 3,
+            DONE: 4
+        });
+
+        sinon.useFakeXMLHttpRequest = function () {
+            FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
+                if (sinonXhr.supportsXHR) {
+                    global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
+                }
+
+                if (sinonXhr.supportsActiveX) {
+                    global.ActiveXObject = sinonXhr.GlobalActiveXObject;
+                }
+
+                delete FakeXMLHttpRequest.restore;
+
+                if (keepOnCreate !== true) {
+                    delete FakeXMLHttpRequest.onCreate;
+                }
+            };
+            if (sinonXhr.supportsXHR) {
+                global.XMLHttpRequest = FakeXMLHttpRequest;
+            }
+
+            if (sinonXhr.supportsActiveX) {
+                global.ActiveXObject = function ActiveXObject(objId) {
+                    if (objId === "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
+
+                        return new FakeXMLHttpRequest();
+                    }
+
+                    return new sinonXhr.GlobalActiveXObject(objId);
+                };
+            }
+
+            return FakeXMLHttpRequest;
+        };
+
+        sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./core");
+        require("../extend");
+        require("./event");
+        require("../log_error");
+        makeApi(sinon);
+        module.exports = sinon;
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon, // eslint-disable-line no-undef
+    typeof global !== "undefined" ? global : self
+));
+
+/**
+ * @depend fake_xdomain_request.js
+ * @depend fake_xml_http_request.js
+ * @depend ../format.js
+ * @depend ../log_error.js
+ */
+/**
+ * The Sinon "server" mimics a web server that receives requests from
+ * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
+ * both synchronously and asynchronously. To respond synchronuously, canned
+ * answers have to be provided upfront.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function () {
+    
+    var push = [].push;
+
+    function responseArray(handler) {
+        var response = handler;
+
+        if (Object.prototype.toString.call(handler) !== "[object Array]") {
+            response = [200, {}, handler];
+        }
+
+        if (typeof response[2] !== "string") {
+            throw new TypeError("Fake server response body should be string, but was " +
+                                typeof response[2]);
+        }
+
+        return response;
+    }
+
+    var wloc = typeof window !== "undefined" ? window.location : {};
+    var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
+
+    function matchOne(response, reqMethod, reqUrl) {
+        var rmeth = response.method;
+        var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase();
+        var url = response.url;
+        var matchUrl = !url || url === reqUrl || (typeof url.test === "function" && url.test(reqUrl));
+
+        return matchMethod && matchUrl;
+    }
+
+    function match(response, request) {
+        var requestUrl = request.url;
+
+        if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
+            requestUrl = requestUrl.replace(rCurrLoc, "");
+        }
+
+        if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
+            if (typeof response.response === "function") {
+                var ru = response.url;
+                var args = [request].concat(ru && typeof ru.exec === "function" ? ru.exec(requestUrl).slice(1) : []);
+                return response.response.apply(response, args);
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    function makeApi(sinon) {
+        sinon.fakeServer = {
+            create: function (config) {
+                var server = sinon.create(this);
+                server.configure(config);
+                if (!sinon.xhr.supportsCORS) {
+                    this.xhr = sinon.useFakeXDomainRequest();
+                } else {
+                    this.xhr = sinon.useFakeXMLHttpRequest();
+                }
+                server.requests = [];
+
+                this.xhr.onCreate = function (xhrObj) {
+                    server.addRequest(xhrObj);
+                };
+
+                return server;
+            },
+            configure: function (config) {
+                var whitelist = {
+                    "autoRespond": true,
+                    "autoRespondAfter": true,
+                    "respondImmediately": true,
+                    "fakeHTTPMethods": true
+                };
+                var setting;
+
+                config = config || {};
+                for (setting in config) {
+                    if (whitelist.hasOwnProperty(setting) && config.hasOwnProperty(setting)) {
+                        this[setting] = config[setting];
+                    }
+                }
+            },
+            addRequest: function addRequest(xhrObj) {
+                var server = this;
+                push.call(this.requests, xhrObj);
+
+                xhrObj.onSend = function () {
+                    server.handleRequest(this);
+
+                    if (server.respondImmediately) {
+                        server.respond();
+                    } else if (server.autoRespond && !server.responding) {
+                        setTimeout(function () {
+                            server.responding = false;
+                            server.respond();
+                        }, server.autoRespondAfter || 10);
+
+                        server.responding = true;
+                    }
+                };
+            },
+
+            getHTTPMethod: function getHTTPMethod(request) {
+                if (this.fakeHTTPMethods && /post/i.test(request.method)) {
+                    var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
+                    return matches ? matches[1] : request.method;
+                }
+
+                return request.method;
+            },
+
+            handleRequest: function handleRequest(xhr) {
+                if (xhr.async) {
+                    if (!this.queue) {
+                        this.queue = [];
+                    }
+
+                    push.call(this.queue, xhr);
+                } else {
+                    this.processRequest(xhr);
+                }
+            },
+
+            log: function log(response, request) {
+                var str;
+
+                str = "Request:\n" + sinon.format(request) + "\n\n";
+                str += "Response:\n" + sinon.format(response) + "\n\n";
+
+                sinon.log(str);
+            },
+
+            respondWith: function respondWith(method, url, body) {
+                if (arguments.length === 1 && typeof method !== "function") {
+                    this.response = responseArray(method);
+                    return;
+                }
+
+                if (!this.responses) {
+                    this.responses = [];
+                }
+
+                if (arguments.length === 1) {
+                    body = method;
+                    url = method = null;
+                }
+
+                if (arguments.length === 2) {
+                    body = url;
+                    url = method;
+                    method = null;
+                }
+
+                push.call(this.responses, {
+                    method: method,
+                    url: url,
+                    response: typeof body === "function" ? body : responseArray(body)
+                });
+            },
+
+            respond: function respond() {
+                if (arguments.length > 0) {
+                    this.respondWith.apply(this, arguments);
+                }
+
+                var queue = this.queue || [];
+                var requests = queue.splice(0, queue.length);
+
+                for (var i = 0; i < requests.length; i++) {
+                    this.processRequest(requests[i]);
+                }
+            },
+
+            processRequest: function processRequest(request) {
+                try {
+                    if (request.aborted) {
+                        return;
+                    }
+
+                    var response = this.response || [404, {}, ""];
+
+                    if (this.responses) {
+                        for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
+                            if (match.call(this, this.responses[i], request)) {
+                                response = this.responses[i].response;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (request.readyState !== 4) {
+                        this.log(response, request);
+
+                        request.respond(response[0], response[1], response[2]);
+                    }
+                } catch (e) {
+                    sinon.logError("Fake server request processing", e);
+                }
+            },
+
+            restore: function restore() {
+                return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
+            }
+        };
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./core");
+        require("./fake_xdomain_request");
+        require("./fake_xml_http_request");
+        require("../format");
+        makeApi(sinon);
+        module.exports = sinon;
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+    } else if (isNode) {
+        loadDependencies(require, module.exports, module);
+    } else {
+        makeApi(sinon); // eslint-disable-line no-undef
+    }
+}());
+
+/**
+ * @depend fake_server.js
+ * @depend fake_timers.js
+ */
+/**
+ * Add-on for sinon.fakeServer that automatically handles a fake timer along with
+ * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
+ * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
+ * it polls the object for completion with setInterval. Dispite the direct
+ * motivation, there is nothing jQuery-specific in this file, so it can be used
+ * in any environment where the ajax implementation depends on setInterval or
+ * setTimeout.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function () {
+    
+    function makeApi(sinon) {
+        function Server() {}
+        Server.prototype = sinon.fakeServer;
+
+        sinon.fakeServerWithClock = new Server();
+
+        sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
+            if (xhr.async) {
+                if (typeof setTimeout.clock === "object") {
+                    this.clock = setTimeout.clock;
+                } else {
+                    this.clock = sinon.useFakeTimers();
+                    this.resetClock = true;
+                }
+
+                if (!this.longestTimeout) {
+                    var clockSetTimeout = this.clock.setTimeout;
+                    var clockSetInterval = this.clock.setInterval;
+                    var server = this;
+
+                    this.clock.setTimeout = function (fn, timeout) {
+                        server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+                        return clockSetTimeout.apply(this, arguments);
+                    };
+
+                    this.clock.setInterval = function (fn, timeout) {
+                        server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+                        return clockSetInterval.apply(this, arguments);
+                    };
+                }
+            }
+
+            return sinon.fakeServer.addRequest.call(this, xhr);
+        };
+
+        sinon.fakeServerWithClock.respond = function respond() {
+            var returnVal = sinon.fakeServer.respond.apply(this, arguments);
+
+            if (this.clock) {
+                this.clock.tick(this.longestTimeout || 0);
+                this.longestTimeout = 0;
+
+                if (this.resetClock) {
+                    this.clock.restore();
+                    this.resetClock = false;
+                }
+            }
+
+            return returnVal;
+        };
+
+        sinon.fakeServerWithClock.restore = function restore() {
+            if (this.clock) {
+                this.clock.restore();
+            }
+
+            return sinon.fakeServer.restore.apply(this, arguments);
+        };
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require) {
+        var sinon = require("./core");
+        require("./fake_server");
+        require("./fake_timers");
+        makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+    } else if (isNode) {
+        loadDependencies(require);
+    } else {
+        makeApi(sinon); // eslint-disable-line no-undef
+    }
+}());
+
+/**
+ * @depend util/core.js
+ * @depend extend.js
+ * @depend collection.js
+ * @depend util/fake_timers.js
+ * @depend util/fake_server_with_clock.js
+ */
+/**
+ * Manages fake collections as well as fake utilities such as Sinon's
+ * timers and fake XHR implementation in one convenient object.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        var push = [].push;
+
+        function exposeValue(sandbox, config, key, value) {
+            if (!value) {
+                return;
+            }
+
+            if (config.injectInto && !(key in config.injectInto)) {
+                config.injectInto[key] = value;
+                sandbox.injectedKeys.push(key);
+            } else {
+                push.call(sandbox.args, value);
+            }
+        }
+
+        function prepareSandboxFromConfig(config) {
+            var sandbox = sinon.create(sinon.sandbox);
+
+            if (config.useFakeServer) {
+                if (typeof config.useFakeServer === "object") {
+                    sandbox.serverPrototype = config.useFakeServer;
+                }
+
+                sandbox.useFakeServer();
+            }
+
+            if (config.useFakeTimers) {
+                if (typeof config.useFakeTimers === "object") {
+                    sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
+                } else {
+                    sandbox.useFakeTimers();
+                }
+            }
+
+            return sandbox;
+        }
+
+        sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
+            useFakeTimers: function useFakeTimers() {
+                this.clock = sinon.useFakeTimers.apply(sinon, arguments);
+
+                return this.add(this.clock);
+            },
+
+            serverPrototype: sinon.fakeServer,
+
+            useFakeServer: function useFakeServer() {
+                var proto = this.serverPrototype || sinon.fakeServer;
+
+                if (!proto || !proto.create) {
+                    return null;
+                }
+
+                this.server = proto.create();
+                return this.add(this.server);
+            },
+
+            inject: function (obj) {
+                sinon.collection.inject.call(this, obj);
+
+                if (this.clock) {
+                    obj.clock = this.clock;
+                }
+
+                if (this.server) {
+                    obj.server = this.server;
+                    obj.requests = this.server.requests;
+                }
+
+                obj.match = sinon.match;
+
+                return obj;
+            },
+
+            restore: function () {
+                sinon.collection.restore.apply(this, arguments);
+                this.restoreContext();
+            },
+
+            restoreContext: function () {
+                if (this.injectedKeys) {
+                    for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
+                        delete this.injectInto[this.injectedKeys[i]];
+                    }
+                    this.injectedKeys = [];
+                }
+            },
+
+            create: function (config) {
+                if (!config) {
+                    return sinon.create(sinon.sandbox);
+                }
+
+                var sandbox = prepareSandboxFromConfig(config);
+                sandbox.args = sandbox.args || [];
+                sandbox.injectedKeys = [];
+                sandbox.injectInto = config.injectInto;
+                var prop,
+                    value;
+                var exposed = sandbox.inject({});
+
+                if (config.properties) {
+                    for (var i = 0, l = config.properties.length; i < l; i++) {
+                        prop = config.properties[i];
+                        value = exposed[prop] || prop === "sandbox" && sandbox;
+                        exposeValue(sandbox, config, prop, value);
+                    }
+                } else {
+                    exposeValue(sandbox, config, "sandbox", value);
+                }
+
+                return sandbox;
+            },
+
+            match: sinon.match
+        });
+
+        sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
+
+        return sinon.sandbox;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        require("./extend");
+        require("./util/fake_server_with_clock");
+        require("./util/fake_timers");
+        require("./collection");
+        module.exports = makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend sandbox.js
+ */
+/**
+ * Test function, sandboxes fakes
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    function makeApi(sinon) {
+        var slice = Array.prototype.slice;
+
+        function test(callback) {
+            var type = typeof callback;
+
+            if (type !== "function") {
+                throw new TypeError("sinon.test needs to wrap a test function, got " + type);
+            }
+
+            function sinonSandboxedTest() {
+                var config = sinon.getConfig(sinon.config);
+                config.injectInto = config.injectIntoThis && this || config.injectInto;
+                var sandbox = sinon.sandbox.create(config);
+                var args = slice.call(arguments);
+                var oldDone = args.length && args[args.length - 1];
+                var exception, result;
+
+                if (typeof oldDone === "function") {
+                    args[args.length - 1] = function sinonDone(res) {
+                        if (res) {
+                            sandbox.restore();
+                        } else {
+                            sandbox.verifyAndRestore();
+                        }
+                        oldDone(res);
+                    };
+                }
+
+                try {
+                    result = callback.apply(this, args.concat(sandbox.args));
+                } catch (e) {
+                    exception = e;
+                }
+
+                if (typeof oldDone !== "function") {
+                    if (typeof exception !== "undefined") {
+                        sandbox.restore();
+                        throw exception;
+                    } else {
+                        sandbox.verifyAndRestore();
+                    }
+                }
+
+                return result;
+            }
+
+            if (callback.length) {
+                return function sinonAsyncSandboxedTest(done) { // eslint-disable-line no-unused-vars
+                    return sinonSandboxedTest.apply(this, arguments);
+                };
+            }
+
+            return sinonSandboxedTest;
+        }
+
+        test.config = {
+            injectIntoThis: true,
+            injectInto: null,
+            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+            useFakeTimers: true,
+            useFakeServer: true
+        };
+
+        sinon.test = test;
+        return test;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var core = require("./util/core");
+        require("./sandbox");
+        module.exports = makeApi(core);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+    } else if (isNode) {
+        loadDependencies(require, module.exports, module);
+    } else if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(typeof sinon === "object" && sinon || null)); // eslint-disable-line no-undef
+
+/**
+ * @depend util/core.js
+ * @depend test.js
+ */
+/**
+ * Test case, sandboxes all test functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+    
+    function createTest(property, setUp, tearDown) {
+        return function () {
+            if (setUp) {
+                setUp.apply(this, arguments);
+            }
+
+            var exception, result;
+
+            try {
+                result = property.apply(this, arguments);
+            } catch (e) {
+                exception = e;
+            }
+
+            if (tearDown) {
+                tearDown.apply(this, arguments);
+            }
+
+            if (exception) {
+                throw exception;
+            }
+
+            return result;
+        };
+    }
+
+    function makeApi(sinon) {
+        function testCase(tests, prefix) {
+            if (!tests || typeof tests !== "object") {
+                throw new TypeError("sinon.testCase needs an object with test functions");
+            }
+
+            prefix = prefix || "test";
+            var rPrefix = new RegExp("^" + prefix);
+            var methods = {};
+            var setUp = tests.setUp;
+            var tearDown = tests.tearDown;
+            var testName,
+                property,
+                method;
+
+            for (testName in tests) {
+                if (tests.hasOwnProperty(testName) && !/^(setUp|tearDown)$/.test(testName)) {
+                    property = tests[testName];
+
+                    if (typeof property === "function" && rPrefix.test(testName)) {
+                        method = property;
+
+                        if (setUp || tearDown) {
+                            method = createTest(property, setUp, tearDown);
+                        }
+
+                        methods[testName] = sinon.test(method);
+                    } else {
+                        methods[testName] = tests[testName];
+                    }
+                }
+            }
+
+            return methods;
+        }
+
+        sinon.testCase = testCase;
+        return testCase;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var core = require("./util/core");
+        require("./test");
+        module.exports = makeApi(core);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend times_in_words.js
+ * @depend util/core.js
+ * @depend match.js
+ * @depend format.js
+ */
+/**
+ * Assertions matching the test spy retrieval interface.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal, global) {
+    
+    var slice = Array.prototype.slice;
+
+    function makeApi(sinon) {
+        var assert;
+
+        function verifyIsStub() {
+            var method;
+
+            for (var i = 0, l = arguments.length; i < l; ++i) {
+                method = arguments[i];
+
+                if (!method) {
+                    assert.fail("fake is not a spy");
+                }
+
+                if (method.proxy && method.proxy.isSinonProxy) {
+                    verifyIsStub(method.proxy);
+                } else {
+                    if (typeof method !== "function") {
+                        assert.fail(method + " is not a function");
+                    }
+
+                    if (typeof method.getCall !== "function") {
+                        assert.fail(method + " is not stubbed");
+                    }
+                }
+
+            }
+        }
+
+        function failAssertion(object, msg) {
+            object = object || global;
+            var failMethod = object.fail || assert.fail;
+            failMethod.call(object, msg);
+        }
+
+        function mirrorPropAsAssertion(name, method, message) {
+            if (arguments.length === 2) {
+                message = method;
+                method = name;
+            }
+
+            assert[name] = function (fake) {
+                verifyIsStub(fake);
+
+                var args = slice.call(arguments, 1);
+                var failed = false;
+
+                if (typeof method === "function") {
+                    failed = !method(fake);
+                } else {
+                    failed = typeof fake[method] === "function" ?
+                        !fake[method].apply(fake, args) : !fake[method];
+                }
+
+                if (failed) {
+                    failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
+                } else {
+                    assert.pass(name);
+                }
+            };
+        }
+
+        function exposedName(prefix, prop) {
+            return !prefix || /^fail/.test(prop) ? prop :
+                prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
+        }
+
+        assert = {
+            failException: "AssertError",
+
+            fail: function fail(message) {
+                var error = new Error(message);
+                error.name = this.failException || assert.failException;
+
+                throw error;
+            },
+
+            pass: function pass() {},
+
+            callOrder: function assertCallOrder() {
+                verifyIsStub.apply(null, arguments);
+                var expected = "";
+                var actual = "";
+
+                if (!sinon.calledInOrder(arguments)) {
+                    try {
+                        expected = [].join.call(arguments, ", ");
+                        var calls = slice.call(arguments);
+                        var i = calls.length;
+                        while (i) {
+                            if (!calls[--i].called) {
+                                calls.splice(i, 1);
+                            }
+                        }
+                        actual = sinon.orderByFirstCall(calls).join(", ");
+                    } catch (e) {
+                        // If this fails, we'll just fall back to the blank string
+                    }
+
+                    failAssertion(this, "expected " + expected + " to be " +
+                                "called in order but were called as " + actual);
+                } else {
+                    assert.pass("callOrder");
+                }
+            },
+
+            callCount: function assertCallCount(method, count) {
+                verifyIsStub(method);
+
+                if (method.callCount !== count) {
+                    var msg = "expected %n to be called " + sinon.timesInWords(count) +
+                        " but was called %c%C";
+                    failAssertion(this, method.printf(msg));
+                } else {
+                    assert.pass("callCount");
+                }
+            },
+
+            expose: function expose(target, options) {
+                if (!target) {
+                    throw new TypeError("target is null or undefined");
+                }
+
+                var o = options || {};
+                var prefix = typeof o.prefix === "undefined" && "assert" || o.prefix;
+                var includeFail = typeof o.includeFail === "undefined" || !!o.includeFail;
+
+                for (var method in this) {
+                    if (method !== "expose" && (includeFail || !/^(fail)/.test(method))) {
+                        target[exposedName(prefix, method)] = this[method];
+                    }
+                }
+
+                return target;
+            },
+
+            match: function match(actual, expectation) {
+                var matcher = sinon.match(expectation);
+                if (matcher.test(actual)) {
+                    assert.pass("match");
+                } else {
+                    var formatted = [
+                        "expected value to match",
+                        "    expected = " + sinon.format(expectation),
+                        "    actual = " + sinon.format(actual)
+                    ];
+
+                    failAssertion(this, formatted.join("\n"));
+                }
+            }
+        };
+
+        mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
+        mirrorPropAsAssertion("notCalled", function (spy) {
+            return !spy.called;
+        }, "expected %n to not have been called but was called %c%C");
+        mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
+        mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
+        mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
+        mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
+        mirrorPropAsAssertion(
+            "alwaysCalledOn",
+            "expected %n to always be called with %1 as this but was called with %t"
+        );
+        mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
+        mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
+        mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
+        mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
+        mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
+        mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
+        mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
+        mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
+        mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
+        mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
+        mirrorPropAsAssertion("threw", "%n did not throw exception%C");
+        mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
+
+        sinon.assert = assert;
+        return assert;
+    }
+
+    var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+    var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+    function loadDependencies(require, exports, module) {
+        var sinon = require("./util/core");
+        require("./match");
+        require("./format");
+        module.exports = makeApi(sinon);
+    }
+
+    if (isAMD) {
+        define(loadDependencies);
+        return;
+    }
+
+    if (isNode) {
+        loadDependencies(require, module.exports, module);
+        return;
+    }
+
+    if (sinonGlobal) {
+        makeApi(sinonGlobal);
+    }
+}(
+    typeof sinon === "object" && sinon, // eslint-disable-line no-undef
+    typeof global !== "undefined" ? global : self
+));
+
+  return sinon;
+}));
diff --git a/resources/lib/sinonjs/sinon-ie-1.15.4.js b/resources/lib/sinonjs/sinon-ie-1.15.4.js
deleted file mode 100644 (file)
index 9eac958..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Sinon.JS 1.15.4, 2015/06/27
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Helps IE run the fake timers. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake timers to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-if (typeof window !== "undefined") {
-    function setTimeout() {}
-    function clearTimeout() {}
-    function setImmediate() {}
-    function clearImmediate() {}
-    function setInterval() {}
-    function clearInterval() {}
-    function Date() {}
-
-    // Reassign the original functions. Now their writable attribute
-    // should be true. Hackish, I know, but it works.
-    setTimeout = sinon.timers.setTimeout;
-    clearTimeout = sinon.timers.clearTimeout;
-    setImmediate = sinon.timers.setImmediate;
-    clearImmediate = sinon.timers.clearImmediate;
-    setInterval = sinon.timers.setInterval;
-    clearInterval = sinon.timers.clearInterval;
-    Date = sinon.timers.Date;
-}
-
-/**
- * Helps IE run the fake XMLHttpRequest. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake XHR to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-if (typeof window !== "undefined") {
-    function XMLHttpRequest() {}
-
-    // Reassign the original function. Now its writable attribute
-    // should be true. Hackish, I know, but it works.
-    XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
-}
-/**
- * Helps IE run the fake XDomainRequest. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake XDR to work in IE, don't include this file.
- */
-if (typeof window !== "undefined") {
-    function XDomainRequest() {}
-
-    // Reassign the original function. Now its writable attribute
-    // should be true. Hackish, I know, but it works.
-    XDomainRequest = sinon.xdr.XDomainRequest || undefined;
-}
index 19fdb26..ddc57ec 100644 (file)
                        options = {};
                }
 
-               return this.each( function () {
+               this.each( function () {
                        var $collapsible, collapseText, expandText, $caption, $toggle, actionHandler, buildDefaultToggleLink,
                                premadeToggleHandler, $toggleLink, $firstItem, collapsibleId, $customTogglers, firstval;
 
                                }
                        }
 
+                       $( this ).data( 'mw-collapsible', {
+                               collapse: function () {
+                                       actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: false } );
+                               },
+                               expand: function () {
+                                       actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: true } );
+                               },
+                               toggle: function () {
+                                       actionHandler.call( $toggleLink.get( 0 ), null, null );
+                               }
+                       } );
+
                        // Initial state
                        if ( options.collapsed || $collapsible.hasClass( 'mw-collapsed' ) ) {
                                // One toggler can hook to multiple elements, and one element can have
                                // multiple togglers. This is the sanest way to handle that.
                                actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: false } );
                        }
+
                } );
+
+               /**
+                * Fired after collapsible content has been initialized
+                *
+                * This gives an option to modify the collapsible behavior.
+                *
+                * @event wikipage_collapsibleContent
+                * @member mw.hook
+                * @param {jQuery} $content All the elements that have been made collapsible
+                */
+               mw.hook( 'wikipage.collapsibleContent' ).fire( this );
+
+               return this;
        };
 
        /**
index 1f977bf..38e5a1f 100644 (file)
@@ -14,7 +14,7 @@
  *
  *             $( '#textbox' ).suggestions();
  *
- * Uses jQuery.suggestions singleteon internally.
+ * Uses jQuery.suggestions singleton internally.
  *
  * @class jQuery.plugin.suggestions
  */
index 2318b33..50bfa87 100644 (file)
                                        $.data( table, 'tablesorter', { config: config } );
 
                                        // Get the CSS class names, could be done elsewhere
-                                       sortCSS = [ config.cssDesc, config.cssAsc ];
+                                       sortCSS = [ config.cssAsc, config.cssDesc ];
+                                       // Messages tell the the user what the *next* state will be
+                                       // so are in reverse order to the CSS classes.
                                        sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ];
 
                                        // Build headers
index 168a1c1..b339371 100644 (file)
@@ -2,6 +2,10 @@
        'use strict';
 
        /**
+        * Fired after an edit was successfully saved.
+        *
+        * Does not fire for null edits.
+        *
         * @event postEdit
         * @member mw.hook
         * @param {Object} [data] Optional data
index 0d324ed..cf3ef79 100644 (file)
@@ -47,7 +47,7 @@ $.extend( mw.language, {
                var pluralRules,
                        pluralFormIndex = 0;
 
-               if ( explicitPluralForms && explicitPluralForms[ count ] ) {
+               if ( explicitPluralForms && ( explicitPluralForms[ count ] !== undefined ) ) {
                        return explicitPluralForms[ count ];
                }
 
index d4446ab..0dffd7d 100644 (file)
@@ -90,6 +90,9 @@
        "greek": [
                "Α", "Ά", "α", "ά", "Β", "β", "Γ", "γ", "Δ", "δ", "Ε", "Έ", "ε", "έ", "Ζ", "ζ", "Η", "Ή", "η", "ή", "Θ", "θ", "Ι", "Ί", "ι", "ί", "Κ", "κ", "Λ", "λ", "Μ", "μ", "Ν", "ν", "Ξ", "ξ", "Ο", "Ό", "ο", "ό", "Π", "π", "Ρ", "ρ", "Σ", "σ", "ς", "Τ", "τ", "Υ", "Ύ", "υ", "ύ", "Φ", "φ", "Χ", "χ", "Ψ", "ψ", "Ω", "Ώ", "ω", "ώ"
        ],
+       "greekextended": [
+               "ἀ", "ἁ", "ἂ", "ἃ", "ἄ", "ἅ", "ἆ", "ἇ", "Ἀ", "Ἁ", "Ἂ", "Ἃ", "Ἄ", "Ἅ", "Ἆ", "Ἇ", "ἐ", "ἑ", "ἒ", "ἓ", "ἔ", "ἕ", "Ἐ", "Ἑ", "Ἒ", "Ἓ", "Ἔ", "Ἕ", "ἠ", "ἡ", "ἢ", "ἣ", "ἤ", "ἥ", "ἦ", "ἧ", "Ἠ", "Ἡ", "Ἢ", "Ἣ", "Ἤ", "Ἥ", "Ἦ", "Ἧ", "ἰ", "ἱ", "ἲ", "ἳ", "ἴ", "ἵ", "ἶ", "ἷ", "Ἰ", "Ἱ", "Ἲ", "Ἳ", "Ἴ", "Ἵ", "Ἶ", "Ἷ", "ὀ", "ὁ", "ὂ", "ὃ", "ὄ", "ὅ", "Ὀ", "Ὁ", "Ὂ", "Ὃ", "Ὄ", "Ὅ", "ὐ", "ὑ", "ὒ", "ὓ", "ὔ", "ὕ", "ὖ", "ὗ", "Ὑ", "Ὓ", "Ὕ", "Ὗ", "ὠ", "ὡ", "ὢ", "ὣ", "ὤ", "ὥ", "ὦ", "ὧ", "Ὠ", "Ὡ", "Ὢ", "Ὣ", "Ὤ", "Ὥ", "Ὦ", "Ὧ", "ὰ", "ά", "ὲ", "έ", "ὴ", "ή", "ὶ", "ί", "ὸ", "ό", "ὺ", "ύ", "ὼ", "ώ", "ᾀ", "ᾁ", "ᾂ", "ᾃ", "ᾄ", "ᾅ", "ᾆ", "ᾇ", "ᾈ", "ᾉ", "ᾊ", "ᾋ", "ᾌ", "ᾍ", "ᾎ", "ᾏ", "ᾐ", "ᾑ", "ᾒ", "ᾓ", "ᾔ", "ᾕ", "ᾖ", "ᾗ", "ᾘ", "ᾙ", "ᾚ", "ᾛ", "ᾜ", "ᾝ", "ᾞ", "ᾟ", "ᾠ", "ᾡ", "ᾢ", "ᾣ", "ᾤ", "ᾥ", "ᾦ", "ᾧ", "ᾨ", "ᾩ", "ᾪ", "ᾫ", "ᾬ", "ᾭ", "ᾮ", "ᾯ", "ᾰ", "ᾱ", "ᾲ", "ᾳ", "ᾴ", "ᾶ", "ᾷ", "Ᾰ", "Ᾱ", "Ὰ", "Ά", "ᾼ", "᾽", "ι", "᾿", "῀", "῁", "ῂ", "ῃ", "ῄ", "ῆ", "ῇ", "Ὲ", "Έ", "Ὴ", "Ή", "ῌ", "῍", "῎", "῏", "ῐ", "ῑ", "ῒ", "ΐ", "ῖ", "ῗ", "Ῐ", "Ῑ", "Ὶ", "Ί", "῝", "῞", "῟", "ῠ", "ῡ", "ῢ", "ΰ", "ῤ", "ῥ", "ῦ", "ῧ", "Ῠ", "Ῡ", "Ὺ", "Ύ", "Ῥ", "῭", "΅", "`", "ῲ", "ῳ", "ῴ", "ῶ", "ῷ", "Ὸ", "Ό", "Ὼ", "Ώ", "ῼ", "´", "῾"
+       ],
        "cyrillic": [
                "А", "а", "Ӑ", "ӑ", "Ӓ", "ӓ", "Ә", "ә", "Ӛ", "ӛ", "Б", "б", "В", "в", "Г", "г", "Ґ", "ґ", "Ӷ", "ӷ", "Ѓ", "ѓ", "Ӻ", "ӻ", "Ғ", "ғ", "Ҕ", "ҕ", "Д", "д", "Ԁ", "ԁ", "Ԃ", "ԃ", "Ђ", "ђ", "Е", "е", "Ѐ", "ѐ", "Є", "є", "Ё", "ё", "Ӗ", "ӗ", "Ҽ", "ҽ", "Ҿ", "ҿ", "Ж", "ж", "Җ", "җ", "Ӂ", "ӂ", "Ӝ", "ӝ", "З", "з", "Ҙ", "ҙ", "Ӟ", "ӟ", "Ԑ", "ԑ", "Ӡ", "ӡ", "Ѕ", "ѕ", "Ԅ", "ԅ", "Ԇ", "ԇ", "И", "и", "І", "і", "Ї", "ї",
                [
index a2d106d..3cfc52c 100644 (file)
                                                return xhr;
                                        }
                                } )
+                                       .then( null, function ( code, data, result, jqXHR ) {
+                                               if ( code !== 'http' ) {
+                                                       // Not really an error, work around mw.Api thinking it is.
+                                                       return $.Deferred()
+                                                               .resolve( result, jqXHR )
+                                                               .promise();
+                                               }
+                                               return this;
+                                       } )
                                        .fail( function ( code, data ) {
                                                var details = 'HTTP error: ' + data.exception;
                                                $result.empty()
index fd907ac..9da6c83 100644 (file)
@@ -1,5 +1,5 @@
-/* Styles for user login and signup forms */
-.mw-form-related-link-container {
+/* User login and signup forms */
+.mw-ui-vform .mw-form-related-link-container {
        margin-bottom: 0.5em;
        text-align: center;
 }
index 42d5693..620c83a 100644 (file)
@@ -5,4 +5,29 @@
        background: url( images/glyph-people-large.png ) no-repeat 50%;
        margin: 0 auto;
        padding-top: 7.8em;
+       font-weight: bold;
+}
+
+/* Login Button, following `ButtonWidget (progressive)‎` from OOjs UI */
+#mw-createaccount-join {
+       color: #347bff;
+}
+#mw-createaccount-join:hover {
+       background-color: #ebf2ff; /* rgba(52, 123, 255, 0.1); */
+       border-color: #859ecc;
+       box-shadow: none;
+}
+#mw-createaccount-join:active {
+       background-color: #ebf2ff;
+       color: #1f4999;
+       border-color: #1f4999;
+}
+#mw-createaccount-join:focus {
+       background-color: #fff;
+       color: #1f4999;
+       border-color: #1f4999;
+       box-shadow: inset 0 0 0 1px #1f4999;
+}
+#mw-createaccount-join:active:focus {
+       background-color: #ebf2ff;
 }
index 29eaaad..58115c3 100644 (file)
         * @private
         */
        PageExistenceCache.prototype.processExistenceCheckQueue = function () {
-               var queue, titles;
+               var queue, titles,
+                       cache = this;
                if ( this.currentRequest ) {
                        // Don't fire off a million requests at the same time
                        this.currentRequest.always( function () {
-                               this.currentRequest = null;
-                               this.processExistenceCheckQueueDebounced();
-                       }.bind( this ) );
+                               cache.currentRequest = null;
+                               cache.processExistenceCheckQueueDebounced();
+                       } );
                        return;
                }
                queue = this.existenceCheckQueue;
                this.existenceCheckQueue = {};
                titles = Object.keys( queue ).filter( function ( title ) {
-                       if ( this.existenceCache.hasOwnProperty( title ) ) {
-                               queue[ title ].resolve( this.existenceCache[ title ] );
+                       if ( cache.existenceCache.hasOwnProperty( title ) ) {
+                               queue[ title ].resolve( cache.existenceCache[ title ] );
                        }
-                       return !this.existenceCache.hasOwnProperty( title );
-               }.bind( this ) );
+                       return !cache.existenceCache.hasOwnProperty( title );
+               } );
                if ( !titles.length ) {
                        return;
                }
                } ).done( function ( response ) {
                        $.each( response.query.pages, function ( index, page ) {
                                var title = new ForeignTitle( page.title ).getPrefixedText();
-                               this.existenceCache[ title ] = !page.missing;
-                               queue[ title ].resolve( this.existenceCache[ title ] );
+                               cache.existenceCache[ title ] = !page.missing;
+                               queue[ title ].resolve( cache.existenceCache[ title ] );
                        } );
-               }.bind( this ) );
+               } );
        };
 
        /**
         * @cfg {string} [apiUrl] API URL, if not the current wiki's API
         */
        mw.widgets.CategoryCapsuleItemWidget = function MWWCategoryCapsuleItemWidget( config ) {
+               var widget = this;
                // Parent constructor
                mw.widgets.CategoryCapsuleItemWidget.parent.call( this, $.extend( {
                        data: config.title.getMainText(),
                this.constructor.static.pageExistenceCaches[ this.apiUrl ]
                        .checkPageExistence( new ForeignTitle( this.title.getPrefixedText() ) )
                        .done( function ( exists ) {
-                               this.setMissing( !exists );
-                       }.bind( this ) );
+                               widget.setMissing( !exists );
+                       } );
                /*jshint +W024*/
        };
 
index b805e65..3d97711 100644 (file)
@@ -6,6 +6,16 @@
  */
 ( function ( $, mw ) {
 
+       var interwikiPrefixesPromise = new mw.Api().get( {
+                       action: 'query',
+                       meta: 'siteinfo',
+                       siprop: 'interwikimap'
+               } ).then( function ( data ) {
+                       return $.map( data.query.interwikimap, function ( interwiki ) {
+                               return interwiki.prefix;
+                       } );
+               } );
+
        /**
         * Mixin for title widgets
         *
@@ -28,8 +38,6 @@
         * @cfg {Object} [cache] Result cache which implements a 'set' method, taking keyed values as an argument
         */
        mw.widgets.TitleWidget = function MwWidgetsTitleWidget( config ) {
-               var widget = this;
-
                // Config initialization
                config = $.extend( {
                        maxLength: 255,
 
                // Initialization
                this.$element.addClass( 'mw-widget-titleWidget' );
-               this.interwikiPrefixes = [];
-               this.interwikiPrefixesPromise = new mw.Api().get( {
-                       action: 'query',
-                       meta: 'siteinfo',
-                       siprop: 'interwikimap'
-               } ).done( function ( data ) {
-                       $.each( data.query.interwikimap, function ( index, interwiki ) {
-                               widget.interwikiPrefixes.push( interwiki.prefix );
-                       } );
-               } );
        };
 
        /* Setup */
                        } };
 
                if ( mw.Title.newFromText( query ) ) {
-                       return this.interwikiPrefixesPromise.then( function () {
+                       return interwikiPrefixesPromise.then( function ( interwikiPrefixes ) {
                                var params,
                                        interwiki = query.substring( 0, query.indexOf( ':' ) );
                                if (
                                        interwiki && interwiki !== '' &&
-                                       widget.interwikiPrefixes.indexOf( interwiki ) !== -1
+                                       interwikiPrefixes.indexOf( interwiki ) !== -1
                                ) {
                                        return $.Deferred().resolve( { query: {
                                                pages: [ {
index 10e0c56..64e5976 100644 (file)
                                .done( function ( result, textStatus, jqXHR ) {
                                        if ( result === undefined || result === null || result === '' ) {
                                                apiDeferred.reject( 'ok-but-empty',
-                                                       'OK response but empty result (check HTTP headers?)'
+                                                       'OK response but empty result (check HTTP headers?)',
+                                                       result,
+                                                       jqXHR
                                                );
                                        } else if ( result.error ) {
                                                var code = result.error.code === undefined ? 'unknown' : result.error.code;
-                                               apiDeferred.reject( code, result );
+                                               apiDeferred.reject( code, result, result, jqXHR );
                                        } else {
                                                apiDeferred.resolve( result, jqXHR );
                                        }
index 49219d7..418fd23 100644 (file)
@@ -7,18 +7,30 @@
                /**
                 * Convenience method for 'action=parse'.
                 *
-                * @param {string} wikitext
+                * @param {string|mw.Title} content Content to parse, either as a wikitext string or
+                *   a mw.Title.
+                * @param {Object} additionalParams Parameters object to set custom settings, e.g.
+                *   redirects, sectionpreview.  prop should not be overridden.
                 * @return {jQuery.Promise}
                 * @return {Function} return.done
                 * @return {string} return.done.data Parsed HTML of `wikitext`.
                 */
-               parse: function ( wikitext ) {
-                       var apiPromise = this.get( {
+               parse: function ( content, additionalParams ) {
+                       var apiPromise, config = $.extend( {
                                formatversion: 2,
                                action: 'parse',
-                               contentmodel: 'wikitext',
-                               text: wikitext
-                       } );
+                               contentmodel: 'wikitext'
+                       }, additionalParams );
+
+                       if ( mw.Title && content instanceof mw.Title ) {
+                               // Parse existing page
+                               config.page = content.getPrefixedDb();
+                       } else {
+                               // Parse wikitext from input
+                               config.text = String( content );
+                       }
+
+                       apiPromise = this.get( config );
 
                        return apiPromise
                                .then( function ( data ) {
index c438d05..6859592 100644 (file)
                getUrl: function ( params ) {
                        var fragment = this.getFragment();
                        if ( fragment ) {
-                               return mw.util.getUrl( this.toString() + '#' + this.getFragment(), params );
+                               return mw.util.getUrl( this.toString() + '#' + fragment, params );
                        } else {
                                return mw.util.getUrl( this.toString(), params );
                        }
index 33b10bd..6af0edf 100644 (file)
                                );
                        }
 
-                       message = mw.message( 'api-error-' + error.code );
-                       if ( !message.exists() ) {
-                               message = mw.message( 'api-error-unknownerror', JSON.stringify( stateDetails ) );
+                       if ( error.code === 'protectedpage' ) {
+                               message = mw.message( 'protectedpagetext' );
+                       } else {
+                               message = mw.message( 'api-error-' + error.code );
+                               if ( !message.exists() ) {
+                                       message = mw.message( 'api-error-unknownerror', JSON.stringify( stateDetails ) );
+                               }
                        }
                        return new OO.ui.Error(
                                $( '<p>' ).append( message.parseDom() ),
                                        $( '<p>' ).msg( 'fileexists', 'File:' + warnings.exists ),
                                        { recoverable: false }
                                );
+                       } else if ( warnings[ 'exists-normalized' ] !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).msg( 'fileexists', 'File:' + warnings[ 'exists-normalized' ] ),
+                                       { recoverable: false }
+                               );
                        } else if ( warnings[ 'page-exists' ] !== undefined ) {
                                return new OO.ui.Error(
                                        $( '<p>' ).msg( 'filepageexists', 'File:' + warnings[ 'page-exists' ] ),
                                        $( '<p>' ).msg( 'api-error-duplicate-archive', 1 ),
                                        { recoverable: false }
                                );
+                       } else if ( warnings[ 'was-deleted' ] !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).msg( 'api-error-was-deleted' ),
+                                       { recoverable: false }
+                               );
                        } else if ( warnings.badfilename !== undefined ) {
                                // Change the name if the current name isn't acceptable
                                // TODO This might not really be the best place to do this
index f282db6..9d799db 100644 (file)
                         * @param {string} [moduleName] Name of currently executing module
                         * @return {jQuery.Promise}
                         */
-                       function queueModuleScript( src, moduleName ) {
+                       function queueModuleScript( src ) {
                                var r = $.Deferred();
 
                                pendingRequests.push( function () {
-                                       if ( moduleName && !hasOwn.call( registry, moduleName ) ) {
-                                               window.require = mw.loader.require;
-                                               window.module = registry[ moduleName ].module;
-                                       }
                                        addScript( src ).always( function () {
-                                               // Clear environment
-                                               delete window.require;
-                                               delete window.module;
                                                r.resolve();
 
                                                // Start the next one (if any)
index 796639f..dfc98ad 100644 (file)
@@ -3,37 +3,19 @@
  *
  * Loosely based on https://w3c.github.io/requestidlecallback/
  */
-( function ( mw, $ ) {
-       var tasks = [],
-               maxIdleDuration = 50,
-               timeout = null;
-
-       function schedule( trigger ) {
-               clearTimeout( timeout );
-               timeout = setTimeout( trigger, 700 );
-       }
-
-       function triggerIdle() {
-               var elapsed,
-                       start = mw.now();
-
-               while ( tasks.length ) {
-                       elapsed = mw.now() - start;
-                       if ( elapsed < maxIdleDuration ) {
-                               tasks.shift().callback();
-                       } else {
-                               // Idle moment expired, try again later
-                               schedule( triggerIdle );
-                               break;
-                       }
-               }
-       }
+( function ( mw ) {
+       var maxBusy = 50;
 
        mw.requestIdleCallbackInternal = function ( callback ) {
-               var task = { callback: callback };
-               tasks.push( task );
-
-               $( function () { schedule( triggerIdle ); } );
+               setTimeout( function () {
+                       var start = mw.now();
+                       callback( {
+                               didTimeout: false,
+                               timeRemaining: function () {
+                                       return Math.max( 0, maxBusy - ( mw.now() - start ) );
+                               }
+                       } );
+               }, 1 );
        };
 
        /**
@@ -43,8 +25,7 @@
         * @param {Function} callback
         */
        mw.requestIdleCallback = window.requestIdleCallback
-               ? function ( callback ) {
-                       window.requestIdleCallback( callback );
-               }
+               // Bind because it throws TypeError if context is not window
+               ? window.requestIdleCallback.bind( window )
                : mw.requestIdleCallbackInternal;
-}( mediaWiki, jQuery ) );
+}( mediaWiki ) );
index d2f2abd..0fdd9aa 100644 (file)
                 * @return {jQuery.Promise}
                 */
                getGroups: function ( callback ) {
-                       return getUserInfo().then(
-                               function ( userInfo ) { return userInfo.groups; },
-                               function () { return []; }
-                       ).done( callback );
+                       var userGroups = mw.config.get( 'wgUserGroups', [] );
+
+                       // Uses promise for backwards compatibility
+                       return $.Deferred().resolve( userGroups ).done( callback );
                },
 
                /**
index cc983e4..cccc468 100644 (file)
                /**
                 * Get the link to a page name (relative to `wgServer`),
                 *
-                * @param {string|null} [str=wgPageName] Page name
+                * @param {string|null} [pageName=wgPageName] Page name
                 * @param {Object} [params] A mapping of query parameter names to values,
                 *  e.g. `{ action: 'edit' }`
-                * @return {string} Url of the page with name of `str`
+                * @return {string} Url of the page with name of `pageName`
                 */
-               getUrl: function ( str, params ) {
-                       var titleFragmentStart,
-                               url,
+               getUrl: function ( pageName, params ) {
+                       var titleFragmentStart, url, query,
                                fragment = '',
-                               pageName = typeof str === 'string' ? str : mw.config.get( 'wgPageName' );
-
-                       // Find any fragment should one exist
-                       if ( typeof str === 'string' ) {
-                               titleFragmentStart = pageName.indexOf( '#' );
-                               if ( titleFragmentStart !== -1 ) {
-                                       fragment = pageName.slice( titleFragmentStart + 1 );
-                                       // Exclude the fragment from the page name
-                                       pageName = pageName.slice( 0, titleFragmentStart );
-                               }
+                               title = typeof pageName === 'string' ? pageName : mw.config.get( 'wgPageName' );
+
+                       // Find any fragment
+                       titleFragmentStart = title.indexOf( '#' );
+                       if ( titleFragmentStart !== -1 ) {
+                               fragment = title.slice( titleFragmentStart + 1 );
+                               // Exclude the fragment from the page name
+                               title = title.slice( 0, titleFragmentStart );
                        }
 
-                       url = mw.config.get( 'wgArticlePath' ).replace( '$1', util.wikiUrlencode( pageName ) );
-
-                       // Add query string if necessary
-                       if ( params && !$.isEmptyObject( params ) ) {
-                               url += ( url.indexOf( '?' ) !== -1 ? '&' : '?' ) + $.param( params );
+                       // Produce query string
+                       if ( params ) {
+                               query = $.param( params );
+                       }
+                       if ( query ) {
+                               url = title
+                                       ? util.wikiScript() + '?title=' + util.wikiUrlencode( title ) + '&' + query
+                                       : util.wikiScript() + '?' + query;
+                       } else {
+                               url = mw.config.get( 'wgArticlePath' ).replace( '$1', util.wikiUrlencode( title ) );
                        }
 
                        // Append the encoded fragment
-                       if ( fragment.length > 0 ) {
+                       if ( fragment.length ) {
                                url += '#' + util.escapeId( fragment );
                        }
 
index aa9dd05..6396331 100644 (file)
                 * @return {boolean}
                 */
                isElementInViewport: function ( el, rectangle ) {
-                       var elRect = el.getBoundingClientRect(),
+                       var $el = $( el ),
+                               offset = $el.offset(),
+                               rect = {
+                                       height: $el.height(),
+                                       width: $el.width(),
+                                       top: offset.top,
+                                       left: offset.left
+                               },
                                viewport = rectangle || this.makeViewportFromWindow();
 
                        return (
-                               ( viewport.bottom >= elRect.top ) &&
-                               ( viewport.right >= elRect.left ) &&
-                               ( viewport.top <= elRect.top + elRect.height ) &&
-                               ( viewport.left <= elRect.left + elRect.width )
+                               // Top border must be above viewport's bottom
+                               ( viewport.bottom >= rect.top ) &&
+                               // Left border must be before viewport's right border
+                               ( viewport.right >= rect.left ) &&
+                               // Bottom border must be below viewport's top
+                               ( viewport.top <= rect.top + rect.height ) &&
+                               // Right border must be after viewport's left border
+                               ( viewport.left <= rect.left + rect.width )
                        );
                },
 
index a097b17..02bc1de 100644 (file)
 
        function bindPageNavigation( $container ) {
                $container.find( '.multipageimagenavbox' ).one( 'click', 'a', function ( e ) {
-                       var page, uri;
+                       var page, url;
 
                        // Generate the same URL on client side as the one generated in ImagePage::openShowImage.
                        // We avoid using the URL in the link directly since it could have been manipulated (bug 66608)
                        page = Number( mw.util.getParamValue( 'page', this.href ) );
-                       uri = new mw.Uri( mw.util.wikiScript() )
-                               .extend( { title: mw.config.get( 'wgPageName' ), page: page } )
-                               .toString();
+                       url = mw.util.getUrl( mw.config.get( 'wgPageName' ), { page: page } );
 
-                       switchPage( uri );
+                       switchPage( url );
                        e.preventDefault();
                } );
 
index 578c846..a57d5c7 100644 (file)
                        .text( mw.msg( msgKey ) )
                        .attr( 'title', mw.msg( 'tooltip-ca-' + action ) )
                        .updateTooltipAccessKeys()
-                       .attr( 'href', mw.util.wikiScript() + '?' + $.param( {
-                                       title: title,
-                                       action: action
-                               } )
-                       );
+                       .attr( 'href', mw.util.getUrl( title, { action: action } ) );
 
                // Most common ID style
                if ( $li.prop( 'id' ) === 'ca-' + otherAction ) {
index c7e7506..45aed88 100644 (file)
@@ -1,4 +1,4 @@
-SPECIAL_TARGETS=Utf8Case.ser normalize-ar.ser normalize-ml.ser first-letters-root.ser
+SPECIAL_TARGETS=normalize-ar.ser normalize-ml.ser first-letters-root.ser
 ALL_TARGETS=$(SPECIAL_TARGETS)
 DIST_TARGETS=$(SPECIAL_TARGETS)
 UNICODE_VERSION=6.0.0
@@ -13,9 +13,6 @@ dist: $(DIST_TARGETS)
 clean:
        rm -f $(ALL_TARGETS)
 
-Utf8Case.ser: UnicodeData.txt
-       php ../maintenance/language/generateUtf8Case.php
-
 normalize-ar.ser: UnicodeData.txt
        php ../maintenance/language/generateNormalizerDataAr.php
 
diff --git a/serialized/Utf8Case.ser b/serialized/Utf8Case.ser
deleted file mode 100644 (file)
index 414500b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-a:2:{s:14:"wikiUpperChars";a:1046:{s:1:"a";s:1:"A";s:1:"b";s:1:"B";s:1:"c";s:1:"C";s:1:"d";s:1:"D";s:1:"e";s:1:"E";s:1:"f";s:1:"F";s:1:"g";s:1:"G";s:1:"h";s:1:"H";s:1:"i";s:1:"I";s:1:"j";s:1:"J";s:1:"k";s:1:"K";s:1:"l";s:1:"L";s:1:"m";s:1:"M";s:1:"n";s:1:"N";s:1:"o";s:1:"O";s:1:"p";s:1:"P";s:1:"q";s:1:"Q";s:1:"r";s:1:"R";s:1:"s";s:1:"S";s:1:"t";s:1:"T";s:1:"u";s:1:"U";s:1:"v";s:1:"V";s:1:"w";s:1:"W";s:1:"x";s:1:"X";s:1:"y";s:1:"Y";s:1:"z";s:1:"Z";s:2:"µ";s:2:"Μ";s:2:"à";s:2:"À";s:2:"á";s:2:"Á";s:2:"â";s:2:"Â";s:2:"ã";s:2:"Ã";s:2:"ä";s:2:"Ä";s:2:"å";s:2:"Å";s:2:"æ";s:2:"Æ";s:2:"ç";s:2:"Ç";s:2:"è";s:2:"È";s:2:"é";s:2:"É";s:2:"ê";s:2:"Ê";s:2:"ë";s:2:"Ë";s:2:"ì";s:2:"Ì";s:2:"í";s:2:"Í";s:2:"î";s:2:"Î";s:2:"ï";s:2:"Ï";s:2:"ð";s:2:"Ð";s:2:"ñ";s:2:"Ñ";s:2:"ò";s:2:"Ò";s:2:"ó";s:2:"Ó";s:2:"ô";s:2:"Ô";s:2:"õ";s:2:"Õ";s:2:"ö";s:2:"Ö";s:2:"ø";s:2:"Ø";s:2:"ù";s:2:"Ù";s:2:"ú";s:2:"Ú";s:2:"û";s:2:"Û";s:2:"ü";s:2:"Ü";s:2:"ý";s:2:"Ý";s:2:"þ";s:2:"Þ";s:2:"ÿ";s:2:"Ÿ";s:2:"ā";s:2:"Ā";s:2:"ă";s:2:"Ă";s:2:"ą";s:2:"Ą";s:2:"ć";s:2:"Ć";s:2:"ĉ";s:2:"Ĉ";s:2:"ċ";s:2:"Ċ";s:2:"č";s:2:"Č";s:2:"ď";s:2:"Ď";s:2:"đ";s:2:"Đ";s:2:"ē";s:2:"Ē";s:2:"ĕ";s:2:"Ĕ";s:2:"ė";s:2:"Ė";s:2:"ę";s:2:"Ę";s:2:"ě";s:2:"Ě";s:2:"ĝ";s:2:"Ĝ";s:2:"ğ";s:2:"Ğ";s:2:"ġ";s:2:"Ġ";s:2:"ģ";s:2:"Ģ";s:2:"ĥ";s:2:"Ĥ";s:2:"ħ";s:2:"Ħ";s:2:"ĩ";s:2:"Ĩ";s:2:"ī";s:2:"Ī";s:2:"ĭ";s:2:"Ĭ";s:2:"į";s:2:"Į";s:2:"ı";s:1:"I";s:2:"ij";s:2:"IJ";s:2:"ĵ";s:2:"Ĵ";s:2:"ķ";s:2:"Ķ";s:2:"ĺ";s:2:"Ĺ";s:2:"ļ";s:2:"Ļ";s:2:"ľ";s:2:"Ľ";s:2:"ŀ";s:2:"Ŀ";s:2:"ł";s:2:"Ł";s:2:"ń";s:2:"Ń";s:2:"ņ";s:2:"Ņ";s:2:"ň";s:2:"Ň";s:2:"ŋ";s:2:"Ŋ";s:2:"ō";s:2:"Ō";s:2:"ŏ";s:2:"Ŏ";s:2:"ő";s:2:"Ő";s:2:"œ";s:2:"Œ";s:2:"ŕ";s:2:"Ŕ";s:2:"ŗ";s:2:"Ŗ";s:2:"ř";s:2:"Ř";s:2:"ś";s:2:"Ś";s:2:"ŝ";s:2:"Ŝ";s:2:"ş";s:2:"Ş";s:2:"š";s:2:"Š";s:2:"ţ";s:2:"Ţ";s:2:"ť";s:2:"Ť";s:2:"ŧ";s:2:"Ŧ";s:2:"ũ";s:2:"Ũ";s:2:"ū";s:2:"Ū";s:2:"ŭ";s:2:"Ŭ";s:2:"ů";s:2:"Ů";s:2:"ű";s:2:"Ű";s:2:"ų";s:2:"Ų";s:2:"ŵ";s:2:"Ŵ";s:2:"ŷ";s:2:"Ŷ";s:2:"ź";s:2:"Ź";s:2:"ż";s:2:"Ż";s:2:"ž";s:2:"Ž";s:2:"ſ";s:1:"S";s:2:"ƀ";s:2:"Ƀ";s:2:"ƃ";s:2:"Ƃ";s:2:"ƅ";s:2:"Ƅ";s:2:"ƈ";s:2:"Ƈ";s:2:"ƌ";s:2:"Ƌ";s:2:"ƒ";s:2:"Ƒ";s:2:"ƕ";s:2:"Ƕ";s:2:"ƙ";s:2:"Ƙ";s:2:"ƚ";s:2:"Ƚ";s:2:"ƞ";s:2:"Ƞ";s:2:"ơ";s:2:"Ơ";s:2:"ƣ";s:2:"Ƣ";s:2:"ƥ";s:2:"Ƥ";s:2:"ƨ";s:2:"Ƨ";s:2:"ƭ";s:2:"Ƭ";s:2:"ư";s:2:"Ư";s:2:"ƴ";s:2:"Ƴ";s:2:"ƶ";s:2:"Ƶ";s:2:"ƹ";s:2:"Ƹ";s:2:"ƽ";s:2:"Ƽ";s:2:"ƿ";s:2:"Ƿ";s:2:"Dž";s:2:"DŽ";s:2:"dž";s:2:"DŽ";s:2:"Lj";s:2:"LJ";s:2:"lj";s:2:"LJ";s:2:"Nj";s:2:"NJ";s:2:"nj";s:2:"NJ";s:2:"ǎ";s:2:"Ǎ";s:2:"ǐ";s:2:"Ǐ";s:2:"ǒ";s:2:"Ǒ";s:2:"ǔ";s:2:"Ǔ";s:2:"ǖ";s:2:"Ǖ";s:2:"ǘ";s:2:"Ǘ";s:2:"ǚ";s:2:"Ǚ";s:2:"ǜ";s:2:"Ǜ";s:2:"ǝ";s:2:"Ǝ";s:2:"ǟ";s:2:"Ǟ";s:2:"ǡ";s:2:"Ǡ";s:2:"ǣ";s:2:"Ǣ";s:2:"ǥ";s:2:"Ǥ";s:2:"ǧ";s:2:"Ǧ";s:2:"ǩ";s:2:"Ǩ";s:2:"ǫ";s:2:"Ǫ";s:2:"ǭ";s:2:"Ǭ";s:2:"ǯ";s:2:"Ǯ";s:2:"Dz";s:2:"DZ";s:2:"dz";s:2:"DZ";s:2:"ǵ";s:2:"Ǵ";s:2:"ǹ";s:2:"Ǹ";s:2:"ǻ";s:2:"Ǻ";s:2:"ǽ";s:2:"Ǽ";s:2:"ǿ";s:2:"Ǿ";s:2:"ȁ";s:2:"Ȁ";s:2:"ȃ";s:2:"Ȃ";s:2:"ȅ";s:2:"Ȅ";s:2:"ȇ";s:2:"Ȇ";s:2:"ȉ";s:2:"Ȉ";s:2:"ȋ";s:2:"Ȋ";s:2:"ȍ";s:2:"Ȍ";s:2:"ȏ";s:2:"Ȏ";s:2:"ȑ";s:2:"Ȑ";s:2:"ȓ";s:2:"Ȓ";s:2:"ȕ";s:2:"Ȕ";s:2:"ȗ";s:2:"Ȗ";s:2:"ș";s:2:"Ș";s:2:"ț";s:2:"Ț";s:2:"ȝ";s:2:"Ȝ";s:2:"ȟ";s:2:"Ȟ";s:2:"ȣ";s:2:"Ȣ";s:2:"ȥ";s:2:"Ȥ";s:2:"ȧ";s:2:"Ȧ";s:2:"ȩ";s:2:"Ȩ";s:2:"ȫ";s:2:"Ȫ";s:2:"ȭ";s:2:"Ȭ";s:2:"ȯ";s:2:"Ȯ";s:2:"ȱ";s:2:"Ȱ";s:2:"ȳ";s:2:"Ȳ";s:2:"ȼ";s:2:"Ȼ";s:2:"ȿ";s:3:"Ȿ";s:2:"ɀ";s:3:"Ɀ";s:2:"ɂ";s:2:"Ɂ";s:2:"ɇ";s:2:"Ɇ";s:2:"ɉ";s:2:"Ɉ";s:2:"ɋ";s:2:"Ɋ";s:2:"ɍ";s:2:"Ɍ";s:2:"ɏ";s:2:"Ɏ";s:2:"ɐ";s:3:"Ɐ";s:2:"ɑ";s:3:"Ɑ";s:2:"ɒ";s:3:"Ɒ";s:2:"ɓ";s:2:"Ɓ";s:2:"ɔ";s:2:"Ɔ";s:2:"ɖ";s:2:"Ɖ";s:2:"ɗ";s:2:"Ɗ";s:2:"ə";s:2:"Ə";s:2:"ɛ";s:2:"Ɛ";s:2:"ɠ";s:2:"Ɠ";s:2:"ɣ";s:2:"Ɣ";s:2:"ɥ";s:3:"Ɥ";s:2:"ɨ";s:2:"Ɨ";s:2:"ɩ";s:2:"Ɩ";s:2:"ɫ";s:3:"Ɫ";s:2:"ɯ";s:2:"Ɯ";s:2:"ɱ";s:3:"Ɱ";s:2:"ɲ";s:2:"Ɲ";s:2:"ɵ";s:2:"Ɵ";s:2:"ɽ";s:3:"Ɽ";s:2:"ʀ";s:2:"Ʀ";s:2:"ʃ";s:2:"Ʃ";s:2:"ʈ";s:2:"Ʈ";s:2:"ʉ";s:2:"Ʉ";s:2:"ʊ";s:2:"Ʊ";s:2:"ʋ";s:2:"Ʋ";s:2:"ʌ";s:2:"Ʌ";s:2:"ʒ";s:2:"Ʒ";s:2:"ͅ";s:2:"Ι";s:2:"ͱ";s:2:"Ͱ";s:2:"ͳ";s:2:"Ͳ";s:2:"ͷ";s:2:"Ͷ";s:2:"ͻ";s:2:"Ͻ";s:2:"ͼ";s:2:"Ͼ";s:2:"ͽ";s:2:"Ͽ";s:2:"ά";s:2:"Ά";s:2:"έ";s:2:"Έ";s:2:"ή";s:2:"Ή";s:2:"ί";s:2:"Ί";s:2:"α";s:2:"Α";s:2:"β";s:2:"Β";s:2:"γ";s:2:"Γ";s:2:"δ";s:2:"Δ";s:2:"ε";s:2:"Ε";s:2:"ζ";s:2:"Ζ";s:2:"η";s:2:"Η";s:2:"θ";s:2:"Θ";s:2:"ι";s:2:"Ι";s:2:"κ";s:2:"Κ";s:2:"λ";s:2:"Λ";s:2:"μ";s:2:"Μ";s:2:"ν";s:2:"Ν";s:2:"ξ";s:2:"Ξ";s:2:"ο";s:2:"Ο";s:2:"π";s:2:"Π";s:2:"ρ";s:2:"Ρ";s:2:"ς";s:2:"Σ";s:2:"σ";s:2:"Σ";s:2:"τ";s:2:"Τ";s:2:"υ";s:2:"Υ";s:2:"φ";s:2:"Φ";s:2:"χ";s:2:"Χ";s:2:"ψ";s:2:"Ψ";s:2:"ω";s:2:"Ω";s:2:"ϊ";s:2:"Ϊ";s:2:"ϋ";s:2:"Ϋ";s:2:"ό";s:2:"Ό";s:2:"ύ";s:2:"Ύ";s:2:"ώ";s:2:"Ώ";s:2:"ϐ";s:2:"Β";s:2:"ϑ";s:2:"Θ";s:2:"ϕ";s:2:"Φ";s:2:"ϖ";s:2:"Π";s:2:"ϗ";s:2:"Ϗ";s:2:"ϙ";s:2:"Ϙ";s:2:"ϛ";s:2:"Ϛ";s:2:"ϝ";s:2:"Ϝ";s:2:"ϟ";s:2:"Ϟ";s:2:"ϡ";s:2:"Ϡ";s:2:"ϣ";s:2:"Ϣ";s:2:"ϥ";s:2:"Ϥ";s:2:"ϧ";s:2:"Ϧ";s:2:"ϩ";s:2:"Ϩ";s:2:"ϫ";s:2:"Ϫ";s:2:"ϭ";s:2:"Ϭ";s:2:"ϯ";s:2:"Ϯ";s:2:"ϰ";s:2:"Κ";s:2:"ϱ";s:2:"Ρ";s:2:"ϲ";s:2:"Ϲ";s:2:"ϵ";s:2:"Ε";s:2:"ϸ";s:2:"Ϸ";s:2:"ϻ";s:2:"Ϻ";s:2:"а";s:2:"А";s:2:"б";s:2:"Б";s:2:"в";s:2:"В";s:2:"г";s:2:"Г";s:2:"д";s:2:"Д";s:2:"е";s:2:"Е";s:2:"ж";s:2:"Ж";s:2:"з";s:2:"З";s:2:"и";s:2:"И";s:2:"й";s:2:"Й";s:2:"к";s:2:"К";s:2:"л";s:2:"Л";s:2:"м";s:2:"М";s:2:"н";s:2:"Н";s:2:"о";s:2:"О";s:2:"п";s:2:"П";s:2:"р";s:2:"Р";s:2:"с";s:2:"С";s:2:"т";s:2:"Т";s:2:"у";s:2:"У";s:2:"ф";s:2:"Ф";s:2:"х";s:2:"Х";s:2:"ц";s:2:"Ц";s:2:"ч";s:2:"Ч";s:2:"ш";s:2:"Ш";s:2:"щ";s:2:"Щ";s:2:"ъ";s:2:"Ъ";s:2:"ы";s:2:"Ы";s:2:"ь";s:2:"Ь";s:2:"э";s:2:"Э";s:2:"ю";s:2:"Ю";s:2:"я";s:2:"Я";s:2:"ѐ";s:2:"Ѐ";s:2:"ё";s:2:"Ё";s:2:"ђ";s:2:"Ђ";s:2:"ѓ";s:2:"Ѓ";s:2:"є";s:2:"Є";s:2:"ѕ";s:2:"Ѕ";s:2:"і";s:2:"І";s:2:"ї";s:2:"Ї";s:2:"ј";s:2:"Ј";s:2:"љ";s:2:"Љ";s:2:"њ";s:2:"Њ";s:2:"ћ";s:2:"Ћ";s:2:"ќ";s:2:"Ќ";s:2:"ѝ";s:2:"Ѝ";s:2:"ў";s:2:"Ў";s:2:"џ";s:2:"Џ";s:2:"ѡ";s:2:"Ѡ";s:2:"ѣ";s:2:"Ѣ";s:2:"ѥ";s:2:"Ѥ";s:2:"ѧ";s:2:"Ѧ";s:2:"ѩ";s:2:"Ѩ";s:2:"ѫ";s:2:"Ѫ";s:2:"ѭ";s:2:"Ѭ";s:2:"ѯ";s:2:"Ѯ";s:2:"ѱ";s:2:"Ѱ";s:2:"ѳ";s:2:"Ѳ";s:2:"ѵ";s:2:"Ѵ";s:2:"ѷ";s:2:"Ѷ";s:2:"ѹ";s:2:"Ѹ";s:2:"ѻ";s:2:"Ѻ";s:2:"ѽ";s:2:"Ѽ";s:2:"ѿ";s:2:"Ѿ";s:2:"ҁ";s:2:"Ҁ";s:2:"ҋ";s:2:"Ҋ";s:2:"ҍ";s:2:"Ҍ";s:2:"ҏ";s:2:"Ҏ";s:2:"ґ";s:2:"Ґ";s:2:"ғ";s:2:"Ғ";s:2:"ҕ";s:2:"Ҕ";s:2:"җ";s:2:"Җ";s:2:"ҙ";s:2:"Ҙ";s:2:"қ";s:2:"Қ";s:2:"ҝ";s:2:"Ҝ";s:2:"ҟ";s:2:"Ҟ";s:2:"ҡ";s:2:"Ҡ";s:2:"ң";s:2:"Ң";s:2:"ҥ";s:2:"Ҥ";s:2:"ҧ";s:2:"Ҧ";s:2:"ҩ";s:2:"Ҩ";s:2:"ҫ";s:2:"Ҫ";s:2:"ҭ";s:2:"Ҭ";s:2:"ү";s:2:"Ү";s:2:"ұ";s:2:"Ұ";s:2:"ҳ";s:2:"Ҳ";s:2:"ҵ";s:2:"Ҵ";s:2:"ҷ";s:2:"Ҷ";s:2:"ҹ";s:2:"Ҹ";s:2:"һ";s:2:"Һ";s:2:"ҽ";s:2:"Ҽ";s:2:"ҿ";s:2:"Ҿ";s:2:"ӂ";s:2:"Ӂ";s:2:"ӄ";s:2:"Ӄ";s:2:"ӆ";s:2:"Ӆ";s:2:"ӈ";s:2:"Ӈ";s:2:"ӊ";s:2:"Ӊ";s:2:"ӌ";s:2:"Ӌ";s:2:"ӎ";s:2:"Ӎ";s:2:"ӏ";s:2:"Ӏ";s:2:"ӑ";s:2:"Ӑ";s:2:"ӓ";s:2:"Ӓ";s:2:"ӕ";s:2:"Ӕ";s:2:"ӗ";s:2:"Ӗ";s:2:"ә";s:2:"Ә";s:2:"ӛ";s:2:"Ӛ";s:2:"ӝ";s:2:"Ӝ";s:2:"ӟ";s:2:"Ӟ";s:2:"ӡ";s:2:"Ӡ";s:2:"ӣ";s:2:"Ӣ";s:2:"ӥ";s:2:"Ӥ";s:2:"ӧ";s:2:"Ӧ";s:2:"ө";s:2:"Ө";s:2:"ӫ";s:2:"Ӫ";s:2:"ӭ";s:2:"Ӭ";s:2:"ӯ";s:2:"Ӯ";s:2:"ӱ";s:2:"Ӱ";s:2:"ӳ";s:2:"Ӳ";s:2:"ӵ";s:2:"Ӵ";s:2:"ӷ";s:2:"Ӷ";s:2:"ӹ";s:2:"Ӹ";s:2:"ӻ";s:2:"Ӻ";s:2:"ӽ";s:2:"Ӽ";s:2:"ӿ";s:2:"Ӿ";s:2:"ԁ";s:2:"Ԁ";s:2:"ԃ";s:2:"Ԃ";s:2:"ԅ";s:2:"Ԅ";s:2:"ԇ";s:2:"Ԇ";s:2:"ԉ";s:2:"Ԉ";s:2:"ԋ";s:2:"Ԋ";s:2:"ԍ";s:2:"Ԍ";s:2:"ԏ";s:2:"Ԏ";s:2:"ԑ";s:2:"Ԑ";s:2:"ԓ";s:2:"Ԓ";s:2:"ԕ";s:2:"Ԕ";s:2:"ԗ";s:2:"Ԗ";s:2:"ԙ";s:2:"Ԙ";s:2:"ԛ";s:2:"Ԛ";s:2:"ԝ";s:2:"Ԝ";s:2:"ԟ";s:2:"Ԟ";s:2:"ԡ";s:2:"Ԡ";s:2:"ԣ";s:2:"Ԣ";s:2:"ԥ";s:2:"Ԥ";s:2:"ԧ";s:2:"Ԧ";s:2:"ա";s:2:"Ա";s:2:"բ";s:2:"Բ";s:2:"գ";s:2:"Գ";s:2:"դ";s:2:"Դ";s:2:"ե";s:2:"Ե";s:2:"զ";s:2:"Զ";s:2:"է";s:2:"Է";s:2:"ը";s:2:"Ը";s:2:"թ";s:2:"Թ";s:2:"ժ";s:2:"Ժ";s:2:"ի";s:2:"Ի";s:2:"լ";s:2:"Լ";s:2:"խ";s:2:"Խ";s:2:"ծ";s:2:"Ծ";s:2:"կ";s:2:"Կ";s:2:"հ";s:2:"Հ";s:2:"ձ";s:2:"Ձ";s:2:"ղ";s:2:"Ղ";s:2:"ճ";s:2:"Ճ";s:2:"մ";s:2:"Մ";s:2:"յ";s:2:"Յ";s:2:"ն";s:2:"Ն";s:2:"շ";s:2:"Շ";s:2:"ո";s:2:"Ո";s:2:"չ";s:2:"Չ";s:2:"պ";s:2:"Պ";s:2:"ջ";s:2:"Ջ";s:2:"ռ";s:2:"Ռ";s:2:"ս";s:2:"Ս";s:2:"վ";s:2:"Վ";s:2:"տ";s:2:"Տ";s:2:"ր";s:2:"Ր";s:2:"ց";s:2:"Ց";s:2:"ւ";s:2:"Ւ";s:2:"փ";s:2:"Փ";s:2:"ք";s:2:"Ք";s:2:"օ";s:2:"Օ";s:2:"ֆ";s:2:"Ֆ";s:3:"ᵹ";s:3:"Ᵹ";s:3:"ᵽ";s:3:"Ᵽ";s:3:"ḁ";s:3:"Ḁ";s:3:"ḃ";s:3:"Ḃ";s:3:"ḅ";s:3:"Ḅ";s:3:"ḇ";s:3:"Ḇ";s:3:"ḉ";s:3:"Ḉ";s:3:"ḋ";s:3:"Ḋ";s:3:"ḍ";s:3:"Ḍ";s:3:"ḏ";s:3:"Ḏ";s:3:"ḑ";s:3:"Ḑ";s:3:"ḓ";s:3:"Ḓ";s:3:"ḕ";s:3:"Ḕ";s:3:"ḗ";s:3:"Ḗ";s:3:"ḙ";s:3:"Ḙ";s:3:"ḛ";s:3:"Ḛ";s:3:"ḝ";s:3:"Ḝ";s:3:"ḟ";s:3:"Ḟ";s:3:"ḡ";s:3:"Ḡ";s:3:"ḣ";s:3:"Ḣ";s:3:"ḥ";s:3:"Ḥ";s:3:"ḧ";s:3:"Ḧ";s:3:"ḩ";s:3:"Ḩ";s:3:"ḫ";s:3:"Ḫ";s:3:"ḭ";s:3:"Ḭ";s:3:"ḯ";s:3:"Ḯ";s:3:"ḱ";s:3:"Ḱ";s:3:"ḳ";s:3:"Ḳ";s:3:"ḵ";s:3:"Ḵ";s:3:"ḷ";s:3:"Ḷ";s:3:"ḹ";s:3:"Ḹ";s:3:"ḻ";s:3:"Ḻ";s:3:"ḽ";s:3:"Ḽ";s:3:"ḿ";s:3:"Ḿ";s:3:"ṁ";s:3:"Ṁ";s:3:"ṃ";s:3:"Ṃ";s:3:"ṅ";s:3:"Ṅ";s:3:"ṇ";s:3:"Ṇ";s:3:"ṉ";s:3:"Ṉ";s:3:"ṋ";s:3:"Ṋ";s:3:"ṍ";s:3:"Ṍ";s:3:"ṏ";s:3:"Ṏ";s:3:"ṑ";s:3:"Ṑ";s:3:"ṓ";s:3:"Ṓ";s:3:"ṕ";s:3:"Ṕ";s:3:"ṗ";s:3:"Ṗ";s:3:"ṙ";s:3:"Ṙ";s:3:"ṛ";s:3:"Ṛ";s:3:"ṝ";s:3:"Ṝ";s:3:"ṟ";s:3:"Ṟ";s:3:"ṡ";s:3:"Ṡ";s:3:"ṣ";s:3:"Ṣ";s:3:"ṥ";s:3:"Ṥ";s:3:"ṧ";s:3:"Ṧ";s:3:"ṩ";s:3:"Ṩ";s:3:"ṫ";s:3:"Ṫ";s:3:"ṭ";s:3:"Ṭ";s:3:"ṯ";s:3:"Ṯ";s:3:"ṱ";s:3:"Ṱ";s:3:"ṳ";s:3:"Ṳ";s:3:"ṵ";s:3:"Ṵ";s:3:"ṷ";s:3:"Ṷ";s:3:"ṹ";s:3:"Ṹ";s:3:"ṻ";s:3:"Ṻ";s:3:"ṽ";s:3:"Ṽ";s:3:"ṿ";s:3:"Ṿ";s:3:"ẁ";s:3:"Ẁ";s:3:"ẃ";s:3:"Ẃ";s:3:"ẅ";s:3:"Ẅ";s:3:"ẇ";s:3:"Ẇ";s:3:"ẉ";s:3:"Ẉ";s:3:"ẋ";s:3:"Ẋ";s:3:"ẍ";s:3:"Ẍ";s:3:"ẏ";s:3:"Ẏ";s:3:"ẑ";s:3:"Ẑ";s:3:"ẓ";s:3:"Ẓ";s:3:"ẕ";s:3:"Ẕ";s:3:"ẛ";s:3:"Ṡ";s:3:"ạ";s:3:"Ạ";s:3:"ả";s:3:"Ả";s:3:"ấ";s:3:"Ấ";s:3:"ầ";s:3:"Ầ";s:3:"ẩ";s:3:"Ẩ";s:3:"ẫ";s:3:"Ẫ";s:3:"ậ";s:3:"Ậ";s:3:"ắ";s:3:"Ắ";s:3:"ằ";s:3:"Ằ";s:3:"ẳ";s:3:"Ẳ";s:3:"ẵ";s:3:"Ẵ";s:3:"ặ";s:3:"Ặ";s:3:"ẹ";s:3:"Ẹ";s:3:"ẻ";s:3:"Ẻ";s:3:"ẽ";s:3:"Ẽ";s:3:"ế";s:3:"Ế";s:3:"ề";s:3:"Ề";s:3:"ể";s:3:"Ể";s:3:"ễ";s:3:"Ễ";s:3:"ệ";s:3:"Ệ";s:3:"ỉ";s:3:"Ỉ";s:3:"ị";s:3:"Ị";s:3:"ọ";s:3:"Ọ";s:3:"ỏ";s:3:"Ỏ";s:3:"ố";s:3:"Ố";s:3:"ồ";s:3:"Ồ";s:3:"ổ";s:3:"Ổ";s:3:"ỗ";s:3:"Ỗ";s:3:"ộ";s:3:"Ộ";s:3:"ớ";s:3:"Ớ";s:3:"ờ";s:3:"Ờ";s:3:"ở";s:3:"Ở";s:3:"ỡ";s:3:"Ỡ";s:3:"ợ";s:3:"Ợ";s:3:"ụ";s:3:"Ụ";s:3:"ủ";s:3:"Ủ";s:3:"ứ";s:3:"Ứ";s:3:"ừ";s:3:"Ừ";s:3:"ử";s:3:"Ử";s:3:"ữ";s:3:"Ữ";s:3:"ự";s:3:"Ự";s:3:"ỳ";s:3:"Ỳ";s:3:"ỵ";s:3:"Ỵ";s:3:"ỷ";s:3:"Ỷ";s:3:"ỹ";s:3:"Ỹ";s:3:"ỻ";s:3:"Ỻ";s:3:"ỽ";s:3:"Ỽ";s:3:"ỿ";s:3:"Ỿ";s:3:"ἀ";s:3:"Ἀ";s:3:"ἁ";s:3:"Ἁ";s:3:"ἂ";s:3:"Ἂ";s:3:"ἃ";s:3:"Ἃ";s:3:"ἄ";s:3:"Ἄ";s:3:"ἅ";s:3:"Ἅ";s:3:"ἆ";s:3:"Ἆ";s:3:"ἇ";s:3:"Ἇ";s:3:"ἐ";s:3:"Ἐ";s:3:"ἑ";s:3:"Ἑ";s:3:"ἒ";s:3:"Ἒ";s:3:"ἓ";s:3:"Ἓ";s:3:"ἔ";s:3:"Ἔ";s:3:"ἕ";s:3:"Ἕ";s:3:"ἠ";s:3:"Ἠ";s:3:"ἡ";s:3:"Ἡ";s:3:"ἢ";s:3:"Ἢ";s:3:"ἣ";s:3:"Ἣ";s:3:"ἤ";s:3:"Ἤ";s:3:"ἥ";s:3:"Ἥ";s:3:"ἦ";s:3:"Ἦ";s:3:"ἧ";s:3:"Ἧ";s:3:"ἰ";s:3:"Ἰ";s:3:"ἱ";s:3:"Ἱ";s:3:"ἲ";s:3:"Ἲ";s:3:"ἳ";s:3:"Ἳ";s:3:"ἴ";s:3:"Ἴ";s:3:"ἵ";s:3:"Ἵ";s:3:"ἶ";s:3:"Ἶ";s:3:"ἷ";s:3:"Ἷ";s:3:"ὀ";s:3:"Ὀ";s:3:"ὁ";s:3:"Ὁ";s:3:"ὂ";s:3:"Ὂ";s:3:"ὃ";s:3:"Ὃ";s:3:"ὄ";s:3:"Ὄ";s:3:"ὅ";s:3:"Ὅ";s:3:"ὑ";s:3:"Ὑ";s:3:"ὓ";s:3:"Ὓ";s:3:"ὕ";s:3:"Ὕ";s:3:"ὗ";s:3:"Ὗ";s:3:"ὠ";s:3:"Ὠ";s:3:"ὡ";s:3:"Ὡ";s:3:"ὢ";s:3:"Ὢ";s:3:"ὣ";s:3:"Ὣ";s:3:"ὤ";s:3:"Ὤ";s:3:"ὥ";s:3:"Ὥ";s:3:"ὦ";s:3:"Ὦ";s:3:"ὧ";s:3:"Ὧ";s:3:"ὰ";s:3:"Ὰ";s:3:"ά";s:3:"Ά";s:3:"ὲ";s:3:"Ὲ";s:3:"έ";s:3:"Έ";s:3:"ὴ";s:3:"Ὴ";s:3:"ή";s:3:"Ή";s:3:"ὶ";s:3:"Ὶ";s:3:"ί";s:3:"Ί";s:3:"ὸ";s:3:"Ὸ";s:3:"ό";s:3:"Ό";s:3:"ὺ";s:3:"Ὺ";s:3:"ύ";s:3:"Ύ";s:3:"ὼ";s:3:"Ὼ";s:3:"ώ";s:3:"Ώ";s:3:"ᾀ";s:3:"ᾈ";s:3:"ᾁ";s:3:"ᾉ";s:3:"ᾂ";s:3:"ᾊ";s:3:"ᾃ";s:3:"ᾋ";s:3:"ᾄ";s:3:"ᾌ";s:3:"ᾅ";s:3:"ᾍ";s:3:"ᾆ";s:3:"ᾎ";s:3:"ᾇ";s:3:"ᾏ";s:3:"ᾐ";s:3:"ᾘ";s:3:"ᾑ";s:3:"ᾙ";s:3:"ᾒ";s:3:"ᾚ";s:3:"ᾓ";s:3:"ᾛ";s:3:"ᾔ";s:3:"ᾜ";s:3:"ᾕ";s:3:"ᾝ";s:3:"ᾖ";s:3:"ᾞ";s:3:"ᾗ";s:3:"ᾟ";s:3:"ᾠ";s:3:"ᾨ";s:3:"ᾡ";s:3:"ᾩ";s:3:"ᾢ";s:3:"ᾪ";s:3:"ᾣ";s:3:"ᾫ";s:3:"ᾤ";s:3:"ᾬ";s:3:"ᾥ";s:3:"ᾭ";s:3:"ᾦ";s:3:"ᾮ";s:3:"ᾧ";s:3:"ᾯ";s:3:"ᾰ";s:3:"Ᾰ";s:3:"ᾱ";s:3:"Ᾱ";s:3:"ᾳ";s:3:"ᾼ";s:3:"ι";s:2:"Ι";s:3:"ῃ";s:3:"ῌ";s:3:"ῐ";s:3:"Ῐ";s:3:"ῑ";s:3:"Ῑ";s:3:"ῠ";s:3:"Ῠ";s:3:"ῡ";s:3:"Ῡ";s:3:"ῥ";s:3:"Ῥ";s:3:"ῳ";s:3:"ῼ";s:3:"ⅎ";s:3:"Ⅎ";s:3:"ⅰ";s:3:"Ⅰ";s:3:"ⅱ";s:3:"Ⅱ";s:3:"ⅲ";s:3:"Ⅲ";s:3:"ⅳ";s:3:"Ⅳ";s:3:"ⅴ";s:3:"Ⅴ";s:3:"ⅵ";s:3:"Ⅵ";s:3:"ⅶ";s:3:"Ⅶ";s:3:"ⅷ";s:3:"Ⅷ";s:3:"ⅸ";s:3:"Ⅸ";s:3:"ⅹ";s:3:"Ⅹ";s:3:"ⅺ";s:3:"Ⅺ";s:3:"ⅻ";s:3:"Ⅻ";s:3:"ⅼ";s:3:"Ⅼ";s:3:"ⅽ";s:3:"Ⅽ";s:3:"ⅾ";s:3:"Ⅾ";s:3:"ⅿ";s:3:"Ⅿ";s:3:"ↄ";s:3:"Ↄ";s:3:"ⓐ";s:3:"Ⓐ";s:3:"ⓑ";s:3:"Ⓑ";s:3:"ⓒ";s:3:"Ⓒ";s:3:"ⓓ";s:3:"Ⓓ";s:3:"ⓔ";s:3:"Ⓔ";s:3:"ⓕ";s:3:"Ⓕ";s:3:"ⓖ";s:3:"Ⓖ";s:3:"ⓗ";s:3:"Ⓗ";s:3:"ⓘ";s:3:"Ⓘ";s:3:"ⓙ";s:3:"Ⓙ";s:3:"ⓚ";s:3:"Ⓚ";s:3:"ⓛ";s:3:"Ⓛ";s:3:"ⓜ";s:3:"Ⓜ";s:3:"ⓝ";s:3:"Ⓝ";s:3:"ⓞ";s:3:"Ⓞ";s:3:"ⓟ";s:3:"Ⓟ";s:3:"ⓠ";s:3:"Ⓠ";s:3:"ⓡ";s:3:"Ⓡ";s:3:"ⓢ";s:3:"Ⓢ";s:3:"ⓣ";s:3:"Ⓣ";s:3:"ⓤ";s:3:"Ⓤ";s:3:"ⓥ";s:3:"Ⓥ";s:3:"ⓦ";s:3:"Ⓦ";s:3:"ⓧ";s:3:"Ⓧ";s:3:"ⓨ";s:3:"Ⓨ";s:3:"ⓩ";s:3:"Ⓩ";s:3:"ⰰ";s:3:"Ⰰ";s:3:"ⰱ";s:3:"Ⰱ";s:3:"ⰲ";s:3:"Ⰲ";s:3:"ⰳ";s:3:"Ⰳ";s:3:"ⰴ";s:3:"Ⰴ";s:3:"ⰵ";s:3:"Ⰵ";s:3:"ⰶ";s:3:"Ⰶ";s:3:"ⰷ";s:3:"Ⰷ";s:3:"ⰸ";s:3:"Ⰸ";s:3:"ⰹ";s:3:"Ⰹ";s:3:"ⰺ";s:3:"Ⰺ";s:3:"ⰻ";s:3:"Ⰻ";s:3:"ⰼ";s:3:"Ⰼ";s:3:"ⰽ";s:3:"Ⰽ";s:3:"ⰾ";s:3:"Ⰾ";s:3:"ⰿ";s:3:"Ⰿ";s:3:"ⱀ";s:3:"Ⱀ";s:3:"ⱁ";s:3:"Ⱁ";s:3:"ⱂ";s:3:"Ⱂ";s:3:"ⱃ";s:3:"Ⱃ";s:3:"ⱄ";s:3:"Ⱄ";s:3:"ⱅ";s:3:"Ⱅ";s:3:"ⱆ";s:3:"Ⱆ";s:3:"ⱇ";s:3:"Ⱇ";s:3:"ⱈ";s:3:"Ⱈ";s:3:"ⱉ";s:3:"Ⱉ";s:3:"ⱊ";s:3:"Ⱊ";s:3:"ⱋ";s:3:"Ⱋ";s:3:"ⱌ";s:3:"Ⱌ";s:3:"ⱍ";s:3:"Ⱍ";s:3:"ⱎ";s:3:"Ⱎ";s:3:"ⱏ";s:3:"Ⱏ";s:3:"ⱐ";s:3:"Ⱐ";s:3:"ⱑ";s:3:"Ⱑ";s:3:"ⱒ";s:3:"Ⱒ";s:3:"ⱓ";s:3:"Ⱓ";s:3:"ⱔ";s:3:"Ⱔ";s:3:"ⱕ";s:3:"Ⱕ";s:3:"ⱖ";s:3:"Ⱖ";s:3:"ⱗ";s:3:"Ⱗ";s:3:"ⱘ";s:3:"Ⱘ";s:3:"ⱙ";s:3:"Ⱙ";s:3:"ⱚ";s:3:"Ⱚ";s:3:"ⱛ";s:3:"Ⱛ";s:3:"ⱜ";s:3:"Ⱜ";s:3:"ⱝ";s:3:"Ⱝ";s:3:"ⱞ";s:3:"Ⱞ";s:3:"ⱡ";s:3:"Ⱡ";s:3:"ⱥ";s:2:"Ⱥ";s:3:"ⱦ";s:2:"Ⱦ";s:3:"ⱨ";s:3:"Ⱨ";s:3:"ⱪ";s:3:"Ⱪ";s:3:"ⱬ";s:3:"Ⱬ";s:3:"ⱳ";s:3:"Ⱳ";s:3:"ⱶ";s:3:"Ⱶ";s:3:"ⲁ";s:3:"Ⲁ";s:3:"ⲃ";s:3:"Ⲃ";s:3:"ⲅ";s:3:"Ⲅ";s:3:"ⲇ";s:3:"Ⲇ";s:3:"ⲉ";s:3:"Ⲉ";s:3:"ⲋ";s:3:"Ⲋ";s:3:"ⲍ";s:3:"Ⲍ";s:3:"ⲏ";s:3:"Ⲏ";s:3:"ⲑ";s:3:"Ⲑ";s:3:"ⲓ";s:3:"Ⲓ";s:3:"ⲕ";s:3:"Ⲕ";s:3:"ⲗ";s:3:"Ⲗ";s:3:"ⲙ";s:3:"Ⲙ";s:3:"ⲛ";s:3:"Ⲛ";s:3:"ⲝ";s:3:"Ⲝ";s:3:"ⲟ";s:3:"Ⲟ";s:3:"ⲡ";s:3:"Ⲡ";s:3:"ⲣ";s:3:"Ⲣ";s:3:"ⲥ";s:3:"Ⲥ";s:3:"ⲧ";s:3:"Ⲧ";s:3:"ⲩ";s:3:"Ⲩ";s:3:"ⲫ";s:3:"Ⲫ";s:3:"ⲭ";s:3:"Ⲭ";s:3:"ⲯ";s:3:"Ⲯ";s:3:"ⲱ";s:3:"Ⲱ";s:3:"ⲳ";s:3:"Ⲳ";s:3:"ⲵ";s:3:"Ⲵ";s:3:"ⲷ";s:3:"Ⲷ";s:3:"ⲹ";s:3:"Ⲹ";s:3:"ⲻ";s:3:"Ⲻ";s:3:"ⲽ";s:3:"Ⲽ";s:3:"ⲿ";s:3:"Ⲿ";s:3:"ⳁ";s:3:"Ⳁ";s:3:"ⳃ";s:3:"Ⳃ";s:3:"ⳅ";s:3:"Ⳅ";s:3:"ⳇ";s:3:"Ⳇ";s:3:"ⳉ";s:3:"Ⳉ";s:3:"ⳋ";s:3:"Ⳋ";s:3:"ⳍ";s:3:"Ⳍ";s:3:"ⳏ";s:3:"Ⳏ";s:3:"ⳑ";s:3:"Ⳑ";s:3:"ⳓ";s:3:"Ⳓ";s:3:"ⳕ";s:3:"Ⳕ";s:3:"ⳗ";s:3:"Ⳗ";s:3:"ⳙ";s:3:"Ⳙ";s:3:"ⳛ";s:3:"Ⳛ";s:3:"ⳝ";s:3:"Ⳝ";s:3:"ⳟ";s:3:"Ⳟ";s:3:"ⳡ";s:3:"Ⳡ";s:3:"ⳣ";s:3:"Ⳣ";s:3:"ⳬ";s:3:"Ⳬ";s:3:"ⳮ";s:3:"Ⳮ";s:3:"ⴀ";s:3:"Ⴀ";s:3:"ⴁ";s:3:"Ⴁ";s:3:"ⴂ";s:3:"Ⴂ";s:3:"ⴃ";s:3:"Ⴃ";s:3:"ⴄ";s:3:"Ⴄ";s:3:"ⴅ";s:3:"Ⴅ";s:3:"ⴆ";s:3:"Ⴆ";s:3:"ⴇ";s:3:"Ⴇ";s:3:"ⴈ";s:3:"Ⴈ";s:3:"ⴉ";s:3:"Ⴉ";s:3:"ⴊ";s:3:"Ⴊ";s:3:"ⴋ";s:3:"Ⴋ";s:3:"ⴌ";s:3:"Ⴌ";s:3:"ⴍ";s:3:"Ⴍ";s:3:"ⴎ";s:3:"Ⴎ";s:3:"ⴏ";s:3:"Ⴏ";s:3:"ⴐ";s:3:"Ⴐ";s:3:"ⴑ";s:3:"Ⴑ";s:3:"ⴒ";s:3:"Ⴒ";s:3:"ⴓ";s:3:"Ⴓ";s:3:"ⴔ";s:3:"Ⴔ";s:3:"ⴕ";s:3:"Ⴕ";s:3:"ⴖ";s:3:"Ⴖ";s:3:"ⴗ";s:3:"Ⴗ";s:3:"ⴘ";s:3:"Ⴘ";s:3:"ⴙ";s:3:"Ⴙ";s:3:"ⴚ";s:3:"Ⴚ";s:3:"ⴛ";s:3:"Ⴛ";s:3:"ⴜ";s:3:"Ⴜ";s:3:"ⴝ";s:3:"Ⴝ";s:3:"ⴞ";s:3:"Ⴞ";s:3:"ⴟ";s:3:"Ⴟ";s:3:"ⴠ";s:3:"Ⴠ";s:3:"ⴡ";s:3:"Ⴡ";s:3:"ⴢ";s:3:"Ⴢ";s:3:"ⴣ";s:3:"Ⴣ";s:3:"ⴤ";s:3:"Ⴤ";s:3:"ⴥ";s:3:"Ⴥ";s:3:"ꙁ";s:3:"Ꙁ";s:3:"ꙃ";s:3:"Ꙃ";s:3:"ꙅ";s:3:"Ꙅ";s:3:"ꙇ";s:3:"Ꙇ";s:3:"ꙉ";s:3:"Ꙉ";s:3:"ꙋ";s:3:"Ꙋ";s:3:"ꙍ";s:3:"Ꙍ";s:3:"ꙏ";s:3:"Ꙏ";s:3:"ꙑ";s:3:"Ꙑ";s:3:"ꙓ";s:3:"Ꙓ";s:3:"ꙕ";s:3:"Ꙕ";s:3:"ꙗ";s:3:"Ꙗ";s:3:"ꙙ";s:3:"Ꙙ";s:3:"ꙛ";s:3:"Ꙛ";s:3:"ꙝ";s:3:"Ꙝ";s:3:"ꙟ";s:3:"Ꙟ";s:3:"ꙡ";s:3:"Ꙡ";s:3:"ꙣ";s:3:"Ꙣ";s:3:"ꙥ";s:3:"Ꙥ";s:3:"ꙧ";s:3:"Ꙧ";s:3:"ꙩ";s:3:"Ꙩ";s:3:"ꙫ";s:3:"Ꙫ";s:3:"ꙭ";s:3:"Ꙭ";s:3:"ꚁ";s:3:"Ꚁ";s:3:"ꚃ";s:3:"Ꚃ";s:3:"ꚅ";s:3:"Ꚅ";s:3:"ꚇ";s:3:"Ꚇ";s:3:"ꚉ";s:3:"Ꚉ";s:3:"ꚋ";s:3:"Ꚋ";s:3:"ꚍ";s:3:"Ꚍ";s:3:"ꚏ";s:3:"Ꚏ";s:3:"ꚑ";s:3:"Ꚑ";s:3:"ꚓ";s:3:"Ꚓ";s:3:"ꚕ";s:3:"Ꚕ";s:3:"ꚗ";s:3:"Ꚗ";s:3:"ꜣ";s:3:"Ꜣ";s:3:"ꜥ";s:3:"Ꜥ";s:3:"ꜧ";s:3:"Ꜧ";s:3:"ꜩ";s:3:"Ꜩ";s:3:"ꜫ";s:3:"Ꜫ";s:3:"ꜭ";s:3:"Ꜭ";s:3:"ꜯ";s:3:"Ꜯ";s:3:"ꜳ";s:3:"Ꜳ";s:3:"ꜵ";s:3:"Ꜵ";s:3:"ꜷ";s:3:"Ꜷ";s:3:"ꜹ";s:3:"Ꜹ";s:3:"ꜻ";s:3:"Ꜻ";s:3:"ꜽ";s:3:"Ꜽ";s:3:"ꜿ";s:3:"Ꜿ";s:3:"ꝁ";s:3:"Ꝁ";s:3:"ꝃ";s:3:"Ꝃ";s:3:"ꝅ";s:3:"Ꝅ";s:3:"ꝇ";s:3:"Ꝇ";s:3:"ꝉ";s:3:"Ꝉ";s:3:"ꝋ";s:3:"Ꝋ";s:3:"ꝍ";s:3:"Ꝍ";s:3:"ꝏ";s:3:"Ꝏ";s:3:"ꝑ";s:3:"Ꝑ";s:3:"ꝓ";s:3:"Ꝓ";s:3:"ꝕ";s:3:"Ꝕ";s:3:"ꝗ";s:3:"Ꝗ";s:3:"ꝙ";s:3:"Ꝙ";s:3:"ꝛ";s:3:"Ꝛ";s:3:"ꝝ";s:3:"Ꝝ";s:3:"ꝟ";s:3:"Ꝟ";s:3:"ꝡ";s:3:"Ꝡ";s:3:"ꝣ";s:3:"Ꝣ";s:3:"ꝥ";s:3:"Ꝥ";s:3:"ꝧ";s:3:"Ꝧ";s:3:"ꝩ";s:3:"Ꝩ";s:3:"ꝫ";s:3:"Ꝫ";s:3:"ꝭ";s:3:"Ꝭ";s:3:"ꝯ";s:3:"Ꝯ";s:3:"ꝺ";s:3:"Ꝺ";s:3:"ꝼ";s:3:"Ꝼ";s:3:"ꝿ";s:3:"Ꝿ";s:3:"ꞁ";s:3:"Ꞁ";s:3:"ꞃ";s:3:"Ꞃ";s:3:"ꞅ";s:3:"Ꞅ";s:3:"ꞇ";s:3:"Ꞇ";s:3:"ꞌ";s:3:"Ꞌ";s:3:"ꞑ";s:3:"Ꞑ";s:3:"ꞡ";s:3:"Ꞡ";s:3:"ꞣ";s:3:"Ꞣ";s:3:"ꞥ";s:3:"Ꞥ";s:3:"ꞧ";s:3:"Ꞧ";s:3:"ꞩ";s:3:"Ꞩ";s:3:"a";s:3:"A";s:3:"b";s:3:"B";s:3:"c";s:3:"C";s:3:"d";s:3:"D";s:3:"e";s:3:"E";s:3:"f";s:3:"F";s:3:"g";s:3:"G";s:3:"h";s:3:"H";s:3:"i";s:3:"I";s:3:"j";s:3:"J";s:3:"k";s:3:"K";s:3:"l";s:3:"L";s:3:"m";s:3:"M";s:3:"n";s:3:"N";s:3:"o";s:3:"O";s:3:"p";s:3:"P";s:3:"q";s:3:"Q";s:3:"r";s:3:"R";s:3:"s";s:3:"S";s:3:"t";s:3:"T";s:3:"u";s:3:"U";s:3:"v";s:3:"V";s:3:"w";s:3:"W";s:3:"x";s:3:"X";s:3:"y";s:3:"Y";s:3:"z";s:3:"Z";s:4:"𐐨";s:4:"𐐀";s:4:"𐐩";s:4:"𐐁";s:4:"𐐪";s:4:"𐐂";s:4:"𐐫";s:4:"𐐃";s:4:"𐐬";s:4:"𐐄";s:4:"𐐭";s:4:"𐐅";s:4:"𐐮";s:4:"𐐆";s:4:"𐐯";s:4:"𐐇";s:4:"𐐰";s:4:"𐐈";s:4:"𐐱";s:4:"𐐉";s:4:"𐐲";s:4:"𐐊";s:4:"𐐳";s:4:"𐐋";s:4:"𐐴";s:4:"𐐌";s:4:"𐐵";s:4:"𐐍";s:4:"𐐶";s:4:"𐐎";s:4:"𐐷";s:4:"𐐏";s:4:"𐐸";s:4:"𐐐";s:4:"𐐹";s:4:"𐐑";s:4:"𐐺";s:4:"𐐒";s:4:"𐐻";s:4:"𐐓";s:4:"𐐼";s:4:"𐐔";s:4:"𐐽";s:4:"𐐕";s:4:"𐐾";s:4:"𐐖";s:4:"𐐿";s:4:"𐐗";s:4:"𐑀";s:4:"𐐘";s:4:"𐑁";s:4:"𐐙";s:4:"𐑂";s:4:"𐐚";s:4:"𐑃";s:4:"𐐛";s:4:"𐑄";s:4:"𐐜";s:4:"𐑅";s:4:"𐐝";s:4:"𐑆";s:4:"𐐞";s:4:"𐑇";s:4:"𐐟";s:4:"𐑈";s:4:"𐐠";s:4:"𐑉";s:4:"𐐡";s:4:"𐑊";s:4:"𐐢";s:4:"𐑋";s:4:"𐐣";s:4:"𐑌";s:4:"𐐤";s:4:"𐑍";s:4:"𐐥";s:4:"𐑎";s:4:"𐐦";s:4:"𐑏";s:4:"𐐧";}s:14:"wikiLowerChars";a:1038:{s:1:"A";s:1:"a";s:1:"B";s:1:"b";s:1:"C";s:1:"c";s:1:"D";s:1:"d";s:1:"E";s:1:"e";s:1:"F";s:1:"f";s:1:"G";s:1:"g";s:1:"H";s:1:"h";s:1:"I";s:1:"i";s:1:"J";s:1:"j";s:1:"K";s:1:"k";s:1:"L";s:1:"l";s:1:"M";s:1:"m";s:1:"N";s:1:"n";s:1:"O";s:1:"o";s:1:"P";s:1:"p";s:1:"Q";s:1:"q";s:1:"R";s:1:"r";s:1:"S";s:1:"s";s:1:"T";s:1:"t";s:1:"U";s:1:"u";s:1:"V";s:1:"v";s:1:"W";s:1:"w";s:1:"X";s:1:"x";s:1:"Y";s:1:"y";s:1:"Z";s:1:"z";s:2:"À";s:2:"à";s:2:"Á";s:2:"á";s:2:"Â";s:2:"â";s:2:"Ã";s:2:"ã";s:2:"Ä";s:2:"ä";s:2:"Å";s:2:"å";s:2:"Æ";s:2:"æ";s:2:"Ç";s:2:"ç";s:2:"È";s:2:"è";s:2:"É";s:2:"é";s:2:"Ê";s:2:"ê";s:2:"Ë";s:2:"ë";s:2:"Ì";s:2:"ì";s:2:"Í";s:2:"í";s:2:"Î";s:2:"î";s:2:"Ï";s:2:"ï";s:2:"Ð";s:2:"ð";s:2:"Ñ";s:2:"ñ";s:2:"Ò";s:2:"ò";s:2:"Ó";s:2:"ó";s:2:"Ô";s:2:"ô";s:2:"Õ";s:2:"õ";s:2:"Ö";s:2:"ö";s:2:"Ø";s:2:"ø";s:2:"Ù";s:2:"ù";s:2:"Ú";s:2:"ú";s:2:"Û";s:2:"û";s:2:"Ü";s:2:"ü";s:2:"Ý";s:2:"ý";s:2:"Þ";s:2:"þ";s:2:"Ā";s:2:"ā";s:2:"Ă";s:2:"ă";s:2:"Ą";s:2:"ą";s:2:"Ć";s:2:"ć";s:2:"Ĉ";s:2:"ĉ";s:2:"Ċ";s:2:"ċ";s:2:"Č";s:2:"č";s:2:"Ď";s:2:"ď";s:2:"Đ";s:2:"đ";s:2:"Ē";s:2:"ē";s:2:"Ĕ";s:2:"ĕ";s:2:"Ė";s:2:"ė";s:2:"Ę";s:2:"ę";s:2:"Ě";s:2:"ě";s:2:"Ĝ";s:2:"ĝ";s:2:"Ğ";s:2:"ğ";s:2:"Ġ";s:2:"ġ";s:2:"Ģ";s:2:"ģ";s:2:"Ĥ";s:2:"ĥ";s:2:"Ħ";s:2:"ħ";s:2:"Ĩ";s:2:"ĩ";s:2:"Ī";s:2:"ī";s:2:"Ĭ";s:2:"ĭ";s:2:"Į";s:2:"į";s:2:"İ";s:1:"i";s:2:"IJ";s:2:"ij";s:2:"Ĵ";s:2:"ĵ";s:2:"Ķ";s:2:"ķ";s:2:"Ĺ";s:2:"ĺ";s:2:"Ļ";s:2:"ļ";s:2:"Ľ";s:2:"ľ";s:2:"Ŀ";s:2:"ŀ";s:2:"Ł";s:2:"ł";s:2:"Ń";s:2:"ń";s:2:"Ņ";s:2:"ņ";s:2:"Ň";s:2:"ň";s:2:"Ŋ";s:2:"ŋ";s:2:"Ō";s:2:"ō";s:2:"Ŏ";s:2:"ŏ";s:2:"Ő";s:2:"ő";s:2:"Œ";s:2:"œ";s:2:"Ŕ";s:2:"ŕ";s:2:"Ŗ";s:2:"ŗ";s:2:"Ř";s:2:"ř";s:2:"Ś";s:2:"ś";s:2:"Ŝ";s:2:"ŝ";s:2:"Ş";s:2:"ş";s:2:"Š";s:2:"š";s:2:"Ţ";s:2:"ţ";s:2:"Ť";s:2:"ť";s:2:"Ŧ";s:2:"ŧ";s:2:"Ũ";s:2:"ũ";s:2:"Ū";s:2:"ū";s:2:"Ŭ";s:2:"ŭ";s:2:"Ů";s:2:"ů";s:2:"Ű";s:2:"ű";s:2:"Ų";s:2:"ų";s:2:"Ŵ";s:2:"ŵ";s:2:"Ŷ";s:2:"ŷ";s:2:"Ÿ";s:2:"ÿ";s:2:"Ź";s:2:"ź";s:2:"Ż";s:2:"ż";s:2:"Ž";s:2:"ž";s:2:"Ɓ";s:2:"ɓ";s:2:"Ƃ";s:2:"ƃ";s:2:"Ƅ";s:2:"ƅ";s:2:"Ɔ";s:2:"ɔ";s:2:"Ƈ";s:2:"ƈ";s:2:"Ɖ";s:2:"ɖ";s:2:"Ɗ";s:2:"ɗ";s:2:"Ƌ";s:2:"ƌ";s:2:"Ǝ";s:2:"ǝ";s:2:"Ə";s:2:"ə";s:2:"Ɛ";s:2:"ɛ";s:2:"Ƒ";s:2:"ƒ";s:2:"Ɠ";s:2:"ɠ";s:2:"Ɣ";s:2:"ɣ";s:2:"Ɩ";s:2:"ɩ";s:2:"Ɨ";s:2:"ɨ";s:2:"Ƙ";s:2:"ƙ";s:2:"Ɯ";s:2:"ɯ";s:2:"Ɲ";s:2:"ɲ";s:2:"Ɵ";s:2:"ɵ";s:2:"Ơ";s:2:"ơ";s:2:"Ƣ";s:2:"ƣ";s:2:"Ƥ";s:2:"ƥ";s:2:"Ʀ";s:2:"ʀ";s:2:"Ƨ";s:2:"ƨ";s:2:"Ʃ";s:2:"ʃ";s:2:"Ƭ";s:2:"ƭ";s:2:"Ʈ";s:2:"ʈ";s:2:"Ư";s:2:"ư";s:2:"Ʊ";s:2:"ʊ";s:2:"Ʋ";s:2:"ʋ";s:2:"Ƴ";s:2:"ƴ";s:2:"Ƶ";s:2:"ƶ";s:2:"Ʒ";s:2:"ʒ";s:2:"Ƹ";s:2:"ƹ";s:2:"Ƽ";s:2:"ƽ";s:2:"DŽ";s:2:"dž";s:2:"Dž";s:2:"dž";s:2:"LJ";s:2:"lj";s:2:"Lj";s:2:"lj";s:2:"NJ";s:2:"nj";s:2:"Nj";s:2:"nj";s:2:"Ǎ";s:2:"ǎ";s:2:"Ǐ";s:2:"ǐ";s:2:"Ǒ";s:2:"ǒ";s:2:"Ǔ";s:2:"ǔ";s:2:"Ǖ";s:2:"ǖ";s:2:"Ǘ";s:2:"ǘ";s:2:"Ǚ";s:2:"ǚ";s:2:"Ǜ";s:2:"ǜ";s:2:"Ǟ";s:2:"ǟ";s:2:"Ǡ";s:2:"ǡ";s:2:"Ǣ";s:2:"ǣ";s:2:"Ǥ";s:2:"ǥ";s:2:"Ǧ";s:2:"ǧ";s:2:"Ǩ";s:2:"ǩ";s:2:"Ǫ";s:2:"ǫ";s:2:"Ǭ";s:2:"ǭ";s:2:"Ǯ";s:2:"ǯ";s:2:"DZ";s:2:"dz";s:2:"Dz";s:2:"dz";s:2:"Ǵ";s:2:"ǵ";s:2:"Ƕ";s:2:"ƕ";s:2:"Ƿ";s:2:"ƿ";s:2:"Ǹ";s:2:"ǹ";s:2:"Ǻ";s:2:"ǻ";s:2:"Ǽ";s:2:"ǽ";s:2:"Ǿ";s:2:"ǿ";s:2:"Ȁ";s:2:"ȁ";s:2:"Ȃ";s:2:"ȃ";s:2:"Ȅ";s:2:"ȅ";s:2:"Ȇ";s:2:"ȇ";s:2:"Ȉ";s:2:"ȉ";s:2:"Ȋ";s:2:"ȋ";s:2:"Ȍ";s:2:"ȍ";s:2:"Ȏ";s:2:"ȏ";s:2:"Ȑ";s:2:"ȑ";s:2:"Ȓ";s:2:"ȓ";s:2:"Ȕ";s:2:"ȕ";s:2:"Ȗ";s:2:"ȗ";s:2:"Ș";s:2:"ș";s:2:"Ț";s:2:"ț";s:2:"Ȝ";s:2:"ȝ";s:2:"Ȟ";s:2:"ȟ";s:2:"Ƞ";s:2:"ƞ";s:2:"Ȣ";s:2:"ȣ";s:2:"Ȥ";s:2:"ȥ";s:2:"Ȧ";s:2:"ȧ";s:2:"Ȩ";s:2:"ȩ";s:2:"Ȫ";s:2:"ȫ";s:2:"Ȭ";s:2:"ȭ";s:2:"Ȯ";s:2:"ȯ";s:2:"Ȱ";s:2:"ȱ";s:2:"Ȳ";s:2:"ȳ";s:2:"Ⱥ";s:3:"ⱥ";s:2:"Ȼ";s:2:"ȼ";s:2:"Ƚ";s:2:"ƚ";s:2:"Ⱦ";s:3:"ⱦ";s:2:"Ɂ";s:2:"ɂ";s:2:"Ƀ";s:2:"ƀ";s:2:"Ʉ";s:2:"ʉ";s:2:"Ʌ";s:2:"ʌ";s:2:"Ɇ";s:2:"ɇ";s:2:"Ɉ";s:2:"ɉ";s:2:"Ɋ";s:2:"ɋ";s:2:"Ɍ";s:2:"ɍ";s:2:"Ɏ";s:2:"ɏ";s:2:"Ͱ";s:2:"ͱ";s:2:"Ͳ";s:2:"ͳ";s:2:"Ͷ";s:2:"ͷ";s:2:"Ά";s:2:"ά";s:2:"Έ";s:2:"έ";s:2:"Ή";s:2:"ή";s:2:"Ί";s:2:"ί";s:2:"Ό";s:2:"ό";s:2:"Ύ";s:2:"ύ";s:2:"Ώ";s:2:"ώ";s:2:"Α";s:2:"α";s:2:"Β";s:2:"β";s:2:"Γ";s:2:"γ";s:2:"Δ";s:2:"δ";s:2:"Ε";s:2:"ε";s:2:"Ζ";s:2:"ζ";s:2:"Η";s:2:"η";s:2:"Θ";s:2:"θ";s:2:"Ι";s:2:"ι";s:2:"Κ";s:2:"κ";s:2:"Λ";s:2:"λ";s:2:"Μ";s:2:"μ";s:2:"Ν";s:2:"ν";s:2:"Ξ";s:2:"ξ";s:2:"Ο";s:2:"ο";s:2:"Π";s:2:"π";s:2:"Ρ";s:2:"ρ";s:2:"Σ";s:2:"σ";s:2:"Τ";s:2:"τ";s:2:"Υ";s:2:"υ";s:2:"Φ";s:2:"φ";s:2:"Χ";s:2:"χ";s:2:"Ψ";s:2:"ψ";s:2:"Ω";s:2:"ω";s:2:"Ϊ";s:2:"ϊ";s:2:"Ϋ";s:2:"ϋ";s:2:"Ϗ";s:2:"ϗ";s:2:"Ϙ";s:2:"ϙ";s:2:"Ϛ";s:2:"ϛ";s:2:"Ϝ";s:2:"ϝ";s:2:"Ϟ";s:2:"ϟ";s:2:"Ϡ";s:2:"ϡ";s:2:"Ϣ";s:2:"ϣ";s:2:"Ϥ";s:2:"ϥ";s:2:"Ϧ";s:2:"ϧ";s:2:"Ϩ";s:2:"ϩ";s:2:"Ϫ";s:2:"ϫ";s:2:"Ϭ";s:2:"ϭ";s:2:"Ϯ";s:2:"ϯ";s:2:"ϴ";s:2:"θ";s:2:"Ϸ";s:2:"ϸ";s:2:"Ϲ";s:2:"ϲ";s:2:"Ϻ";s:2:"ϻ";s:2:"Ͻ";s:2:"ͻ";s:2:"Ͼ";s:2:"ͼ";s:2:"Ͽ";s:2:"ͽ";s:2:"Ѐ";s:2:"ѐ";s:2:"Ё";s:2:"ё";s:2:"Ђ";s:2:"ђ";s:2:"Ѓ";s:2:"ѓ";s:2:"Є";s:2:"є";s:2:"Ѕ";s:2:"ѕ";s:2:"І";s:2:"і";s:2:"Ї";s:2:"ї";s:2:"Ј";s:2:"ј";s:2:"Љ";s:2:"љ";s:2:"Њ";s:2:"њ";s:2:"Ћ";s:2:"ћ";s:2:"Ќ";s:2:"ќ";s:2:"Ѝ";s:2:"ѝ";s:2:"Ў";s:2:"ў";s:2:"Џ";s:2:"џ";s:2:"А";s:2:"а";s:2:"Б";s:2:"б";s:2:"В";s:2:"в";s:2:"Г";s:2:"г";s:2:"Д";s:2:"д";s:2:"Е";s:2:"е";s:2:"Ж";s:2:"ж";s:2:"З";s:2:"з";s:2:"И";s:2:"и";s:2:"Й";s:2:"й";s:2:"К";s:2:"к";s:2:"Л";s:2:"л";s:2:"М";s:2:"м";s:2:"Н";s:2:"н";s:2:"О";s:2:"о";s:2:"П";s:2:"п";s:2:"Р";s:2:"р";s:2:"С";s:2:"с";s:2:"Т";s:2:"т";s:2:"У";s:2:"у";s:2:"Ф";s:2:"ф";s:2:"Х";s:2:"х";s:2:"Ц";s:2:"ц";s:2:"Ч";s:2:"ч";s:2:"Ш";s:2:"ш";s:2:"Щ";s:2:"щ";s:2:"Ъ";s:2:"ъ";s:2:"Ы";s:2:"ы";s:2:"Ь";s:2:"ь";s:2:"Э";s:2:"э";s:2:"Ю";s:2:"ю";s:2:"Я";s:2:"я";s:2:"Ѡ";s:2:"ѡ";s:2:"Ѣ";s:2:"ѣ";s:2:"Ѥ";s:2:"ѥ";s:2:"Ѧ";s:2:"ѧ";s:2:"Ѩ";s:2:"ѩ";s:2:"Ѫ";s:2:"ѫ";s:2:"Ѭ";s:2:"ѭ";s:2:"Ѯ";s:2:"ѯ";s:2:"Ѱ";s:2:"ѱ";s:2:"Ѳ";s:2:"ѳ";s:2:"Ѵ";s:2:"ѵ";s:2:"Ѷ";s:2:"ѷ";s:2:"Ѹ";s:2:"ѹ";s:2:"Ѻ";s:2:"ѻ";s:2:"Ѽ";s:2:"ѽ";s:2:"Ѿ";s:2:"ѿ";s:2:"Ҁ";s:2:"ҁ";s:2:"Ҋ";s:2:"ҋ";s:2:"Ҍ";s:2:"ҍ";s:2:"Ҏ";s:2:"ҏ";s:2:"Ґ";s:2:"ґ";s:2:"Ғ";s:2:"ғ";s:2:"Ҕ";s:2:"ҕ";s:2:"Җ";s:2:"җ";s:2:"Ҙ";s:2:"ҙ";s:2:"Қ";s:2:"қ";s:2:"Ҝ";s:2:"ҝ";s:2:"Ҟ";s:2:"ҟ";s:2:"Ҡ";s:2:"ҡ";s:2:"Ң";s:2:"ң";s:2:"Ҥ";s:2:"ҥ";s:2:"Ҧ";s:2:"ҧ";s:2:"Ҩ";s:2:"ҩ";s:2:"Ҫ";s:2:"ҫ";s:2:"Ҭ";s:2:"ҭ";s:2:"Ү";s:2:"ү";s:2:"Ұ";s:2:"ұ";s:2:"Ҳ";s:2:"ҳ";s:2:"Ҵ";s:2:"ҵ";s:2:"Ҷ";s:2:"ҷ";s:2:"Ҹ";s:2:"ҹ";s:2:"Һ";s:2:"һ";s:2:"Ҽ";s:2:"ҽ";s:2:"Ҿ";s:2:"ҿ";s:2:"Ӏ";s:2:"ӏ";s:2:"Ӂ";s:2:"ӂ";s:2:"Ӄ";s:2:"ӄ";s:2:"Ӆ";s:2:"ӆ";s:2:"Ӈ";s:2:"ӈ";s:2:"Ӊ";s:2:"ӊ";s:2:"Ӌ";s:2:"ӌ";s:2:"Ӎ";s:2:"ӎ";s:2:"Ӑ";s:2:"ӑ";s:2:"Ӓ";s:2:"ӓ";s:2:"Ӕ";s:2:"ӕ";s:2:"Ӗ";s:2:"ӗ";s:2:"Ә";s:2:"ә";s:2:"Ӛ";s:2:"ӛ";s:2:"Ӝ";s:2:"ӝ";s:2:"Ӟ";s:2:"ӟ";s:2:"Ӡ";s:2:"ӡ";s:2:"Ӣ";s:2:"ӣ";s:2:"Ӥ";s:2:"ӥ";s:2:"Ӧ";s:2:"ӧ";s:2:"Ө";s:2:"ө";s:2:"Ӫ";s:2:"ӫ";s:2:"Ӭ";s:2:"ӭ";s:2:"Ӯ";s:2:"ӯ";s:2:"Ӱ";s:2:"ӱ";s:2:"Ӳ";s:2:"ӳ";s:2:"Ӵ";s:2:"ӵ";s:2:"Ӷ";s:2:"ӷ";s:2:"Ӹ";s:2:"ӹ";s:2:"Ӻ";s:2:"ӻ";s:2:"Ӽ";s:2:"ӽ";s:2:"Ӿ";s:2:"ӿ";s:2:"Ԁ";s:2:"ԁ";s:2:"Ԃ";s:2:"ԃ";s:2:"Ԅ";s:2:"ԅ";s:2:"Ԇ";s:2:"ԇ";s:2:"Ԉ";s:2:"ԉ";s:2:"Ԋ";s:2:"ԋ";s:2:"Ԍ";s:2:"ԍ";s:2:"Ԏ";s:2:"ԏ";s:2:"Ԑ";s:2:"ԑ";s:2:"Ԓ";s:2:"ԓ";s:2:"Ԕ";s:2:"ԕ";s:2:"Ԗ";s:2:"ԗ";s:2:"Ԙ";s:2:"ԙ";s:2:"Ԛ";s:2:"ԛ";s:2:"Ԝ";s:2:"ԝ";s:2:"Ԟ";s:2:"ԟ";s:2:"Ԡ";s:2:"ԡ";s:2:"Ԣ";s:2:"ԣ";s:2:"Ԥ";s:2:"ԥ";s:2:"Ԧ";s:2:"ԧ";s:2:"Ա";s:2:"ա";s:2:"Բ";s:2:"բ";s:2:"Գ";s:2:"գ";s:2:"Դ";s:2:"դ";s:2:"Ե";s:2:"ե";s:2:"Զ";s:2:"զ";s:2:"Է";s:2:"է";s:2:"Ը";s:2:"ը";s:2:"Թ";s:2:"թ";s:2:"Ժ";s:2:"ժ";s:2:"Ի";s:2:"ի";s:2:"Լ";s:2:"լ";s:2:"Խ";s:2:"խ";s:2:"Ծ";s:2:"ծ";s:2:"Կ";s:2:"կ";s:2:"Հ";s:2:"հ";s:2:"Ձ";s:2:"ձ";s:2:"Ղ";s:2:"ղ";s:2:"Ճ";s:2:"ճ";s:2:"Մ";s:2:"մ";s:2:"Յ";s:2:"յ";s:2:"Ն";s:2:"ն";s:2:"Շ";s:2:"շ";s:2:"Ո";s:2:"ո";s:2:"Չ";s:2:"չ";s:2:"Պ";s:2:"պ";s:2:"Ջ";s:2:"ջ";s:2:"Ռ";s:2:"ռ";s:2:"Ս";s:2:"ս";s:2:"Վ";s:2:"վ";s:2:"Տ";s:2:"տ";s:2:"Ր";s:2:"ր";s:2:"Ց";s:2:"ց";s:2:"Ւ";s:2:"ւ";s:2:"Փ";s:2:"փ";s:2:"Ք";s:2:"ք";s:2:"Օ";s:2:"օ";s:2:"Ֆ";s:2:"ֆ";s:3:"Ⴀ";s:3:"ⴀ";s:3:"Ⴁ";s:3:"ⴁ";s:3:"Ⴂ";s:3:"ⴂ";s:3:"Ⴃ";s:3:"ⴃ";s:3:"Ⴄ";s:3:"ⴄ";s:3:"Ⴅ";s:3:"ⴅ";s:3:"Ⴆ";s:3:"ⴆ";s:3:"Ⴇ";s:3:"ⴇ";s:3:"Ⴈ";s:3:"ⴈ";s:3:"Ⴉ";s:3:"ⴉ";s:3:"Ⴊ";s:3:"ⴊ";s:3:"Ⴋ";s:3:"ⴋ";s:3:"Ⴌ";s:3:"ⴌ";s:3:"Ⴍ";s:3:"ⴍ";s:3:"Ⴎ";s:3:"ⴎ";s:3:"Ⴏ";s:3:"ⴏ";s:3:"Ⴐ";s:3:"ⴐ";s:3:"Ⴑ";s:3:"ⴑ";s:3:"Ⴒ";s:3:"ⴒ";s:3:"Ⴓ";s:3:"ⴓ";s:3:"Ⴔ";s:3:"ⴔ";s:3:"Ⴕ";s:3:"ⴕ";s:3:"Ⴖ";s:3:"ⴖ";s:3:"Ⴗ";s:3:"ⴗ";s:3:"Ⴘ";s:3:"ⴘ";s:3:"Ⴙ";s:3:"ⴙ";s:3:"Ⴚ";s:3:"ⴚ";s:3:"Ⴛ";s:3:"ⴛ";s:3:"Ⴜ";s:3:"ⴜ";s:3:"Ⴝ";s:3:"ⴝ";s:3:"Ⴞ";s:3:"ⴞ";s:3:"Ⴟ";s:3:"ⴟ";s:3:"Ⴠ";s:3:"ⴠ";s:3:"Ⴡ";s:3:"ⴡ";s:3:"Ⴢ";s:3:"ⴢ";s:3:"Ⴣ";s:3:"ⴣ";s:3:"Ⴤ";s:3:"ⴤ";s:3:"Ⴥ";s:3:"ⴥ";s:3:"Ḁ";s:3:"ḁ";s:3:"Ḃ";s:3:"ḃ";s:3:"Ḅ";s:3:"ḅ";s:3:"Ḇ";s:3:"ḇ";s:3:"Ḉ";s:3:"ḉ";s:3:"Ḋ";s:3:"ḋ";s:3:"Ḍ";s:3:"ḍ";s:3:"Ḏ";s:3:"ḏ";s:3:"Ḑ";s:3:"ḑ";s:3:"Ḓ";s:3:"ḓ";s:3:"Ḕ";s:3:"ḕ";s:3:"Ḗ";s:3:"ḗ";s:3:"Ḙ";s:3:"ḙ";s:3:"Ḛ";s:3:"ḛ";s:3:"Ḝ";s:3:"ḝ";s:3:"Ḟ";s:3:"ḟ";s:3:"Ḡ";s:3:"ḡ";s:3:"Ḣ";s:3:"ḣ";s:3:"Ḥ";s:3:"ḥ";s:3:"Ḧ";s:3:"ḧ";s:3:"Ḩ";s:3:"ḩ";s:3:"Ḫ";s:3:"ḫ";s:3:"Ḭ";s:3:"ḭ";s:3:"Ḯ";s:3:"ḯ";s:3:"Ḱ";s:3:"ḱ";s:3:"Ḳ";s:3:"ḳ";s:3:"Ḵ";s:3:"ḵ";s:3:"Ḷ";s:3:"ḷ";s:3:"Ḹ";s:3:"ḹ";s:3:"Ḻ";s:3:"ḻ";s:3:"Ḽ";s:3:"ḽ";s:3:"Ḿ";s:3:"ḿ";s:3:"Ṁ";s:3:"ṁ";s:3:"Ṃ";s:3:"ṃ";s:3:"Ṅ";s:3:"ṅ";s:3:"Ṇ";s:3:"ṇ";s:3:"Ṉ";s:3:"ṉ";s:3:"Ṋ";s:3:"ṋ";s:3:"Ṍ";s:3:"ṍ";s:3:"Ṏ";s:3:"ṏ";s:3:"Ṑ";s:3:"ṑ";s:3:"Ṓ";s:3:"ṓ";s:3:"Ṕ";s:3:"ṕ";s:3:"Ṗ";s:3:"ṗ";s:3:"Ṙ";s:3:"ṙ";s:3:"Ṛ";s:3:"ṛ";s:3:"Ṝ";s:3:"ṝ";s:3:"Ṟ";s:3:"ṟ";s:3:"Ṡ";s:3:"ṡ";s:3:"Ṣ";s:3:"ṣ";s:3:"Ṥ";s:3:"ṥ";s:3:"Ṧ";s:3:"ṧ";s:3:"Ṩ";s:3:"ṩ";s:3:"Ṫ";s:3:"ṫ";s:3:"Ṭ";s:3:"ṭ";s:3:"Ṯ";s:3:"ṯ";s:3:"Ṱ";s:3:"ṱ";s:3:"Ṳ";s:3:"ṳ";s:3:"Ṵ";s:3:"ṵ";s:3:"Ṷ";s:3:"ṷ";s:3:"Ṹ";s:3:"ṹ";s:3:"Ṻ";s:3:"ṻ";s:3:"Ṽ";s:3:"ṽ";s:3:"Ṿ";s:3:"ṿ";s:3:"Ẁ";s:3:"ẁ";s:3:"Ẃ";s:3:"ẃ";s:3:"Ẅ";s:3:"ẅ";s:3:"Ẇ";s:3:"ẇ";s:3:"Ẉ";s:3:"ẉ";s:3:"Ẋ";s:3:"ẋ";s:3:"Ẍ";s:3:"ẍ";s:3:"Ẏ";s:3:"ẏ";s:3:"Ẑ";s:3:"ẑ";s:3:"Ẓ";s:3:"ẓ";s:3:"Ẕ";s:3:"ẕ";s:3:"ẞ";s:2:"ß";s:3:"Ạ";s:3:"ạ";s:3:"Ả";s:3:"ả";s:3:"Ấ";s:3:"ấ";s:3:"Ầ";s:3:"ầ";s:3:"Ẩ";s:3:"ẩ";s:3:"Ẫ";s:3:"ẫ";s:3:"Ậ";s:3:"ậ";s:3:"Ắ";s:3:"ắ";s:3:"Ằ";s:3:"ằ";s:3:"Ẳ";s:3:"ẳ";s:3:"Ẵ";s:3:"ẵ";s:3:"Ặ";s:3:"ặ";s:3:"Ẹ";s:3:"ẹ";s:3:"Ẻ";s:3:"ẻ";s:3:"Ẽ";s:3:"ẽ";s:3:"Ế";s:3:"ế";s:3:"Ề";s:3:"ề";s:3:"Ể";s:3:"ể";s:3:"Ễ";s:3:"ễ";s:3:"Ệ";s:3:"ệ";s:3:"Ỉ";s:3:"ỉ";s:3:"Ị";s:3:"ị";s:3:"Ọ";s:3:"ọ";s:3:"Ỏ";s:3:"ỏ";s:3:"Ố";s:3:"ố";s:3:"Ồ";s:3:"ồ";s:3:"Ổ";s:3:"ổ";s:3:"Ỗ";s:3:"ỗ";s:3:"Ộ";s:3:"ộ";s:3:"Ớ";s:3:"ớ";s:3:"Ờ";s:3:"ờ";s:3:"Ở";s:3:"ở";s:3:"Ỡ";s:3:"ỡ";s:3:"Ợ";s:3:"ợ";s:3:"Ụ";s:3:"ụ";s:3:"Ủ";s:3:"ủ";s:3:"Ứ";s:3:"ứ";s:3:"Ừ";s:3:"ừ";s:3:"Ử";s:3:"ử";s:3:"Ữ";s:3:"ữ";s:3:"Ự";s:3:"ự";s:3:"Ỳ";s:3:"ỳ";s:3:"Ỵ";s:3:"ỵ";s:3:"Ỷ";s:3:"ỷ";s:3:"Ỹ";s:3:"ỹ";s:3:"Ỻ";s:3:"ỻ";s:3:"Ỽ";s:3:"ỽ";s:3:"Ỿ";s:3:"ỿ";s:3:"Ἀ";s:3:"ἀ";s:3:"Ἁ";s:3:"ἁ";s:3:"Ἂ";s:3:"ἂ";s:3:"Ἃ";s:3:"ἃ";s:3:"Ἄ";s:3:"ἄ";s:3:"Ἅ";s:3:"ἅ";s:3:"Ἆ";s:3:"ἆ";s:3:"Ἇ";s:3:"ἇ";s:3:"Ἐ";s:3:"ἐ";s:3:"Ἑ";s:3:"ἑ";s:3:"Ἒ";s:3:"ἒ";s:3:"Ἓ";s:3:"ἓ";s:3:"Ἔ";s:3:"ἔ";s:3:"Ἕ";s:3:"ἕ";s:3:"Ἠ";s:3:"ἠ";s:3:"Ἡ";s:3:"ἡ";s:3:"Ἢ";s:3:"ἢ";s:3:"Ἣ";s:3:"ἣ";s:3:"Ἤ";s:3:"ἤ";s:3:"Ἥ";s:3:"ἥ";s:3:"Ἦ";s:3:"ἦ";s:3:"Ἧ";s:3:"ἧ";s:3:"Ἰ";s:3:"ἰ";s:3:"Ἱ";s:3:"ἱ";s:3:"Ἲ";s:3:"ἲ";s:3:"Ἳ";s:3:"ἳ";s:3:"Ἴ";s:3:"ἴ";s:3:"Ἵ";s:3:"ἵ";s:3:"Ἶ";s:3:"ἶ";s:3:"Ἷ";s:3:"ἷ";s:3:"Ὀ";s:3:"ὀ";s:3:"Ὁ";s:3:"ὁ";s:3:"Ὂ";s:3:"ὂ";s:3:"Ὃ";s:3:"ὃ";s:3:"Ὄ";s:3:"ὄ";s:3:"Ὅ";s:3:"ὅ";s:3:"Ὑ";s:3:"ὑ";s:3:"Ὓ";s:3:"ὓ";s:3:"Ὕ";s:3:"ὕ";s:3:"Ὗ";s:3:"ὗ";s:3:"Ὠ";s:3:"ὠ";s:3:"Ὡ";s:3:"ὡ";s:3:"Ὢ";s:3:"ὢ";s:3:"Ὣ";s:3:"ὣ";s:3:"Ὤ";s:3:"ὤ";s:3:"Ὥ";s:3:"ὥ";s:3:"Ὦ";s:3:"ὦ";s:3:"Ὧ";s:3:"ὧ";s:3:"ᾈ";s:3:"ᾀ";s:3:"ᾉ";s:3:"ᾁ";s:3:"ᾊ";s:3:"ᾂ";s:3:"ᾋ";s:3:"ᾃ";s:3:"ᾌ";s:3:"ᾄ";s:3:"ᾍ";s:3:"ᾅ";s:3:"ᾎ";s:3:"ᾆ";s:3:"ᾏ";s:3:"ᾇ";s:3:"ᾘ";s:3:"ᾐ";s:3:"ᾙ";s:3:"ᾑ";s:3:"ᾚ";s:3:"ᾒ";s:3:"ᾛ";s:3:"ᾓ";s:3:"ᾜ";s:3:"ᾔ";s:3:"ᾝ";s:3:"ᾕ";s:3:"ᾞ";s:3:"ᾖ";s:3:"ᾟ";s:3:"ᾗ";s:3:"ᾨ";s:3:"ᾠ";s:3:"ᾩ";s:3:"ᾡ";s:3:"ᾪ";s:3:"ᾢ";s:3:"ᾫ";s:3:"ᾣ";s:3:"ᾬ";s:3:"ᾤ";s:3:"ᾭ";s:3:"ᾥ";s:3:"ᾮ";s:3:"ᾦ";s:3:"ᾯ";s:3:"ᾧ";s:3:"Ᾰ";s:3:"ᾰ";s:3:"Ᾱ";s:3:"ᾱ";s:3:"Ὰ";s:3:"ὰ";s:3:"Ά";s:3:"ά";s:3:"ᾼ";s:3:"ᾳ";s:3:"Ὲ";s:3:"ὲ";s:3:"Έ";s:3:"έ";s:3:"Ὴ";s:3:"ὴ";s:3:"Ή";s:3:"ή";s:3:"ῌ";s:3:"ῃ";s:3:"Ῐ";s:3:"ῐ";s:3:"Ῑ";s:3:"ῑ";s:3:"Ὶ";s:3:"ὶ";s:3:"Ί";s:3:"ί";s:3:"Ῠ";s:3:"ῠ";s:3:"Ῡ";s:3:"ῡ";s:3:"Ὺ";s:3:"ὺ";s:3:"Ύ";s:3:"ύ";s:3:"Ῥ";s:3:"ῥ";s:3:"Ὸ";s:3:"ὸ";s:3:"Ό";s:3:"ό";s:3:"Ὼ";s:3:"ὼ";s:3:"Ώ";s:3:"ώ";s:3:"ῼ";s:3:"ῳ";s:3:"Ω";s:2:"ω";s:3:"K";s:1:"k";s:3:"Å";s:2:"å";s:3:"Ⅎ";s:3:"ⅎ";s:3:"Ⅰ";s:3:"ⅰ";s:3:"Ⅱ";s:3:"ⅱ";s:3:"Ⅲ";s:3:"ⅲ";s:3:"Ⅳ";s:3:"ⅳ";s:3:"Ⅴ";s:3:"ⅴ";s:3:"Ⅵ";s:3:"ⅵ";s:3:"Ⅶ";s:3:"ⅶ";s:3:"Ⅷ";s:3:"ⅷ";s:3:"Ⅸ";s:3:"ⅸ";s:3:"Ⅹ";s:3:"ⅹ";s:3:"Ⅺ";s:3:"ⅺ";s:3:"Ⅻ";s:3:"ⅻ";s:3:"Ⅼ";s:3:"ⅼ";s:3:"Ⅽ";s:3:"ⅽ";s:3:"Ⅾ";s:3:"ⅾ";s:3:"Ⅿ";s:3:"ⅿ";s:3:"Ↄ";s:3:"ↄ";s:3:"Ⓐ";s:3:"ⓐ";s:3:"Ⓑ";s:3:"ⓑ";s:3:"Ⓒ";s:3:"ⓒ";s:3:"Ⓓ";s:3:"ⓓ";s:3:"Ⓔ";s:3:"ⓔ";s:3:"Ⓕ";s:3:"ⓕ";s:3:"Ⓖ";s:3:"ⓖ";s:3:"Ⓗ";s:3:"ⓗ";s:3:"Ⓘ";s:3:"ⓘ";s:3:"Ⓙ";s:3:"ⓙ";s:3:"Ⓚ";s:3:"ⓚ";s:3:"Ⓛ";s:3:"ⓛ";s:3:"Ⓜ";s:3:"ⓜ";s:3:"Ⓝ";s:3:"ⓝ";s:3:"Ⓞ";s:3:"ⓞ";s:3:"Ⓟ";s:3:"ⓟ";s:3:"Ⓠ";s:3:"ⓠ";s:3:"Ⓡ";s:3:"ⓡ";s:3:"Ⓢ";s:3:"ⓢ";s:3:"Ⓣ";s:3:"ⓣ";s:3:"Ⓤ";s:3:"ⓤ";s:3:"Ⓥ";s:3:"ⓥ";s:3:"Ⓦ";s:3:"ⓦ";s:3:"Ⓧ";s:3:"ⓧ";s:3:"Ⓨ";s:3:"ⓨ";s:3:"Ⓩ";s:3:"ⓩ";s:3:"Ⰰ";s:3:"ⰰ";s:3:"Ⰱ";s:3:"ⰱ";s:3:"Ⰲ";s:3:"ⰲ";s:3:"Ⰳ";s:3:"ⰳ";s:3:"Ⰴ";s:3:"ⰴ";s:3:"Ⰵ";s:3:"ⰵ";s:3:"Ⰶ";s:3:"ⰶ";s:3:"Ⰷ";s:3:"ⰷ";s:3:"Ⰸ";s:3:"ⰸ";s:3:"Ⰹ";s:3:"ⰹ";s:3:"Ⰺ";s:3:"ⰺ";s:3:"Ⰻ";s:3:"ⰻ";s:3:"Ⰼ";s:3:"ⰼ";s:3:"Ⰽ";s:3:"ⰽ";s:3:"Ⰾ";s:3:"ⰾ";s:3:"Ⰿ";s:3:"ⰿ";s:3:"Ⱀ";s:3:"ⱀ";s:3:"Ⱁ";s:3:"ⱁ";s:3:"Ⱂ";s:3:"ⱂ";s:3:"Ⱃ";s:3:"ⱃ";s:3:"Ⱄ";s:3:"ⱄ";s:3:"Ⱅ";s:3:"ⱅ";s:3:"Ⱆ";s:3:"ⱆ";s:3:"Ⱇ";s:3:"ⱇ";s:3:"Ⱈ";s:3:"ⱈ";s:3:"Ⱉ";s:3:"ⱉ";s:3:"Ⱊ";s:3:"ⱊ";s:3:"Ⱋ";s:3:"ⱋ";s:3:"Ⱌ";s:3:"ⱌ";s:3:"Ⱍ";s:3:"ⱍ";s:3:"Ⱎ";s:3:"ⱎ";s:3:"Ⱏ";s:3:"ⱏ";s:3:"Ⱐ";s:3:"ⱐ";s:3:"Ⱑ";s:3:"ⱑ";s:3:"Ⱒ";s:3:"ⱒ";s:3:"Ⱓ";s:3:"ⱓ";s:3:"Ⱔ";s:3:"ⱔ";s:3:"Ⱕ";s:3:"ⱕ";s:3:"Ⱖ";s:3:"ⱖ";s:3:"Ⱗ";s:3:"ⱗ";s:3:"Ⱘ";s:3:"ⱘ";s:3:"Ⱙ";s:3:"ⱙ";s:3:"Ⱚ";s:3:"ⱚ";s:3:"Ⱛ";s:3:"ⱛ";s:3:"Ⱜ";s:3:"ⱜ";s:3:"Ⱝ";s:3:"ⱝ";s:3:"Ⱞ";s:3:"ⱞ";s:3:"Ⱡ";s:3:"ⱡ";s:3:"Ɫ";s:2:"ɫ";s:3:"Ᵽ";s:3:"ᵽ";s:3:"Ɽ";s:2:"ɽ";s:3:"Ⱨ";s:3:"ⱨ";s:3:"Ⱪ";s:3:"ⱪ";s:3:"Ⱬ";s:3:"ⱬ";s:3:"Ɑ";s:2:"ɑ";s:3:"Ɱ";s:2:"ɱ";s:3:"Ɐ";s:2:"ɐ";s:3:"Ɒ";s:2:"ɒ";s:3:"Ⱳ";s:3:"ⱳ";s:3:"Ⱶ";s:3:"ⱶ";s:3:"Ȿ";s:2:"ȿ";s:3:"Ɀ";s:2:"ɀ";s:3:"Ⲁ";s:3:"ⲁ";s:3:"Ⲃ";s:3:"ⲃ";s:3:"Ⲅ";s:3:"ⲅ";s:3:"Ⲇ";s:3:"ⲇ";s:3:"Ⲉ";s:3:"ⲉ";s:3:"Ⲋ";s:3:"ⲋ";s:3:"Ⲍ";s:3:"ⲍ";s:3:"Ⲏ";s:3:"ⲏ";s:3:"Ⲑ";s:3:"ⲑ";s:3:"Ⲓ";s:3:"ⲓ";s:3:"Ⲕ";s:3:"ⲕ";s:3:"Ⲗ";s:3:"ⲗ";s:3:"Ⲙ";s:3:"ⲙ";s:3:"Ⲛ";s:3:"ⲛ";s:3:"Ⲝ";s:3:"ⲝ";s:3:"Ⲟ";s:3:"ⲟ";s:3:"Ⲡ";s:3:"ⲡ";s:3:"Ⲣ";s:3:"ⲣ";s:3:"Ⲥ";s:3:"ⲥ";s:3:"Ⲧ";s:3:"ⲧ";s:3:"Ⲩ";s:3:"ⲩ";s:3:"Ⲫ";s:3:"ⲫ";s:3:"Ⲭ";s:3:"ⲭ";s:3:"Ⲯ";s:3:"ⲯ";s:3:"Ⲱ";s:3:"ⲱ";s:3:"Ⲳ";s:3:"ⲳ";s:3:"Ⲵ";s:3:"ⲵ";s:3:"Ⲷ";s:3:"ⲷ";s:3:"Ⲹ";s:3:"ⲹ";s:3:"Ⲻ";s:3:"ⲻ";s:3:"Ⲽ";s:3:"ⲽ";s:3:"Ⲿ";s:3:"ⲿ";s:3:"Ⳁ";s:3:"ⳁ";s:3:"Ⳃ";s:3:"ⳃ";s:3:"Ⳅ";s:3:"ⳅ";s:3:"Ⳇ";s:3:"ⳇ";s:3:"Ⳉ";s:3:"ⳉ";s:3:"Ⳋ";s:3:"ⳋ";s:3:"Ⳍ";s:3:"ⳍ";s:3:"Ⳏ";s:3:"ⳏ";s:3:"Ⳑ";s:3:"ⳑ";s:3:"Ⳓ";s:3:"ⳓ";s:3:"Ⳕ";s:3:"ⳕ";s:3:"Ⳗ";s:3:"ⳗ";s:3:"Ⳙ";s:3:"ⳙ";s:3:"Ⳛ";s:3:"ⳛ";s:3:"Ⳝ";s:3:"ⳝ";s:3:"Ⳟ";s:3:"ⳟ";s:3:"Ⳡ";s:3:"ⳡ";s:3:"Ⳣ";s:3:"ⳣ";s:3:"Ⳬ";s:3:"ⳬ";s:3:"Ⳮ";s:3:"ⳮ";s:3:"Ꙁ";s:3:"ꙁ";s:3:"Ꙃ";s:3:"ꙃ";s:3:"Ꙅ";s:3:"ꙅ";s:3:"Ꙇ";s:3:"ꙇ";s:3:"Ꙉ";s:3:"ꙉ";s:3:"Ꙋ";s:3:"ꙋ";s:3:"Ꙍ";s:3:"ꙍ";s:3:"Ꙏ";s:3:"ꙏ";s:3:"Ꙑ";s:3:"ꙑ";s:3:"Ꙓ";s:3:"ꙓ";s:3:"Ꙕ";s:3:"ꙕ";s:3:"Ꙗ";s:3:"ꙗ";s:3:"Ꙙ";s:3:"ꙙ";s:3:"Ꙛ";s:3:"ꙛ";s:3:"Ꙝ";s:3:"ꙝ";s:3:"Ꙟ";s:3:"ꙟ";s:3:"Ꙡ";s:3:"ꙡ";s:3:"Ꙣ";s:3:"ꙣ";s:3:"Ꙥ";s:3:"ꙥ";s:3:"Ꙧ";s:3:"ꙧ";s:3:"Ꙩ";s:3:"ꙩ";s:3:"Ꙫ";s:3:"ꙫ";s:3:"Ꙭ";s:3:"ꙭ";s:3:"Ꚁ";s:3:"ꚁ";s:3:"Ꚃ";s:3:"ꚃ";s:3:"Ꚅ";s:3:"ꚅ";s:3:"Ꚇ";s:3:"ꚇ";s:3:"Ꚉ";s:3:"ꚉ";s:3:"Ꚋ";s:3:"ꚋ";s:3:"Ꚍ";s:3:"ꚍ";s:3:"Ꚏ";s:3:"ꚏ";s:3:"Ꚑ";s:3:"ꚑ";s:3:"Ꚓ";s:3:"ꚓ";s:3:"Ꚕ";s:3:"ꚕ";s:3:"Ꚗ";s:3:"ꚗ";s:3:"Ꜣ";s:3:"ꜣ";s:3:"Ꜥ";s:3:"ꜥ";s:3:"Ꜧ";s:3:"ꜧ";s:3:"Ꜩ";s:3:"ꜩ";s:3:"Ꜫ";s:3:"ꜫ";s:3:"Ꜭ";s:3:"ꜭ";s:3:"Ꜯ";s:3:"ꜯ";s:3:"Ꜳ";s:3:"ꜳ";s:3:"Ꜵ";s:3:"ꜵ";s:3:"Ꜷ";s:3:"ꜷ";s:3:"Ꜹ";s:3:"ꜹ";s:3:"Ꜻ";s:3:"ꜻ";s:3:"Ꜽ";s:3:"ꜽ";s:3:"Ꜿ";s:3:"ꜿ";s:3:"Ꝁ";s:3:"ꝁ";s:3:"Ꝃ";s:3:"ꝃ";s:3:"Ꝅ";s:3:"ꝅ";s:3:"Ꝇ";s:3:"ꝇ";s:3:"Ꝉ";s:3:"ꝉ";s:3:"Ꝋ";s:3:"ꝋ";s:3:"Ꝍ";s:3:"ꝍ";s:3:"Ꝏ";s:3:"ꝏ";s:3:"Ꝑ";s:3:"ꝑ";s:3:"Ꝓ";s:3:"ꝓ";s:3:"Ꝕ";s:3:"ꝕ";s:3:"Ꝗ";s:3:"ꝗ";s:3:"Ꝙ";s:3:"ꝙ";s:3:"Ꝛ";s:3:"ꝛ";s:3:"Ꝝ";s:3:"ꝝ";s:3:"Ꝟ";s:3:"ꝟ";s:3:"Ꝡ";s:3:"ꝡ";s:3:"Ꝣ";s:3:"ꝣ";s:3:"Ꝥ";s:3:"ꝥ";s:3:"Ꝧ";s:3:"ꝧ";s:3:"Ꝩ";s:3:"ꝩ";s:3:"Ꝫ";s:3:"ꝫ";s:3:"Ꝭ";s:3:"ꝭ";s:3:"Ꝯ";s:3:"ꝯ";s:3:"Ꝺ";s:3:"ꝺ";s:3:"Ꝼ";s:3:"ꝼ";s:3:"Ᵹ";s:3:"ᵹ";s:3:"Ꝿ";s:3:"ꝿ";s:3:"Ꞁ";s:3:"ꞁ";s:3:"Ꞃ";s:3:"ꞃ";s:3:"Ꞅ";s:3:"ꞅ";s:3:"Ꞇ";s:3:"ꞇ";s:3:"Ꞌ";s:3:"ꞌ";s:3:"Ɥ";s:2:"ɥ";s:3:"Ꞑ";s:3:"ꞑ";s:3:"Ꞡ";s:3:"ꞡ";s:3:"Ꞣ";s:3:"ꞣ";s:3:"Ꞥ";s:3:"ꞥ";s:3:"Ꞧ";s:3:"ꞧ";s:3:"Ꞩ";s:3:"ꞩ";s:3:"A";s:3:"a";s:3:"B";s:3:"b";s:3:"C";s:3:"c";s:3:"D";s:3:"d";s:3:"E";s:3:"e";s:3:"F";s:3:"f";s:3:"G";s:3:"g";s:3:"H";s:3:"h";s:3:"I";s:3:"i";s:3:"J";s:3:"j";s:3:"K";s:3:"k";s:3:"L";s:3:"l";s:3:"M";s:3:"m";s:3:"N";s:3:"n";s:3:"O";s:3:"o";s:3:"P";s:3:"p";s:3:"Q";s:3:"q";s:3:"R";s:3:"r";s:3:"S";s:3:"s";s:3:"T";s:3:"t";s:3:"U";s:3:"u";s:3:"V";s:3:"v";s:3:"W";s:3:"w";s:3:"X";s:3:"x";s:3:"Y";s:3:"y";s:3:"Z";s:3:"z";s:4:"𐐀";s:4:"𐐨";s:4:"𐐁";s:4:"𐐩";s:4:"𐐂";s:4:"𐐪";s:4:"𐐃";s:4:"𐐫";s:4:"𐐄";s:4:"𐐬";s:4:"𐐅";s:4:"𐐭";s:4:"𐐆";s:4:"𐐮";s:4:"𐐇";s:4:"𐐯";s:4:"𐐈";s:4:"𐐰";s:4:"𐐉";s:4:"𐐱";s:4:"𐐊";s:4:"𐐲";s:4:"𐐋";s:4:"𐐳";s:4:"𐐌";s:4:"𐐴";s:4:"𐐍";s:4:"𐐵";s:4:"𐐎";s:4:"𐐶";s:4:"𐐏";s:4:"𐐷";s:4:"𐐐";s:4:"𐐸";s:4:"𐐑";s:4:"𐐹";s:4:"𐐒";s:4:"𐐺";s:4:"𐐓";s:4:"𐐻";s:4:"𐐔";s:4:"𐐼";s:4:"𐐕";s:4:"𐐽";s:4:"𐐖";s:4:"𐐾";s:4:"𐐗";s:4:"𐐿";s:4:"𐐘";s:4:"𐑀";s:4:"𐐙";s:4:"𐑁";s:4:"𐐚";s:4:"𐑂";s:4:"𐐛";s:4:"𐑃";s:4:"𐐜";s:4:"𐑄";s:4:"𐐝";s:4:"𐑅";s:4:"𐐞";s:4:"𐑆";s:4:"𐐟";s:4:"𐑇";s:4:"𐐠";s:4:"𐑈";s:4:"𐐡";s:4:"𐑉";s:4:"𐐢";s:4:"𐑊";s:4:"𐐣";s:4:"𐑋";s:4:"𐐤";s:4:"𐑌";s:4:"𐐥";s:4:"𐑍";s:4:"𐐦";s:4:"𐑎";s:4:"𐐧";s:4:"𐑏";}}
\ No newline at end of file
index 76a6335..c8b4661 100644 (file)
@@ -105,6 +105,7 @@ $wgAutoloadClasses += [
 
        # tests/phpunit/includes/specials
        'SpecialPageTestBase' => "$testDir/phpunit/includes/specials/SpecialPageTestBase.php",
+       'SpecialPageExecutor' => "$testDir/phpunit/includes/specials/SpecialPageExecutor.php",
 
        # tests/phpunit/languages
        'LanguageClassesTestCase' => "$testDir/phpunit/languages/LanguageClassesTestCase.php",
index bef8f50..a48087e 100644 (file)
Binary files a/tests/parser/extraParserTests.txt and b/tests/parser/extraParserTests.txt differ
index 9f45307..56108c9 100644 (file)
@@ -195,7 +195,7 @@ class ParserTest {
                        'transformVia404' => false,
                        'backend' => new FSFileBackend( [
                                'name' => 'local-backend',
-                               'wikiId' => wfWikiId(),
+                               'wikiId' => wfWikiID(),
                                'containerPaths' => [
                                        'local-public' => $this->uploadDir . '/public',
                                        'local-thumb' => $this->uploadDir . '/thumb',
@@ -619,6 +619,7 @@ class ParserTest {
                        $titleText = 'Parser test';
                }
 
+               ObjectCache::getMainWANInstance()->clearProcessCache();
                $local = isset( $opts['local'] );
                $preprocessor = isset( $opts['preprocessor'] ) ? $opts['preprocessor'] : null;
                $parser = $this->getParser( $preprocessor );
@@ -849,7 +850,7 @@ class ParserTest {
                                'transformVia404' => false,
                                'backend' => new FSFileBackend( [
                                        'name' => 'local-backend',
-                                       'wikiId' => wfWikiId(),
+                                       'wikiId' => wfWikiID(),
                                        'containerPaths' => [
                                                'local-public' => $this->uploadDir,
                                                'local-thumb' => $this->uploadDir . '/thumb',
@@ -896,7 +897,6 @@ class ParserTest {
                        'wgExternalLinkTarget' => false,
                        'wgHtml5' => true,
                        'wgWellFormedXml' => true,
-                       'wgAllowMicrodataAttributes' => true,
                        'wgAdaptiveMessageCache' => true,
                        'wgDisableLangConversion' => false,
                        'wgDisableTitleConversion' => false,
index d01ebdf..23bdbde 100644 (file)
@@ -18,7 +18,6 @@
 # ill           add inter-language links
 #               (ignored by Parsoid, since it emits <link>s)
 # subpage       enable subpages (disabled by default)
-# noxml         don't check for XML well-formedness
 # title=[[XXX]] run test using article title XXX
 # language=XXX  set content language to XXX for this test
 # variant=XXX   set the variant of language for this test (eg zh-tw)
@@ -1541,9 +1540,9 @@ parsoid=html2wt
 <span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a }&quot;}},&quot;i&quot;:0}}]}" about="#mwt5"></span></p>
 !! wikitext
 {{echo|a [ b}}
-{{echo|a <nowiki>}}</nowiki> b}}
+{{echo|<nowiki>a }} b</nowiki>}}
 {{echo|<nowiki>a [[ b</nowiki>}}
-{{echo|a {{!}} <nowiki>{{ ]]</nowiki>}}
+{{echo|<nowiki>a | {{ ]]</nowiki>}}
 {{echo|a <nowiki>}</nowiki>}}
 !! end
 
@@ -2520,7 +2519,6 @@ Barack Obama <President> of the United States
 </p>
 !! end
 
-## PHP parser discards the "<pre " string
 !! test
 Handle broken pre-like tags (bug 64025)
 !! options
@@ -2531,8 +2529,13 @@ parsoid=wt2html
 <table><pre </table>
 !! html/php
 <pre>x</pre>
-<table><pre></pre></table>
+<table>&lt;pre </table>
 
+!! html/php+tidy
+<pre>
+x
+</pre>
+<p>&lt;pre</p>
 !! html/parsoid
 <pre about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"a":{"&lt;pre":null},"sa":{"&lt;pre":""},"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>x</pre>
 
@@ -4773,7 +4776,7 @@ External image
 !! wikitext
 External image: http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
 !! html
-<p>External image: <img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" />
+<p>External image: <img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png"/>
 </p>
 !! end
 
@@ -4782,7 +4785,7 @@ External image from https
 !! wikitext
 External image from https: https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
 !! html
-<p>External image from https: <img src="https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" />
+<p>External image from https: <img src="https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png"/>
 </p>
 !! end
 
@@ -4856,7 +4859,7 @@ External links: Clickable images
 !! wikitext
 ja-style clickable images: [http://example.com http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png]
 !! html/php
-<p>ja-style clickable images: <a rel="nofollow" class="external text" href="http://example.com"><img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" /></a>
+<p>ja-style clickable images: <a rel="nofollow" class="external text" href="http://example.com"><img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png"/></a>
 </p>
 !! html/parsoid
 <p>ja-style clickable images: <a rel="mw:ExtLink" href="http://example.com"><img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" data-parsoid='{"type":"extlink"}'/></a></p>
@@ -6330,6 +6333,24 @@ parsoid=wt2html,html2html
 <td data-parsoid='{"startTagSrc":"| ","attrSepSrc":"|","autoInsertedEnd":true}'><a rel="mw:ExtLink" href="ftp://|x||"></a>" onmouseover="alert(document.cookie)">test</td></tr></tbody></table>
 !! end
 
+!! test
+Element attributes with double ! should not be broken up by <th>
+!! wikitext
+{|
+! hi <div class="!!">ha</div> ho
+|}
+!! html/php
+<table>
+<tr>
+<th> hi <div class="!!">ha</div> ho
+</th></tr></table>
+
+!! html/parsoid
+<table>
+<tbody><tr><th> hi <div class="!!" data-parsoid='{"stx":"html"}'>ha</div> ho</th></tr>
+</tbody></table>
+!! end
+
 !! test
 ! and || in element attributes should not be parsed as <th>/<td>
 !! wikitext
@@ -6567,6 +6588,8 @@ Table with empty line following the start tag
 
 !! test
 Table attributes with empty value
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 {|
 | style=| hello
@@ -6579,11 +6602,8 @@ Table attributes with empty value
 
 !! html/parsoid
 <table>
-<tbody>
-<tr>
-<td style=""> hello
-</td></tr></tbody></table>
-
+<tbody><tr><td style=""> hello</td></tr>
+</tbody></table>
 !! end
 
 !! test
@@ -10272,7 +10292,7 @@ Template with just whitespace in it, bug #68421
 !! wikitext
 {{echo|{{ }}}}
 !! html/parsoid
-<p><span typeof="mw:Transclusion mw:Nowiki" about="#mwt1" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{ }}"}},"i":0}}]}'>{{ }}</span></p>
+<p about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{ }}"}},"i":0}}]}'>{{ }}</p>
 !! end
 
 !! article
@@ -10509,6 +10529,7 @@ Abort table cell attribute parsing on wikilink
 {|
 | testing [[one|two]] | three || four
 | testing one two | three || four
+| testing="[[one|two]]" | three || four
 |}
 !! html/php
 <table>
@@ -10518,12 +10539,16 @@ Abort table cell attribute parsing on wikilink
 </td>
 <td> three </td>
 <td> four
+</td>
+<td> testing="<a href="/index.php?title=One&amp;action=edit&amp;redlink=1" class="new" title="One (page does not exist)">two</a>" | three </td>
+<td> four
 </td></tr></table>
 
 !! html/parsoid
 <table>
 <tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'> testing <a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"piped","a":{"href":"./One"},"sa":{"href":"one"}}'>two</a> | three </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> four</td>
-<td data-parsoid='{"a":{"testing":null,"one":null,"two":null},"sa":{"testing":"","one":"","two":""},"autoInsertedEnd":true}'> three </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> four</td></tr>
+<td data-parsoid='{"a":{"testing":null,"one":null,"two":null},"sa":{"testing":"","one":"","two":""},"autoInsertedEnd":true}'> three </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> four</td>
+<td> testing="<a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"piped","a":{"href":"./One"},"sa":{"href":"one"}}'>two</a>" | three </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> four</td></tr>
 </tbody></table>
 !! end
 
@@ -12163,7 +12188,7 @@ This template has <!-- a comment --> in it.
 !! test
 pre-save transform: unclosed tag
 !! options
-pst noxml
+pst
 !! wikitext
 <nowiki>'''not wiki'''
 !! html/php
@@ -12173,7 +12198,7 @@ pst noxml
 !! test
 pre-save transform: mixed tag case
 !! options
-pst noxml
+pst
 !! wikitext
 <NOwiki>'''not wiki'''</noWIKI>
 !! html/php
@@ -12183,7 +12208,7 @@ pst noxml
 !! test
 pre-save transform: unclosed comment in <nowiki>
 !! options
-pst noxml
+pst
 !! wikitext
 wiki<nowiki>nowiki<!--nowiki</nowiki>wiki
 !! html/php
@@ -13839,6 +13864,17 @@ language=es
 <figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
 !! end
 
+!! test
+Localized image handling (3).
+!! options
+language=fa
+parsoid=html2wt
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></figure>
+!! wikitext
+[[File:Foobar.jpg|بندانگشتی]]
+!! end
+
 !! test
 "border", "frameless" and "class" attributes on an image.
 !! options
@@ -15471,14 +15507,17 @@ div with illegal double attributes
 
 !! test
 div with empty attribute value, space before equals
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 <div class =>HTML rocks</div>
-!! html
+!! html/php
 <div class="">HTML rocks</div>
 
+!! html/parsoid
+<div class="" data-parsoid='{"stx":"html"}'>HTML rocks</div>
 !! end
 
-# FIXME: Parsoid doesn't match the html5 spec
 !! test
 div with multiple empty attribute values
 !! options
@@ -15489,10 +15528,9 @@ parsoid=wt2html,html2html
 <div id="title.3D">HTML rocks</div>
 
 !! html/parsoid
-<div id="" title="">HTML rocks</div>
+<div id="title=" data-parsoid='{"stx":"html"}'>HTML rocks</div>
 !! end
 
-# FIXME: Parsoid doesn't match the html5 spec
 !! test
 table with multiple empty attribute values
 !! options
@@ -15508,7 +15546,7 @@ parsoid=wt2html,html2html
 </td></tr></table>
 
 !! html/parsoid
-<table title="" id="">
+<table title="id=">
 <tbody><tr><td> hi</td></tr>
 </tbody></table>
 !! end
@@ -15850,20 +15888,28 @@ Empty attribute crash test single-quotes (bug 2067)
 
 !! test
 Attribute test: equals, then nothing
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 <font color=>foo</font>
-!! html
+!! html/php
 <p><font color="">foo</font>
 </p>
+!! html/parsoid
+<p><font color="" data-parsoid='{"stx":"html"}'>foo</font></p>
 !! end
 
 !! test
 Attribute test: unquoted value
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 <font color=x>foo</font>
-!! html
+!! html/php
 <p><font color="x">foo</font>
 </p>
+!! html/parsoid
+<p><font color="x" data-parsoid='{"stx":"html"}'>foo</font></p>
 !! end
 
 !! test
@@ -16414,8 +16460,6 @@ array (
 
 !! test
 Parser hook: nested tags
-!! options
-noxml
 !! wikitext
 <tag><tag></tag></tag>
 !! html/php
@@ -17049,6 +17093,8 @@ http://<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
 
 !! test
 Fuzz testing: Parser14-table
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 ==a==
 {| STYLE=__TOC__
@@ -17065,13 +17111,14 @@ Fuzz testing: Parser14-table
 <td></td>
 </tr>
 </table>
+!! html/parsoid
+<h2>a</h2>
+<table style="__TOC__"></table>
 !! end
 
 # Known to produce bogus xml (extra </td>)
 !! test
 Fuzz testing: Parser16
-!! options
-noxml
 !! wikitext
 {|
 !https://||||||
@@ -17133,8 +17180,6 @@ http://===r:::https://b
 # Known to produce bad XML for now
 !! test
 Fuzz testing: Parser24
-!! options
-noxml
 !! wikitext
 {|
 {{{|
@@ -18199,7 +18244,7 @@ section=1
 !! test
 Section extraction, <pre> around bogus header (bug 10309)
 !! options
-noxml section=2
+section=2
 !! wikitext
 == Section One ==
 <pre>
@@ -18216,7 +18261,7 @@ stuff
 !! test
 Section replacement, <pre> around bogus header (bug 10309)
 !! options
-noxml replace=2,"xxx"
+replace=2,"xxx"
 !! wikitext
 == Section One ==
 <pre>
@@ -20862,7 +20907,7 @@ Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate external images links
 !! wikitext
 http://www.example.org/pic.png <-- U+3000 (vim: ^Vu3000)
 !! html
-<p><img src="http://www.example.org/pic.png" alt="pic.png" /> &lt;-- U+3000 (vim: ^Vu3000)
+<p><img src="http://www.example.org/pic.png" alt="pic.png"/> &lt;-- U+3000 (vim: ^Vu3000)
 </p>
 !! end
 
@@ -21771,7 +21816,7 @@ A <ref> foo {{echo|</ref> B C}}
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C<span typeof="mw:Nowiki">}}</span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C}}</p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
 <li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo {{echo|</span></li>
 </ol>
@@ -22114,8 +22159,8 @@ X{{echo|<ref>foo {{echo|<b>bar</b>}} and {{echo|baz}} boo</ref>}}
 
 # This test only works in wt2html now as the <references /> are always generated
 # unless selser is active. Once T72722 is fixed, we should add a changes test
-# here to ensure that unrelated changes don't add the new <references /> in
-# wt2wt.
+# here to ensure that unrelated changes don't add the new <references />
+# when selser is active.
 !! test
 References: 9. Generate missing references list at the end
 !! wikitext
@@ -22123,10 +22168,10 @@ A <ref>foo</ref>
 B <ref group="inexistent">bar</ref>
 !! html/parsoid
 <p>A <span class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B <span class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"inexistent"}}'><a href="#cite_note-2" data-mw-group="inexistent"><span class="mw-reflink-text">[inexistent 1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'>
 <li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
 </ol>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="inexistent" data-mw='{"name":"references","attrs":{"group":"inexistent"}}'>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="inexistent" data-mw='{"name":"references","attrs":{"group":"inexistent"},"autoGenerated":true}'>
 <li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" data-mw-group="inexistent" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
 </ol>
 !! end
@@ -24028,26 +24073,6 @@ parsoid=wt2html,html2html
 
 !! end
 
-!! test
-2. Parsoid-only: Don't wrap broken template tags in <nowiki> on wt2wt (Bug 42353)
-!! options
-parsoid
-!! wikitext
-{{}}
-!! html
-{{}}
-!! end
-
-!! test
-1. Parsoid-only: Don't wrap broken template tags in <nowiki> on wt2wt (Bug 42353)
-!! options
-parsoid
-!! wikitext
-}}{{
-!! html
-}}{{
-!! end
-
 !!test
 Accept empty td cell attribute
 !! wikitext
@@ -24664,7 +24689,7 @@ Don't block XML namespace declaration
 !! wikitext
 <span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">MediaWiki</span>
 !! html/php
-<p><span>MediaWiki</span>
+<p><span xmlns:dct="http&#58;//purl.org/dc/terms/" property="dct:title">MediaWiki</span>
 </p>
 !! html/parsoid
 <p><span xmlns:dct="http://purl.org/dc/terms/" data-x-property="dct:title" data-parsoid='{"stx":"html"}'>MediaWiki</span></p>
index 3bd5ed8..a99b4b9 100644 (file)
@@ -29,6 +29,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        public static $users;
 
        /**
+        * Primary database
+        *
         * @var DatabaseBase
         * @since 1.18
         */
@@ -132,14 +134,21 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        $this->checkDbIsSupported();
 
                        if ( !self::$dbSetup ) {
-                               // switch to a temporary clone of the database
-                               self::setupTestDB( $this->db, $this->dbPrefix() );
+                               $this->setupAllTestDBs();
+                               $this->addCoreDBData();
 
                                if ( ( $this->db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
-                                       $this->resetDB();
+                                       $this->resetDB( $this->db, $this->tablesUsed );
                                }
                        }
-                       $this->addCoreDBData();
+
+                       // TODO: the DB setup should be done in setUpBeforeClass(), so the test DB
+                       // is available in subclass's setUpBeforeClass() and setUp() methods.
+                       // This would also remove the need for the HACK that is oncePerClass().
+                       if ( $this->oncePerClass() ) {
+                               $this->addDBDataOnce();
+                       }
+
                        $this->addDBData();
                        $needsResetDB = true;
                }
@@ -147,10 +156,26 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                parent::run( $result );
 
                if ( $needsResetDB ) {
-                       $this->resetDB();
+                       $this->resetDB( $this->db, $this->tablesUsed );
                }
        }
 
+       /**
+        * @return bool
+        */
+       private function oncePerClass() {
+               // Remember current test class in the database connection,
+               // so we know when we need to run addData.
+
+               $class = static::class;
+
+               $first = !isset( $this->db->_hasDataForTestClass )
+                       || $this->db->_hasDataForTestClass !== $class;
+
+               $this->db->_hasDataForTestClass = $class;
+               return $first;
+       }
+
        /**
         * @since 1.21
         *
@@ -222,6 +247,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                }
 
                DeferredUpdates::clearPendingUpdates();
+               ObjectCache::getMainWANInstance()->clearProcessCache();
 
                ob_start( 'MediaWikiTestCase::wfResetOutputBuffersBarrier' );
        }
@@ -540,10 +566,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                $user = User::newFromName( 'UTSysop' );
                $comment = __METHOD__ . ': Sample page for unit test.';
 
-               // Avoid memory leak...?
-               // LinkCache::singleton()->clear();
-               // Maybe.  But doing this absolutely breaks $title->isRedirect() when called during unit tests....
-
                $page = WikiPage::factory( $title );
                $page->doEditContent( ContentHandler::makeContent( $text, $title ), $comment, 0, false, $user );
 
@@ -554,8 +576,29 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        }
 
        /**
-        * Stub. If a test needs to add additional data to the database, it should
-        * implement this method and do so
+        * Stub. If a test suite needs to add additional data to the database, it should
+        * implement this method and do so. This method is called once per test suite
+        * (i.e. once per class).
+        *
+        * Note data added by this method may be removed by resetDB() depending on
+        * the contents of $tablesUsed.
+        *
+        * To add additional data between test function runs, override prepareDB().
+        *
+        * @see addDBData()
+        * @see resetDB()
+        *
+        * @since 1.27
+        */
+       public function addDBDataOnce() {
+       }
+
+       /**
+        * Stub. Subclasses may override this to prepare the database.
+        * Called before every test run (test function or data set).
+        *
+        * @see addDBDataOnce()
+        * @see resetDB()
         *
         * @since 1.18
         */
@@ -645,6 +688,52 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                self::$dbSetup = false;
        }
 
+       /**
+        * Setups a database with the given prefix.
+        *
+        * If reuseDB is true and certain conditions apply, it will just change the prefix.
+        * Otherwise, it will clone the tables and change the prefix.
+        *
+        * Clones all tables in the given database (whatever database that connection has
+        * open), to versions with the test prefix.
+        *
+        * @param DatabaseBase $db Database to use
+        * @param string $prefix Prefix to use for test tables
+        * @return bool True if tables were cloned, false if only the prefix was changed
+        */
+       protected static function setupDatabaseWithTestPrefix( DatabaseBase $db, $prefix ) {
+               $tablesCloned = self::listTables( $db );
+               $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix );
+               $dbClone->useTemporaryTables( self::$useTemporaryTables );
+
+               if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
+                       CloneDatabase::changePrefix( $prefix );
+
+                       return false;
+               } else {
+                       $dbClone->cloneTableStructure();
+                       return true;
+               }
+       }
+
+       /**
+        * Set up all test DBs
+        */
+       public function setupAllTestDBs() {
+               global $wgDBprefix;
+
+               self::$oldTablePrefix = $wgDBprefix;
+
+               $testPrefix = $this->dbPrefix();
+
+               // switch to a temporary clone of the database
+               self::setupTestDB( $this->db, $testPrefix );
+
+               if ( self::isUsingExternalStoreDB() ) {
+                       self::setupExternalStoreTestDBs( $testPrefix );
+               }
+       }
+
        /**
         * Creates an empty skeleton of the wiki database by cloning its structure
         * to equivalent tables using the given $prefix. Then sets MediaWiki to
@@ -667,8 +756,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @throws MWException If the database table prefix is already $prefix
         */
        public static function setupTestDB( DatabaseBase $db, $prefix ) {
-               global $wgDBprefix;
-               if ( $wgDBprefix === $prefix ) {
+               if ( $db->tablePrefix() === $prefix ) {
                        throw new MWException(
                                'Cannot run unit tests, the database prefix is already "' . $prefix . '"' );
                }
@@ -677,49 +765,110 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        return;
                }
 
-               $tablesCloned = self::listTables( $db );
-               $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix );
-               $dbClone->useTemporaryTables( self::$useTemporaryTables );
-
                self::$dbSetup = true;
-               self::$oldTablePrefix = $wgDBprefix;
-
-               if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
-                       CloneDatabase::changePrefix( $prefix );
 
+               if ( !self::setupDatabaseWithTestPrefix( $db, $prefix ) ) {
                        return;
-               } else {
-                       $dbClone->cloneTableStructure();
                }
 
+               // Assuming this isn't needed for External Store database, and not sure if the procedure
+               // would be available there.
                if ( $db->getType() == 'oracle' ) {
                        $db->query( 'BEGIN FILL_WIKI_INFO; END;' );
                }
        }
 
+       /**
+        * Clones the External Store database(s) for testing
+        *
+        * @param string $testPrefix Prefix for test tables
+        */
+       protected static function setupExternalStoreTestDBs( $testPrefix ) {
+               $connections = self::getExternalStoreDatabaseConnections();
+               foreach ( $connections as $dbw ) {
+                       // Hack: cloneTableStructure sets $wgDBprefix to the unit test
+                       // prefix,.  Even though listTables now uses tablePrefix, that
+                       // itself is populated from $wgDBprefix by default.
+
+                       // We have to set it back, or we won't find the original 'blobs'
+                       // table to copy.
+
+                       $dbw->tablePrefix( self::$oldTablePrefix );
+                       self::setupDatabaseWithTestPrefix( $dbw, $testPrefix );
+               }
+       }
+
+       /**
+        * Gets master database connections for all of the ExternalStoreDB
+        * stores configured in $wgDefaultExternalStore.
+        *
+        * @return array Array of DatabaseBase master connections
+        */
+
+       protected static function getExternalStoreDatabaseConnections() {
+               global $wgDefaultExternalStore;
+
+               $externalStoreDB = ExternalStore::getStoreObject( 'DB' );
+               $defaultArray = (array) $wgDefaultExternalStore;
+               $dbws = [];
+               foreach ( $defaultArray as $url ) {
+                       if ( strpos( $url, 'DB://' ) === 0 ) {
+                               list( $proto, $cluster ) = explode( '://', $url, 2 );
+                               $dbw = $externalStoreDB->getMaster( $cluster );
+                               $dbws[] = $dbw;
+                       }
+               }
+
+               return $dbws;
+       }
+
+       /**
+        * Check whether ExternalStoreDB is being used
+        *
+        * @return bool True if it's being used
+        */
+       protected static function isUsingExternalStoreDB() {
+               global $wgDefaultExternalStore;
+               if ( !$wgDefaultExternalStore ) {
+                       return false;
+               }
+
+               $defaultArray = (array) $wgDefaultExternalStore;
+               foreach ( $defaultArray as $url ) {
+                       if ( strpos( $url, 'DB://' ) === 0 ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
        /**
         * Empty all tables so they can be repopulated for tests
+        *
+        * @param DatabaseBase $db|null Database to reset
+        * @param array $tablesUsed Tables to reset
         */
-       private function resetDB() {
-               if ( $this->db ) {
-                       if ( $this->db->getType() == 'oracle' ) {
-                               if ( self::$useTemporaryTables ) {
-                                       wfGetLB()->closeAll();
-                                       $this->db = wfGetDB( DB_MASTER );
+       private function resetDB( $db, $tablesUsed ) {
+               if ( $db ) {
+                       $truncate = in_array( $db->getType(), [ 'oracle', 'mysql' ] );
+                       foreach ( $tablesUsed as $tbl ) {
+                               // TODO: reset interwiki and user tables to their original content.
+                               if ( $tbl == 'interwiki' || $tbl == 'user' ) {
+                                       continue;
+                               }
+
+                               if ( $truncate ) {
+                                       $db->query( 'TRUNCATE TABLE ' . $db->tableName( $tbl ), __METHOD__ );
                                } else {
-                                       foreach ( $this->tablesUsed as $tbl ) {
-                                               if ( $tbl == 'interwiki' ) {
-                                                       continue;
-                                               }
-                                               $this->db->query( 'TRUNCATE TABLE ' . $this->db->tableName( $tbl ), __METHOD__ );
-                                       }
+
+                                       $db->delete( $tbl, '*', __METHOD__ );
                                }
-                       } else {
-                               foreach ( $this->tablesUsed as $tbl ) {
-                                       if ( $tbl == 'interwiki' || $tbl == 'user' ) {
-                                               continue;
-                                       }
-                                       $this->db->delete( $tbl, '*', __METHOD__ );
+
+                               if ( $tbl === 'page' ) {
+                                       // Forget about the pages since they don't
+                                       // exist in the DB.
+                                       LinkCache::singleton()->clear();
                                }
                        }
                }
@@ -756,10 +905,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                $this->assertTrue( $value == '', $msg );
        }
 
-       private static function unprefixTable( $tableName ) {
-               global $wgDBprefix;
-
-               return substr( $tableName, strlen( $wgDBprefix ) );
+       private static function unprefixTable( &$tableName, $ind, $prefix ) {
+               $tableName = substr( $tableName, strlen( $prefix ) );
        }
 
        private static function isNotUnittest( $table ) {
@@ -774,16 +921,15 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @return array
         */
        public static function listTables( $db ) {
-               global $wgDBprefix;
-
-               $tables = $db->listTables( $wgDBprefix, __METHOD__ );
+               $prefix = $db->tablePrefix();
+               $tables = $db->listTables( $prefix, __METHOD__ );
 
                if ( $db->getType() === 'mysql' ) {
                        # bug 43571: cannot clone VIEWs under MySQL
-                       $views = $db->listViews( $wgDBprefix, __METHOD__ );
+                       $views = $db->listViews( $prefix, __METHOD__ );
                        $tables = array_diff( $tables, $views );
                }
-               $tables = array_map( [ __CLASS__, 'unprefixTable' ], $tables );
+               array_walk( $tables, [ __CLASS__, 'unprefixTable' ], $prefix );
 
                // Don't duplicate test tables from the previous fataled run
                $tables = array_filter( $tables, [ __CLASS__, 'isNotUnittest' ] );
@@ -1176,33 +1322,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                return $loaded;
        }
 
-       /**
-        * Asserts that an exception of the specified type occurs when running
-        * the provided code.
-        *
-        * @since 1.21
-        * @deprecated since 1.22 Use setExpectedException
-        *
-        * @param callable $code
-        * @param string $expected
-        * @param string $message
-        */
-       protected function assertException( $code, $expected = 'Exception', $message = '' ) {
-               $pokemons = null;
-
-               try {
-                       call_user_func( $code );
-               } catch ( Exception $pokemons ) {
-                       // Gotta Catch 'Em All!
-               }
-
-               if ( $message === '' ) {
-                       $message = 'An exception of type "' . $expected . '" should have been thrown';
-               }
-
-               $this->assertInstanceOf( $expected, $pokemons, $message );
-       }
-
        /**
         * Asserts that the given string is a valid HTML snippet.
         * Wraps the given string in the required top level tags and
@@ -1310,4 +1429,5 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        public static function wfResetOutputBuffersBarrier( $buffer ) {
                return $buffer;
        }
+
 }
index e14960a..9f38659 100644 (file)
@@ -14,9 +14,8 @@ class BlockTest extends MediaWikiLangTestCase {
        private $blockId;
 
        function addDBData() {
-
                $user = User::newFromName( 'UTBlockee' );
-               if ( $user->getID() == 0 ) {
+               if ( $user->getId() == 0 ) {
                        $user->addToDatabase();
                        TestUser::setPasswordForUser( $user, 'UTBlockeePassword' );
 
@@ -32,7 +31,7 @@ class BlockTest extends MediaWikiLangTestCase {
 
                $blockOptions = [
                        'address' => 'UTBlockee',
-                       'user' => $user->getID(),
+                       'user' => $user->getId(),
                        'reason' => 'Parce que',
                        'expiry' => time() + 100500,
                ];
@@ -366,7 +365,7 @@ class BlockTest extends MediaWikiLangTestCase {
 
                # Set up the target
                $u = User::newFromName( $username );
-               if ( $u->getID() == 0 ) {
+               if ( $u->getId() == 0 ) {
                        $u->addToDatabase();
                        TestUser::setPasswordForUser( $u, 'TotallyObvious' );
                }
diff --git a/tests/phpunit/includes/FallbackTest.php b/tests/phpunit/includes/FallbackTest.php
deleted file mode 100644 (file)
index 85732dd..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-/**
- * @covers Fallback
- */
-class FallbackTest extends MediaWikiTestCase {
-       public function testFallbackMbstringFunctions() {
-               if ( !extension_loaded( 'mbstring' ) ) {
-                       $this->markTestSkipped(
-                               "The mb_string functions must be installed to test the fallback functions"
-                       );
-               }
-
-               $sampleUTF = "Östergötland_coat_of_arms.png";
-
-               // mb_substr
-               $substr_params = [
-                       [ 0, 0 ],
-                       [ 5, -4 ],
-                       [ 33 ],
-                       [ 100, -5 ],
-                       [ -8, 10 ],
-                       [ 1, 1 ],
-                       [ 2, -1 ]
-               ];
-
-               foreach ( $substr_params as $param_set ) {
-                       $old_param_set = $param_set;
-                       array_unshift( $param_set, $sampleUTF );
-
-                       $this->assertEquals(
-                               call_user_func_array( 'mb_substr', $param_set ),
-                               call_user_func_array( 'Fallback::mb_substr', $param_set ),
-                               'Fallback mb_substr with params ' . implode( ', ', $old_param_set )
-                       );
-               }
-
-               // mb_strlen
-               $this->assertEquals(
-                       mb_strlen( $sampleUTF ),
-                       Fallback::mb_strlen( $sampleUTF ),
-                       'Fallback mb_strlen'
-               );
-
-               // mb_str(r?)pos
-               $strpos_params = [
-                       // array( 'ter' ),
-                       // array( 'Ö' ),
-                       // array( 'Ö', 3 ),
-                       // array( 'oat_', 100 ),
-                       // array( 'c', -10 ),
-                       // Broken for now
-               ];
-
-               foreach ( $strpos_params as $param_set ) {
-                       $old_param_set = $param_set;
-                       array_unshift( $param_set, $sampleUTF );
-
-                       $this->assertEquals(
-                               call_user_func_array( 'mb_strpos', $param_set ),
-                               call_user_func_array( 'Fallback::mb_strpos', $param_set ),
-                               'Fallback mb_strpos with params ' . implode( ', ', $old_param_set )
-                       );
-
-                       $this->assertEquals(
-                               call_user_func_array( 'mb_strrpos', $param_set ),
-                               call_user_func_array( 'Fallback::mb_strrpos', $param_set ),
-                               'Fallback mb_strrpos with params ' . implode( ', ', $old_param_set )
-                       );
-               }
-       }
-}
index 85ac4ce..eac56fb 100644 (file)
@@ -69,33 +69,33 @@ class FauxResponseTest extends MediaWikiTestCase {
         * @covers FauxResponse::header
         */
        public function testHeader() {
-               $this->assertEquals( null, $this->response->getheader( 'Location' ), 'Non-existing header' );
+               $this->assertEquals( null, $this->response->getHeader( 'Location' ), 'Non-existing header' );
 
                $this->response->header( 'Location: http://localhost/' );
                $this->assertEquals(
                        'http://localhost/',
-                       $this->response->getheader( 'Location' ),
+                       $this->response->getHeader( 'Location' ),
                        'Set header'
                );
 
                $this->response->header( 'Location: http://127.0.0.1/' );
                $this->assertEquals(
                        'http://127.0.0.1/',
-                       $this->response->getheader( 'Location' ),
+                       $this->response->getHeader( 'Location' ),
                        'Same header'
                );
 
                $this->response->header( 'Location: http://127.0.0.2/', false );
                $this->assertEquals(
                        'http://127.0.0.1/',
-                       $this->response->getheader( 'Location' ),
+                       $this->response->getHeader( 'Location' ),
                        'Same header with override disabled'
                );
 
                $this->response->header( 'Location: http://localhost/' );
                $this->assertEquals(
                        'http://localhost/',
-                       $this->response->getheader( 'LOCATION' ),
+                       $this->response->getHeader( 'LOCATION' ),
                        'Get header case insensitive'
                );
        }
index a90295a..6c92b8c 100644 (file)
@@ -8,6 +8,7 @@ class HtmlTest extends MediaWikiTestCase {
 
                $this->setMwGlobals( [
                        'wgWellFormedXml' => false,
+                       'wgUseMediaWikiUIEverywhere' => false,
                ] );
 
                $langObj = Language::factory( 'en' );
@@ -64,7 +65,7 @@ class HtmlTest extends MediaWikiTestCase {
                $this->setMwGlobals( 'wgWellFormedXml', true );
 
                $this->assertEquals(
-                       '<img />',
+                       '<img/>',
                        Html::element( 'img', null, '' ),
                        'Self-closing tag for short-tag elements (wgWellFormedXml = true)'
                );
index f380696..4c2e02b 100644 (file)
@@ -62,6 +62,17 @@ class HttpTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers Http::getProxy
+        */
+       public function testGetProxy() {
+               $this->setMwGlobals( 'wgHTTPProxy', 'proxy.domain.tld' );
+               $this->assertEquals(
+                       'proxy.domain.tld',
+                       Http::getProxy()
+               );
+       }
+
        /**
         * Feeds URI to test a long regular expression in Http::isValidURI
         */
index 8248257..e50b4f1 100644 (file)
@@ -132,129 +132,129 @@ class LinkerTest extends MediaWikiLangTestCase {
                $wikiId = 'enwiki'; // $wgConf has a fake entry for this
 
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
+               return [
                        // Linker::formatComment
-                       array(
+                       [
                                'a&lt;script&gt;b',
                                'a<script>b',
-                       ),
-                       array(
+                       ],
+                       [
                                'a—b',
                                'a&mdash;b',
-                       ),
-                       array(
+                       ],
+                       [
                                "&#039;&#039;&#039;not bolded&#039;&#039;&#039;",
                                "'''not bolded'''",
-                       ),
-                       array(
+                       ],
+                       [
                                "try &lt;script&gt;evil&lt;/scipt&gt; things",
                                "try <script>evil</scipt> things",
-                       ),
+                       ],
                        // Linker::formatAutocomments
-                       array(
+                       [
                                '<a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
                                "/* autocomment */",
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="/wiki/Special:BlankPage#linkie.3F" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment"><a href="/wiki/index.php?title=Linkie%3F&amp;action=edit&amp;redlink=1" class="new" title="Linkie? (page does not exist)">linkie?</a></span></span>',
                                "/* [[linkie?]] */",
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment: </span> post</span>',
                                "/* autocomment */ post",
-                       ),
-                       array(
+                       ],
+                       [
                                'pre <a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
                                "pre /* autocomment */",
-                       ),
-                       array(
+                       ],
+                       [
                                'pre <a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment: </span> post</span>',
                                "pre /* autocomment */ post",
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment: </span> multiple? <a href="/wiki/Special:BlankPage#autocomment2" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment2: </span> </span></span>',
                                "/* autocomment */ multiple? /* autocomment2 */ ",
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="/wiki/Special:BlankPage#autocomment_containing_.2F.2A" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment containing /*: </span> T70361</span>',
                                "/* autocomment containing /* */ T70361"
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="/wiki/Special:BlankPage#autocomment_containing_.22quotes.22" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment containing &quot;quotes&quot;</span></span>',
                                "/* autocomment containing \"quotes\" */"
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="/wiki/Special:BlankPage#autocomment_containing_.3Cscript.3Etags.3C.2Fscript.3E" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment containing &lt;script&gt;tags&lt;/script&gt;</span></span>',
                                "/* autocomment containing <script>tags</script> */"
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="#autocomment">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
                                "/* autocomment */",
                                false, true
-                       ),
-                       array(
+                       ],
+                       [
                                '‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
                                "/* autocomment */",
                                null
-                       ),
-                       array(
+                       ],
+                       [
                                '<a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
                                "/* autocomment */",
                                false, false
-                       ),
-                       array(
+                       ],
+                       [
                                '<a class="external" rel="nofollow" href="//en.example.org/w/Special:BlankPage#autocomment">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
                                "/* autocomment */",
                                false, false, $wikiId
-                       ),
+                       ],
                        // Linker::formatLinksInComment
-                       array(
+                       [
                                'abc <a href="/wiki/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">link</a> def',
                                "abc [[link]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a href="/wiki/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">text</a> def',
                                "abc [[link|text]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a> def',
                                "abc [[Special:BlankPage|]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a href="/wiki/index.php?title=%C4%84%C5%9B%C5%BC&amp;action=edit&amp;redlink=1" class="new" title="Ąśż (page does not exist)">ąśż</a> def',
                                "abc [[%C4%85%C5%9B%C5%BC]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a href="/wiki/Special:BlankPage#section" title="Special:BlankPage">#section</a> def',
                                "abc [[#section]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a href="/wiki/index.php?title=/subpage&amp;action=edit&amp;redlink=1" class="new" title="/subpage (page does not exist)">/subpage</a> def',
                                "abc [[/subpage]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a href="/wiki/index.php?title=%22evil!%22&amp;action=edit&amp;redlink=1" class="new" title="&quot;evil!&quot; (page does not exist)">&quot;evil!&quot;</a> def',
                                "abc [[\"evil!\"]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc [[&lt;script&gt;very evil&lt;/script&gt;]] def',
                                "abc [[<script>very evil</script>]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc [[|]] def',
                                "abc [[|]] def",
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a href="/wiki/index.php?title=Link&amp;action=edit&amp;redlink=1" class="new" title="Link (page does not exist)">link</a> def',
                                "abc [[link]] def",
                                false, false
-                       ),
-                       array(
+                       ],
+                       [
                                'abc <a class="external" rel="nofollow" href="//en.example.org/w/Link">link</a> def',
                                "abc [[link]] def",
                                false, false, $wikiId
-                       )
-               );
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
@@ -290,23 +290,23 @@ class LinkerTest extends MediaWikiLangTestCase {
 
        public static function provideCasesForFormatLinksInComment() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array(
+               return [
+                       [
                                'foo bar <a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>',
                                'foo bar [[Special:BlankPage]]',
                                null,
-                       ),
-                       array(
+                       ],
+                       [
                                '<a class="external" rel="nofollow" href="//en.example.org/w/Foo%27bar">Foo\'bar</a>',
                                "[[Foo'bar]]",
                                'enwiki',
-                       ),
-                       array(
+                       ],
+                       [
                                'foo bar <a class="external" rel="nofollow" href="//en.example.org/w/Special:BlankPage">Special:BlankPage</a>',
                                'foo bar [[Special:BlankPage]]',
                                'enwiki',
-                       ),
-               );
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 }
diff --git a/tests/phpunit/includes/MediaWikiServicesTest.php b/tests/phpunit/includes/MediaWikiServicesTest.php
new file mode 100644 (file)
index 0000000..127f869
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+use MediaWiki\MediaWikiServices;
+
+/**
+ * @covers MediaWiki\MediaWikiServices
+ *
+ * @group MediaWiki
+ */
+class MediaWikiServicesTest extends PHPUnit_Framework_TestCase {
+
+       public function testGetInstance() {
+               $services = MediaWikiServices::getInstance();
+               $this->assertInstanceOf( 'MediaWiki\\MediaWikiServices', $services );
+       }
+
+       public function provideGetters() {
+               // NOTE: This should list all service getters defined in MediaWikiServices.
+               // NOTE: For every test case defined here there should be a corresponding
+               // test case defined in provideGetService().
+               return [
+                       'BootstrapConfig' => [ 'getBootstrapConfig', Config::class ],
+                       'ConfigFactory' => [ 'getConfigFactory', ConfigFactory::class ],
+                       'MainConfig' => [ 'getMainConfig', Config::class ],
+                       'SiteStore' => [ 'getSiteStore', SiteStore::class ],
+                       'SiteLookup' => [ 'getSiteLookup', SiteLookup::class ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideGetters
+        */
+       public function testGetters( $getter, $type ) {
+               // Test against the default instance, since the dummy will not know the default services.
+               $services = MediaWikiServices::getInstance();
+               $service = $services->$getter();
+               $this->assertInstanceOf( $type, $service );
+       }
+
+       public function provideGetService() {
+               // NOTE: This should list all service getters defined in ServiceWiring.php.
+               // NOTE: For every test case defined here there should be a corresponding
+               // test case defined in provideGetters().
+               return [
+                       'BootstrapConfig' => [ 'BootstrapConfig', Config::class ],
+                       'ConfigFactory' => [ 'ConfigFactory', ConfigFactory::class ],
+                       'MainConfig' => [ 'MainConfig', Config::class ],
+                       'SiteStore' => [ 'SiteStore', SiteStore::class ],
+                       'SiteLookup' => [ 'SiteLookup', SiteLookup::class ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideGetService
+        */
+       public function testGetService( $name, $type ) {
+               // Test against the default instance, since the dummy will not know the default services.
+               $services = MediaWikiServices::getInstance();
+
+               $service = $services->getService( $name );
+               $this->assertInstanceOf( $type, $service );
+       }
+
+       public function testDefaultServiceInstantiation() {
+               // Check all services in the default instance, not a dummy instance!
+               // Note that we instantiate all services here, including any that
+               // were registered by extensions.
+               $services = MediaWikiServices::getInstance();
+               $names = $services->getServiceNames();
+
+               foreach ( $names as $name ) {
+                       $this->assertTrue( $services->hasService( $name ) );
+                       $service = $services->getService( $name );
+                       $this->assertInternalType( 'object', $service );
+               }
+       }
+
+}
index 951cf8d..5ea0cdf 100644 (file)
@@ -8,7 +8,7 @@ class MergeHistoryTest extends MediaWikiTestCase {
        /**
         * Make some pages to work with
         */
-       public function addDBData() {
+       public function addDBDataOnce() {
                // Pages that won't actually be merged
                $this->insertPage( 'Test' );
                $this->insertPage( 'Test2' );
index d404ab8..2f63ca8 100644 (file)
@@ -138,62 +138,62 @@ class OutputPageTest extends MediaWikiTestCase {
 
        public static function provideMakeResourceLoaderLink() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
+               return [
                        // Load module script only
-                       array(
-                               array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
+                       [
+                               [ 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ],
+                               "<script>(window.RLQ=window.RLQ||[]).push(function(){"
                                        . 'mw.loader.load("http://127.0.0.1:8080/w/load.php?debug=false\u0026lang=en\u0026modules=test.foo\u0026only=scripts\u0026skin=fallback");'
-                                       . "\n} );</script>"
-                       ),
-                       array(
+                                       . "});</script>"
+                       ],
+                       [
                                // Don't condition wrap raw modules (like the startup module)
-                               array( 'test.raw', ResourceLoaderModule::TYPE_SCRIPTS ),
+                               [ 'test.raw', ResourceLoaderModule::TYPE_SCRIPTS ],
                                '<script async src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.raw&amp;only=scripts&amp;skin=fallback"></script>'
-                       ),
+                       ],
                        // Load module styles only
                        // This also tests the order the modules are put into the url
-                       array(
-                               array( array( 'test.baz', 'test.foo', 'test.bar' ), ResourceLoaderModule::TYPE_STYLES ),
+                       [
+                               [ [ 'test.baz', 'test.foo', 'test.bar' ], ResourceLoaderModule::TYPE_STYLES ],
 
                                '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.bar%2Cbaz%2Cfoo&amp;only=styles&amp;skin=fallback">'
-                       ),
+                       ],
                        // Load private module (only=scripts)
-                       array(
-                               array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
-                                       . "mw.test.baz({token:123});mw.loader.state({\"test.quux\":\"ready\"});\n"
-                                       . "} );</script>"
-                       ),
+                       [
+                               [ 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ],
+                               "<script>(window.RLQ=window.RLQ||[]).push(function(){"
+                                       . "mw.test.baz({token:123});mw.loader.state({\"test.quux\":\"ready\"});"
+                                       . "});</script>"
+                       ],
                        // Load private module (combined)
-                       array(
-                               array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
-                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
+                       [
+                               [ 'test.quux', ResourceLoaderModule::TYPE_COMBINED ],
+                               "<script>(window.RLQ=window.RLQ||[]).push(function(){"
                                        . "mw.loader.implement(\"test.quux\",function($,jQuery){"
                                        . "mw.test.baz({token:123});},{\"css\":[\".mw-icon{transition:none}"
-                                       . "\"]});\n} );</script>"
-                       ),
+                                       . "\"]});});</script>"
+                       ],
                        // Load no modules
-                       array(
-                               array( array(), ResourceLoaderModule::TYPE_COMBINED ),
+                       [
+                               [ [], ResourceLoaderModule::TYPE_COMBINED ],
                                '',
-                       ),
+                       ],
                        // noscript group
-                       array(
-                               array( 'test.noscript', ResourceLoaderModule::TYPE_STYLES ),
+                       [
+                               [ 'test.noscript', ResourceLoaderModule::TYPE_STYLES ],
                                '<noscript><link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.noscript&amp;only=styles&amp;skin=fallback"></noscript>'
-                       ),
+                       ],
                        // Load two modules in separate groups
-                       array(
-                               array( array( 'test.group.foo', 'test.group.bar' ), ResourceLoaderModule::TYPE_COMBINED ),
-                               "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
+                       [
+                               [ [ 'test.group.foo', 'test.group.bar' ], ResourceLoaderModule::TYPE_COMBINED ],
+                               "<script>(window.RLQ=window.RLQ||[]).push(function(){"
                                        . 'mw.loader.load("http://127.0.0.1:8080/w/load.php?debug=false\u0026lang=en\u0026modules=test.group.bar\u0026skin=fallback");'
-                                       . "\n} );</script>\n"
-                                       . "<script>(window.RLQ = window.RLQ || []).push(function () {\n"
+                                       . "});</script>\n"
+                                       . "<script>(window.RLQ=window.RLQ||[]).push(function(){"
                                        . 'mw.loader.load("http://127.0.0.1:8080/w/load.php?debug=false\u0026lang=en\u0026modules=test.group.foo\u0026skin=fallback");'
-                                       . "\n} );</script>"
-                       ),
-               );
+                                       . "});</script>"
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index d5f5420..67364cb 100644 (file)
@@ -237,8 +237,13 @@ class PathRouterTest extends MediaWikiTestCase {
         */
        public function testLength() {
                // @codingStandardsIgnoreStart Ignore long line warnings
-               $matches = $this->basicRouter->parse( "/wiki/Lorem_ipsum_dolor_sit_amet,_consectetur_adipisicing_elit,_sed_do_eiusmod_tempor_incididunt_ut_labore_et_dolore_magna_aliqua._Ut_enim_ad_minim_veniam,_quis_nostrud_exercitation_ullamco_laboris_nisi_ut_aliquip_ex_ea_commodo_consequat._Duis_aute_irure_dolor_in_reprehenderit_in_voluptate_velit_esse_cillum_dolore_eu_fugiat_nulla_pariatur._Excepteur_sint_occaecat_cupidatat_non_proident,_sunt_in_culpa_qui_officia_deserunt_mollit_anim_id_est_laborum." );
-               $this->assertEquals( $matches, array( 'title' => "Lorem_ipsum_dolor_sit_amet,_consectetur_adipisicing_elit,_sed_do_eiusmod_tempor_incididunt_ut_labore_et_dolore_magna_aliqua._Ut_enim_ad_minim_veniam,_quis_nostrud_exercitation_ullamco_laboris_nisi_ut_aliquip_ex_ea_commodo_consequat._Duis_aute_irure_dolor_in_reprehenderit_in_voluptate_velit_esse_cillum_dolore_eu_fugiat_nulla_pariatur._Excepteur_sint_occaecat_cupidatat_non_proident,_sunt_in_culpa_qui_officia_deserunt_mollit_anim_id_est_laborum." ) );
+               $matches = $this->basicRouter->parse(
+                       "/wiki/Lorem_ipsum_dolor_sit_amet,_consectetur_adipisicing_elit,_sed_do_eiusmod_tempor_incididunt_ut_labore_et_dolore_magna_aliqua._Ut_enim_ad_minim_veniam,_quis_nostrud_exercitation_ullamco_laboris_nisi_ut_aliquip_ex_ea_commodo_consequat._Duis_aute_irure_dolor_in_reprehenderit_in_voluptate_velit_esse_cillum_dolore_eu_fugiat_nulla_pariatur._Excepteur_sint_occaecat_cupidatat_non_proident,_sunt_in_culpa_qui_officia_deserunt_mollit_anim_id_est_laborum."
+               );
+               $this->assertEquals(
+                       $matches,
+                       [ 'title' => "Lorem_ipsum_dolor_sit_amet,_consectetur_adipisicing_elit,_sed_do_eiusmod_tempor_incididunt_ut_labore_et_dolore_magna_aliqua._Ut_enim_ad_minim_veniam,_quis_nostrud_exercitation_ullamco_laboris_nisi_ut_aliquip_ex_ea_commodo_consequat._Duis_aute_irure_dolor_in_reprehenderit_in_voluptate_velit_esse_cillum_dolore_eu_fugiat_nulla_pariatur._Excepteur_sint_occaecat_cupidatat_non_proident,_sunt_in_culpa_qui_officia_deserunt_mollit_anim_id_est_laborum." ]
+               );
                // @codingStandardsIgnoreEnd
        }
 
index 6f4c300..6d5154f 100644 (file)
@@ -5,7 +5,7 @@
  */
 class PrefixSearchTest extends MediaWikiLangTestCase {
 
-       public function addDBData() {
+       public function addDBDataOnce() {
                if ( !$this->isWikitextNS( NS_MAIN ) ) {
                        // tests are skipped if NS_MAIN is not wikitext
                        return;
index 16d8c97..7d3007b 100644 (file)
@@ -57,6 +57,8 @@ class RevisionStorageTest extends MediaWikiTestCase {
                                CONTENT_MODEL_WIKITEXT
                        );
                }
+
+               $this->tablesUsed[] = 'archive';
        }
 
        protected function tearDown() {
@@ -93,7 +95,7 @@ class RevisionStorageTest extends MediaWikiTestCase {
 
                $rev = new Revision( $props );
 
-               $dbw = wfgetDB( DB_MASTER );
+               $dbw = wfGetDB( DB_MASTER );
                $rev->insertOn( $dbw );
 
                return $rev;
@@ -143,7 +145,7 @@ class RevisionStorageTest extends MediaWikiTestCase {
        public function testConstructFromRow() {
                $orig = $this->makeRevision();
 
-               $dbr = wfgetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_SLAVE );
                $res = $dbr->select( 'revision', '*', [ 'rev_id' => $orig->getId() ] );
                $this->assertTrue( is_object( $res ), 'query failed' );
 
@@ -161,7 +163,7 @@ class RevisionStorageTest extends MediaWikiTestCase {
        public function testNewFromRow() {
                $orig = $this->makeRevision();
 
-               $dbr = wfgetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_SLAVE );
                $res = $dbr->select( 'revision', '*', [ 'rev_id' => $orig->getId() ] );
                $this->assertTrue( is_object( $res ), 'query failed' );
 
@@ -185,7 +187,7 @@ class RevisionStorageTest extends MediaWikiTestCase {
                $orig = $page->getRevision();
                $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
 
-               $dbr = wfgetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_SLAVE );
                $res = $dbr->select( 'archive', '*', [ 'ar_rev_id' => $orig->getId() ] );
                $this->assertTrue( is_object( $res ), 'query failed' );
 
@@ -312,18 +314,6 @@ class RevisionStorageTest extends MediaWikiTestCase {
                $this->assertEquals( 'hello hello.', $rev->getContent()->getNativeData() );
        }
 
-       /**
-        * @covers Revision::getRawText
-        */
-       public function testGetRawText() {
-               $this->hideDeprecated( 'Revision::getRawText' );
-
-               $orig = $this->makeRevision( [ 'text' => 'hello hello raw.' ] );
-               $rev = Revision::newFromId( $orig->getId() );
-
-               $this->assertEquals( 'hello hello raw.', $rev->getRawText() );
-       }
-
        /**
         * @covers Revision::getContentModel
         */
index d2eb6b8..767c963 100644 (file)
@@ -333,19 +333,6 @@ class RevisionTest extends MediaWikiTestCase {
                $this->assertEquals( $expectedText, $rev->getText( $audience ) );
        }
 
-       /**
-        * @group Database
-        * @dataProvider dataGetText
-        * @covers Revision::getRawText
-        */
-       public function testGetRawText( $text, $title, $model, $format, $audience, $expectedText ) {
-               $this->hideDeprecated( 'Revision::getRawText' );
-
-               $rev = $this->newTestRevision( $text, $title, $model, $format );
-
-               $this->assertEquals( $expectedText, $rev->getRawText( $audience ) );
-       }
-
        public function dataGetSize() {
                return [
                        [ "hello world.", CONTENT_MODEL_WIKITEXT, 12 ],
diff --git a/tests/phpunit/includes/Services/ServiceContainerTest.php b/tests/phpunit/includes/Services/ServiceContainerTest.php
new file mode 100644 (file)
index 0000000..942c45e
--- /dev/null
@@ -0,0 +1,214 @@
+<?php
+use MediaWiki\Services\ServiceContainer;
+
+/**
+ * @covers MediaWiki\Services\ServiceContainer
+ *
+ * @group MediaWiki
+ */
+class ServiceContainerTest extends PHPUnit_Framework_TestCase {
+
+       private function newServiceContainer( $extraArgs = [] ) {
+               return new ServiceContainer( $extraArgs );
+       }
+
+       public function testGetServiceNames() {
+               $services = $this->newServiceContainer();
+               $names = $services->getServiceNames();
+
+               $this->assertInternalType( 'array', $names );
+               $this->assertEmpty( $names );
+
+               $name = 'TestService92834576';
+               $services->defineService( $name, function() {
+                       return null;
+               } );
+
+               $names = $services->getServiceNames();
+               $this->assertContains( $name, $names );
+       }
+
+       public function testHasService() {
+               $services = $this->newServiceContainer();
+
+               $name = 'TestService92834576';
+               $this->assertFalse( $services->hasService( $name ) );
+
+               $services->defineService( $name, function() {
+                       return null;
+               } );
+
+               $this->assertTrue( $services->hasService( $name ) );
+       }
+
+       public function testGetService() {
+               $services = $this->newServiceContainer( [ 'Foo' ] );
+
+               $theService = new stdClass();
+               $name = 'TestService92834576';
+               $count = 0;
+
+               $services->defineService(
+                       $name,
+                       function( $actualLocator, $extra ) use ( $services, $theService, &$count ) {
+                               $count++;
+                               PHPUnit_Framework_Assert::assertSame( $services, $actualLocator );
+                               PHPUnit_Framework_Assert::assertSame( $extra, 'Foo' );
+                               return $theService;
+                       }
+               );
+
+               $this->assertSame( $theService, $services->getService( $name ) );
+
+               $services->getService( $name );
+               $this->assertSame( 1, $count, 'instantiator should be called exactly once!' );
+       }
+
+       public function testGetService_fail_unknown() {
+               $services = $this->newServiceContainer();
+
+               $name = 'TestService92834576';
+
+               $this->setExpectedException( 'InvalidArgumentException' );
+
+               $services->getService( $name );
+       }
+
+       public function testDefineService() {
+               $services = $this->newServiceContainer();
+
+               $theService = new stdClass();
+               $name = 'TestService92834576';
+
+               $services->defineService( $name, function( $actualLocator ) use ( $services, $theService ) {
+                       PHPUnit_Framework_Assert::assertSame( $services, $actualLocator );
+                       return $theService;
+               } );
+
+               $this->assertTrue( $services->hasService( $name ) );
+               $this->assertSame( $theService, $services->getService( $name ) );
+       }
+
+       public function testDefineService_fail_duplicate() {
+               $services = $this->newServiceContainer();
+
+               $theService = new stdClass();
+               $name = 'TestService92834576';
+
+               $services->defineService( $name, function() use ( $theService ) {
+                       return $theService;
+               } );
+
+               $this->setExpectedException( 'RuntimeException' );
+
+               $services->defineService( $name, function() use ( $theService ) {
+                       return $theService;
+               } );
+       }
+
+       public function testApplyWiring() {
+               $services = $this->newServiceContainer();
+
+               $wiring = [
+                       'Foo' => function() {
+                               return 'Foo!';
+                       },
+                       'Bar' => function() {
+                               return 'Bar!';
+                       },
+               ];
+
+               $services->applyWiring( $wiring );
+
+               $this->assertSame( 'Foo!', $services->getService( 'Foo' ) );
+               $this->assertSame( 'Bar!', $services->getService( 'Bar' ) );
+       }
+
+       public function testLoadWiringFiles() {
+               $services = $this->newServiceContainer();
+
+               $wiringFiles = [
+                       __DIR__ . '/TestWiring1.php',
+                       __DIR__ . '/TestWiring2.php',
+               ];
+
+               $services->loadWiringFiles( $wiringFiles );
+
+               $this->assertSame( 'Foo!', $services->getService( 'Foo' ) );
+               $this->assertSame( 'Bar!', $services->getService( 'Bar' ) );
+       }
+
+       public function testLoadWiringFiles_fail_duplicate() {
+               $services = $this->newServiceContainer();
+
+               $wiringFiles = [
+                       __DIR__ . '/TestWiring1.php',
+                       __DIR__ . '/./TestWiring1.php',
+               ];
+
+               // loading the same file twice should fail, because
+               $this->setExpectedException( 'RuntimeException' );
+
+               $services->loadWiringFiles( $wiringFiles );
+       }
+
+       public function testRedefineService() {
+               $services = $this->newServiceContainer( [ 'Foo' ] );
+
+               $theService1 = new stdClass();
+               $name = 'TestService92834576';
+
+               $services->defineService( $name, function() {
+                       PHPUnit_Framework_Assert::fail(
+                               'The original instantiator function should not get called'
+                       );
+               } );
+
+               // redefine before instantiation
+               $services->redefineService(
+                       $name,
+                       function( $actualLocator, $extra ) use ( $services, $theService1 ) {
+                               PHPUnit_Framework_Assert::assertSame( $services, $actualLocator );
+                               PHPUnit_Framework_Assert::assertSame( 'Foo', $extra );
+                               return $theService1;
+                       }
+               );
+
+               // force instantiation, check result
+               $this->assertSame( $theService1, $services->getService( $name ) );
+       }
+
+       public function testRedefineService_fail_undefined() {
+               $services = $this->newServiceContainer();
+
+               $theService = new stdClass();
+               $name = 'TestService92834576';
+
+               $this->setExpectedException( 'RuntimeException' );
+
+               $services->redefineService( $name, function() use ( $theService ) {
+                       return $theService;
+               } );
+       }
+
+       public function testRedefineService_fail_in_use() {
+               $services = $this->newServiceContainer( [ 'Foo' ] );
+
+               $theService = new stdClass();
+               $name = 'TestService92834576';
+
+               $services->defineService( $name, function() {
+                       return 'Foo';
+               } );
+
+               // create the service, so it can no longer be redefined
+               $services->getService( $name );
+
+               $this->setExpectedException( 'RuntimeException' );
+
+               $services->redefineService( $name, function() use ( $theService ) {
+                       return $theService;
+               } );
+       }
+
+}
diff --git a/tests/phpunit/includes/Services/TestWiring1.php b/tests/phpunit/includes/Services/TestWiring1.php
new file mode 100644 (file)
index 0000000..186021a
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Test file for testing ServiceContainer::loadWiringFiles
+ */
+
+return [
+       'Foo' => function() {
+               return 'Foo!';
+       },
+];
diff --git a/tests/phpunit/includes/Services/TestWiring2.php b/tests/phpunit/includes/Services/TestWiring2.php
new file mode 100644 (file)
index 0000000..3b4fff0
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Test file for testing ServiceContainer::loadWiringFiles
+ */
+
+return [
+       'Bar' => function() {
+               return 'Bar!';
+       },
+];
index 584a368..5ecdf56 100644 (file)
@@ -48,7 +48,7 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                if ( !isset( $this->userUser ) || !( $this->userUser instanceof User ) ) {
                        $this->userUser = User::newFromName( $this->userName );
 
-                       if ( !$this->userUser->getID() ) {
+                       if ( !$this->userUser->getId() ) {
                                $this->userUser = User::createNew( $this->userName, [
                                        "email" => "test@example.com",
                                        "real_name" => "Test User" ] );
@@ -56,7 +56,7 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                        }
 
                        $this->altUser = User::newFromName( $this->altUserName );
-                       if ( !$this->altUser->getID() ) {
+                       if ( !$this->altUser->getId() ) {
                                $this->altUser = User::createNew( $this->altUserName, [
                                        "email" => "alttest@example.com",
                                        "real_name" => "Test User Alt" ] );
@@ -658,7 +658,7 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                $this->setUserPerm( [ "createpage" ] );
                $this->setTitle( NS_MAIN, "test page" );
                $this->title->mTitleProtection['permission'] = '';
-               $this->title->mTitleProtection['user'] = $this->user->getID();
+               $this->title->mTitleProtection['user'] = $this->user->getId();
                $this->title->mTitleProtection['expiry'] = 'infinity';
                $this->title->mTitleProtection['reason'] = 'test';
                $this->title->mCascadeRestriction = false;
index 9341fb8..5b2873a 100644 (file)
@@ -25,21 +25,83 @@ class WatchedItemStoreIntegrationTest extends MediaWikiTestCase {
                $store = WatchedItemStore::getDefaultInstance();
                // Cleanup after previous tests
                $store->removeWatch( $user, $title );
+               $initialWatchers = $store->countWatchers( $title );
+               $initialUserWatchedItems = $store->countWatchedItems( $user );
 
                $this->assertFalse(
                        $store->isWatched( $user, $title ),
                        'Page should not initially be watched'
                );
+
                $store->addWatch( $user, $title );
                $this->assertTrue(
                        $store->isWatched( $user, $title ),
                        'Page should be watched'
                );
+               $this->assertEquals( $initialUserWatchedItems + 1, $store->countWatchedItems( $user ) );
+               $watchedItemsForUser = $store->getWatchedItemsForUser( $user );
+               $this->assertCount( $initialUserWatchedItems + 1, $watchedItemsForUser );
+               $watchedItemsForUserHasExpectedItem = false;
+               foreach ( $watchedItemsForUser as $watchedItem ) {
+                       if (
+                               $watchedItem->getUser()->equals( $user ) &&
+                               $watchedItem->getLinkTarget() == $title->getTitleValue()
+                       ) {
+                               $watchedItemsForUserHasExpectedItem = true;
+                       }
+               }
+               $this->assertTrue(
+                       $watchedItemsForUserHasExpectedItem,
+                       'getWatchedItemsForUser should contain the page'
+               );
+               $this->assertEquals( $initialWatchers + 1, $store->countWatchers( $title ) );
+               $this->assertEquals(
+                       $initialWatchers + 1,
+                       $store->countWatchersMultiple( [ $title ] )[$title->getNamespace()][$title->getDBkey()]
+               );
+               $this->assertEquals(
+                       [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => $initialWatchers + 1 ] ],
+                       $store->countWatchersMultiple( [ $title ], [ 'minimumWatchers' => $initialWatchers + 1 ] )
+               );
+               $this->assertEquals(
+                       [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => 0 ] ],
+                       $store->countWatchersMultiple( [ $title ], [ 'minimumWatchers' => $initialWatchers + 2 ] )
+               );
+               $this->assertEquals(
+                       [ $title->getNamespace() => [ $title->getDBkey() => null ] ],
+                       $store->getNotificationTimestampsBatch( $user, [ $title ] )
+               );
+
                $store->removeWatch( $user, $title );
                $this->assertFalse(
                        $store->isWatched( $user, $title ),
                        'Page should be unwatched'
                );
+               $this->assertEquals( $initialUserWatchedItems, $store->countWatchedItems( $user ) );
+               $watchedItemsForUser = $store->getWatchedItemsForUser( $user );
+               $this->assertCount( $initialUserWatchedItems, $watchedItemsForUser );
+               $watchedItemsForUserHasExpectedItem = false;
+               foreach ( $watchedItemsForUser as $watchedItem ) {
+                       if (
+                               $watchedItem->getUser()->equals( $user ) &&
+                               $watchedItem->getLinkTarget() == $title->getTitleValue()
+                       ) {
+                               $watchedItemsForUserHasExpectedItem = true;
+                       }
+               }
+               $this->assertFalse(
+                       $watchedItemsForUserHasExpectedItem,
+                       'getWatchedItemsForUser should not contain the page'
+               );
+               $this->assertEquals( $initialWatchers, $store->countWatchers( $title ) );
+               $this->assertEquals(
+                       $initialWatchers,
+                       $store->countWatchersMultiple( [ $title ] )[$title->getNamespace()][$title->getDBkey()]
+               );
+               $this->assertEquals(
+                       [ $title->getNamespace() => [ $title->getDBkey() => false ] ],
+                       $store->getNotificationTimestampsBatch( $user, [ $title ] )
+               );
        }
 
        public function testUpdateAndResetNotificationTimestamp() {
@@ -49,15 +111,65 @@ class WatchedItemStoreIntegrationTest extends MediaWikiTestCase {
                $store = WatchedItemStore::getDefaultInstance();
                $store->addWatch( $user, $title );
                $this->assertNull( $store->loadWatchedItem( $user, $title )->getNotificationTimestamp() );
+               $initialVisitingWatchers = $store->countVisitingWatchers( $title, '20150202020202' );
+               $initialUnreadNotifications = $store->countUnreadNotifications( $user );
 
                $store->updateNotificationTimestamp( $otherUser, $title, '20150202010101' );
                $this->assertEquals(
                        '20150202010101',
                        $store->loadWatchedItem( $user, $title )->getNotificationTimestamp()
                );
+               $this->assertEquals(
+                       [ $title->getNamespace() => [ $title->getDBkey() => '20150202010101' ] ],
+                       $store->getNotificationTimestampsBatch( $user, [ $title ] )
+               );
+               $this->assertEquals(
+                       $initialVisitingWatchers - 1,
+                       $store->countVisitingWatchers( $title, '20150202020202' )
+               );
+               $this->assertEquals(
+                       $initialVisitingWatchers - 1,
+                       $store->countVisitingWatchersMultiple(
+                               [ [ $title, '20150202020202' ] ]
+                       )[$title->getNamespace()][$title->getDBkey()]
+               );
+               $this->assertEquals(
+                       $initialUnreadNotifications + 1,
+                       $store->countUnreadNotifications( $user )
+               );
+               $this->assertSame(
+                       true,
+                       $store->countUnreadNotifications( $user, $initialUnreadNotifications + 1 )
+               );
 
                $this->assertTrue( $store->resetNotificationTimestamp( $user, $title ) );
-               $this->assertNull( $store->loadWatchedItem( $user, $title )->getNotificationTimestamp() );
+               $this->assertNull( $store->getWatchedItem( $user, $title )->getNotificationTimestamp() );
+               $this->assertEquals(
+                       [ $title->getNamespace() => [ $title->getDBkey() => null ] ],
+                       $store->getNotificationTimestampsBatch( $user, [ $title ] )
+               );
+               $this->assertEquals(
+                       $initialVisitingWatchers,
+                       $store->countVisitingWatchers( $title, '20150202020202' )
+               );
+               $this->assertEquals(
+                       $initialVisitingWatchers,
+                       $store->countVisitingWatchersMultiple(
+                               [ [ $title, '20150202020202' ] ]
+                       )[$title->getNamespace()][$title->getDBkey()]
+               );
+               $this->assertEquals(
+                       [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => $initialVisitingWatchers ] ],
+                       $store->countVisitingWatchersMultiple(
+                               [ [ $title, '20150202020202' ] ], $initialVisitingWatchers
+                       )
+               );
+               $this->assertEquals(
+                       [ 0 => [ 'WatchedItemStoreIntegrationTestPage' => 0 ] ],
+                       $store->countVisitingWatchersMultiple(
+                               [ [ $title, '20150202020202' ] ], $initialVisitingWatchers + 1
+                       )
+               );
        }
 
        public function testDuplicateAllAssociatedEntries() {
index 709b4b4..9dd38df 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+use Liuggio\StatsdClient\Factory\StatsdDataFactory;
 
 /**
  * @author Addshore
@@ -17,13 +18,20 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
        /**
         * @return PHPUnit_Framework_MockObject_MockObject|LoadBalancer
         */
-       private function getMockLoadBalancer( $mockDb ) {
+       private function getMockLoadBalancer( $mockDb, $expectedConnectionType = null ) {
                $mock = $this->getMockBuilder( LoadBalancer::class )
                        ->disableOriginalConstructor()
                        ->getMock();
-               $mock->expects( $this->any() )
-                       ->method( 'getConnection' )
-                       ->will( $this->returnValue( $mockDb ) );
+               if ( $expectedConnectionType !== null ) {
+                       $mock->expects( $this->any() )
+                               ->method( 'getConnection' )
+                               ->with( $expectedConnectionType )
+                               ->will( $this->returnValue( $mockDb ) );
+               } else {
+                       $mock->expects( $this->any() )
+                               ->method( 'getConnection' )
+                               ->will( $this->returnValue( $mockDb ) );
+               }
                $mock->expects( $this->any() )
                        ->method( 'getReadOnlyReason' )
                        ->will( $this->returnValue( false ) );
@@ -31,10 +39,10 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
        }
 
        /**
-        * @return PHPUnit_Framework_MockObject_MockObject|BagOStuff
+        * @return PHPUnit_Framework_MockObject_MockObject|HashBagOStuff
         */
        private function getMockCache() {
-               $mock = $this->getMockBuilder( BagOStuff::class )
+               $mock = $this->getMockBuilder( HashBagOStuff::class )
                        ->disableOriginalConstructor()
                        ->getMock();
                $mock->expects( $this->any() )
@@ -75,12 +83,599 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                return $fakeRow;
        }
 
+       private function newWatchedItemStore( LoadBalancer $loadBalancer, HashBagOStuff $cache ) {
+               return new WatchedItemStore(
+                       $loadBalancer,
+                       $cache
+               );
+       }
+
        public function testGetDefaultInstance() {
                $instanceOne = WatchedItemStore::getDefaultInstance();
                $instanceTwo = WatchedItemStore::getDefaultInstance();
                $this->assertSame( $instanceOne, $instanceTwo );
        }
 
+       public function testOverrideDefaultInstance() {
+               $instance = WatchedItemStore::getDefaultInstance();
+               $scopedOverride = $instance->overrideDefaultInstance( null );
+
+               $this->assertNotSame( $instance, WatchedItemStore::getDefaultInstance() );
+
+               unset( $scopedOverride );
+
+               $this->assertSame( $instance, WatchedItemStore::getDefaultInstance() );
+       }
+
+       public function testCountWatchedItems() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'selectField' )
+                       ->with(
+                               'watchlist',
+                               'COUNT(*)',
+                               [
+                                       'wl_user' => $user->getId(),
+                               ],
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 12 ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals( 12, $store->countWatchedItems( $user ) );
+       }
+
+       public function testCountWatchers() {
+               $titleValue = new TitleValue( 0, 'SomeDbKey' );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'selectField' )
+                       ->with(
+                               'watchlist',
+                               'COUNT(*)',
+                               [
+                                       'wl_namespace' => $titleValue->getNamespace(),
+                                       'wl_title' => $titleValue->getDBkey(),
+                               ],
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 7 ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals( 7, $store->countWatchers( $titleValue ) );
+       }
+
+       public function testCountWatchersMultiple() {
+               $titleValues = [
+                       new TitleValue( 0, 'SomeDbKey' ),
+                       new TitleValue( 0, 'OtherDbKey' ),
+                       new TitleValue( 1, 'AnotherDbKey' ),
+               ];
+
+               $mockDb = $this->getMockDb();
+
+               $dbResult = [
+                       $this->getFakeRow( [ 'wl_title' => 'SomeDbKey', 'wl_namespace' => 0, 'watchers' => 100 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'OtherDbKey', 'wl_namespace' => 0, 'watchers' => 300 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'AnotherDbKey', 'wl_namespace' => 1, 'watchers' => 500 ]
+                       ),
+               ];
+               $mockDb->expects( $this->once() )
+                       ->method( 'makeWhereFrom2d' )
+                       ->with(
+                               [ [ 'SomeDbKey' => 1, 'OtherDbKey' => 1 ], [ 'AnotherDbKey' => 1 ] ],
+                               $this->isType( 'string' ),
+                               $this->isType( 'string' )
+                               )
+                       ->will( $this->returnValue( 'makeWhereFrom2d return value' ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_title', 'wl_namespace', 'watchers' => 'COUNT(*)' ],
+                               [ 'makeWhereFrom2d return value' ],
+                               $this->isType( 'string' ),
+                               [
+                                       'GROUP BY' => [ 'wl_namespace', 'wl_title' ],
+                               ]
+                       )
+                       ->will(
+                               $this->returnValue( $dbResult )
+                       );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $expected = [
+                       0 => [ 'SomeDbKey' => 100, 'OtherDbKey' => 300 ],
+                       1 => [ 'AnotherDbKey' => 500 ],
+               ];
+               $this->assertEquals( $expected, $store->countWatchersMultiple( $titleValues ) );
+       }
+
+       public function provideIntWithDbUnsafeVersion() {
+               return [
+                       [ 50 ],
+                       [ "50; DROP TABLE watchlist;\n--" ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideIntWithDbUnsafeVersion
+        */
+       public function testCountWatchersMultiple_withMinimumWatchers( $minWatchers ) {
+               $titleValues = [
+                       new TitleValue( 0, 'SomeDbKey' ),
+                       new TitleValue( 0, 'OtherDbKey' ),
+                       new TitleValue( 1, 'AnotherDbKey' ),
+               ];
+
+               $mockDb = $this->getMockDb();
+
+               $dbResult = [
+                       $this->getFakeRow( [ 'wl_title' => 'SomeDbKey', 'wl_namespace' => 0, 'watchers' => 100 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'OtherDbKey', 'wl_namespace' => 0, 'watchers' => 300 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'AnotherDbKey', 'wl_namespace' => 1, 'watchers' => 500 ]
+                       ),
+               ];
+               $mockDb->expects( $this->once() )
+                       ->method( 'makeWhereFrom2d' )
+                       ->with(
+                               [ [ 'SomeDbKey' => 1, 'OtherDbKey' => 1 ], [ 'AnotherDbKey' => 1 ] ],
+                               $this->isType( 'string' ),
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 'makeWhereFrom2d return value' ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_title', 'wl_namespace', 'watchers' => 'COUNT(*)' ],
+                               [ 'makeWhereFrom2d return value' ],
+                               $this->isType( 'string' ),
+                               [
+                                       'GROUP BY' => [ 'wl_namespace', 'wl_title' ],
+                                       'HAVING' => 'COUNT(*) >= 50',
+                               ]
+                       )
+                       ->will(
+                               $this->returnValue( $dbResult )
+                       );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $expected = [
+                       0 => [ 'SomeDbKey' => 100, 'OtherDbKey' => 300 ],
+                       1 => [ 'AnotherDbKey' => 500 ],
+               ];
+               $this->assertEquals(
+                       $expected,
+                       $store->countWatchersMultiple( $titleValues, [ 'minimumWatchers' => $minWatchers ] )
+               );
+       }
+
+       public function testCountVisitingWatchers() {
+               $titleValue = new TitleValue( 0, 'SomeDbKey' );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'selectField' )
+                       ->with(
+                               'watchlist',
+                               'COUNT(*)',
+                               [
+                                       'wl_namespace' => $titleValue->getNamespace(),
+                                       'wl_title' => $titleValue->getDBkey(),
+                                       'wl_notificationtimestamp >= \'TS111TS\' OR wl_notificationtimestamp IS NULL',
+                               ],
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 7 ) );
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'addQuotes' )
+                       ->will( $this->returnCallback( function( $value ) {
+                               return "'$value'";
+                       } ) );
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'timestamp' )
+                       ->will( $this->returnCallback( function( $value ) {
+                               return 'TS' . $value . 'TS';
+                       } ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals( 7, $store->countVisitingWatchers( $titleValue, '111' ) );
+       }
+
+       public function testCountVisitingWatchersMultiple() {
+               $titleValuesWithThresholds = [
+                       [ new TitleValue( 0, 'SomeDbKey' ), '111' ],
+                       [ new TitleValue( 0, 'OtherDbKey' ), '111' ],
+                       [ new TitleValue( 1, 'AnotherDbKey' ), '123' ],
+               ];
+
+               $dbResult = [
+                       $this->getFakeRow( [ 'wl_title' => 'SomeDbKey', 'wl_namespace' => 0, 'watchers' => 100 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'OtherDbKey', 'wl_namespace' => 0, 'watchers' => 300 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'AnotherDbKey', 'wl_namespace' => 1, 'watchers' => 500 ] ),
+               ];
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 2 * 3 ) )
+                       ->method( 'addQuotes' )
+                       ->will( $this->returnCallback( function( $value ) {
+                               return "'$value'";
+                       } ) );
+               $mockDb->expects( $this->exactly( 3 ) )
+                       ->method( 'timestamp' )
+                       ->will( $this->returnCallback( function( $value ) {
+                               return 'TS' . $value . 'TS';
+                       } ) );
+               $mockDb->expects( $this->any() )
+                       ->method( 'makeList' )
+                       ->with(
+                               $this->isType( 'array' ),
+                               $this->isType( 'int' )
+                       )
+                       ->will( $this->returnCallback( function( $a, $conj ) {
+                               $sqlConj = $conj === LIST_AND ? ' AND ' : ' OR ';
+                               return join( $sqlConj, array_map( function( $s ) {
+                                       return '(' . $s . ')';
+                               }, $a
+                               ) );
+                       } ) );
+               $mockDb->expects( $this->never() )
+                       ->method( 'makeWhereFrom2d' );
+
+               $expectedCond =
+                       '((wl_namespace = 0) AND (' .
+                       "(((wl_title = 'SomeDbKey') AND (" .
+                       "(wl_notificationtimestamp >= 'TS111TS') OR (wl_notificationtimestamp IS NULL)" .
+                       ')) OR (' .
+                       "(wl_title = 'OtherDbKey') AND (" .
+                       "(wl_notificationtimestamp >= 'TS111TS') OR (wl_notificationtimestamp IS NULL)" .
+                       '))))' .
+                       ') OR ((wl_namespace = 1) AND (' .
+                       "(((wl_title = 'AnotherDbKey') AND (".
+                       "(wl_notificationtimestamp >= 'TS123TS') OR (wl_notificationtimestamp IS NULL)" .
+                       ')))))';
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_namespace', 'wl_title', 'watchers' => 'COUNT(*)' ],
+                               $expectedCond,
+                               $this->isType( 'string' ),
+                               [
+                                       'GROUP BY' => [ 'wl_namespace', 'wl_title' ],
+                               ]
+                       )
+                       ->will(
+                               $this->returnValue( $dbResult )
+                       );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $expected = [
+                       0 => [ 'SomeDbKey' => 100, 'OtherDbKey' => 300 ],
+                       1 => [ 'AnotherDbKey' => 500 ],
+               ];
+               $this->assertEquals(
+                       $expected,
+                       $store->countVisitingWatchersMultiple( $titleValuesWithThresholds )
+               );
+       }
+
+       public function testCountVisitingWatchersMultiple_withMissingTargets() {
+               $titleValuesWithThresholds = [
+                       [ new TitleValue( 0, 'SomeDbKey' ), '111' ],
+                       [ new TitleValue( 0, 'OtherDbKey' ), '111' ],
+                       [ new TitleValue( 1, 'AnotherDbKey' ), '123' ],
+                       [ new TitleValue( 0, 'SomeNotExisitingDbKey' ), null ],
+                       [ new TitleValue( 0, 'OtherNotExisitingDbKey' ), null ],
+               ];
+
+               $dbResult = [
+                       $this->getFakeRow( [ 'wl_title' => 'SomeDbKey', 'wl_namespace' => 0, 'watchers' => 100 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'OtherDbKey', 'wl_namespace' => 0, 'watchers' => 300 ] ),
+                       $this->getFakeRow( [ 'wl_title' => 'AnotherDbKey', 'wl_namespace' => 1, 'watchers' => 500 ] ),
+                       $this->getFakeRow(
+                               [ 'wl_title' => 'SomeNotExisitingDbKey', 'wl_namespace' => 0, 'watchers' => 100 ]
+                       ),
+                       $this->getFakeRow(
+                               [ 'wl_title' => 'OtherNotExisitingDbKey', 'wl_namespace' => 0, 'watchers' => 200 ]
+                       ),
+               ];
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 2 * 3 ) )
+                       ->method( 'addQuotes' )
+                       ->will( $this->returnCallback( function( $value ) {
+                               return "'$value'";
+                       } ) );
+               $mockDb->expects( $this->exactly( 3 ) )
+                       ->method( 'timestamp' )
+                       ->will( $this->returnCallback( function( $value ) {
+                               return 'TS' . $value . 'TS';
+                       } ) );
+               $mockDb->expects( $this->any() )
+                       ->method( 'makeList' )
+                       ->with(
+                               $this->isType( 'array' ),
+                               $this->isType( 'int' )
+                       )
+                       ->will( $this->returnCallback( function( $a, $conj ) {
+                               $sqlConj = $conj === LIST_AND ? ' AND ' : ' OR ';
+                               return join( $sqlConj, array_map( function( $s ) {
+                                       return '(' . $s . ')';
+                               }, $a
+                               ) );
+                       } ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'makeWhereFrom2d' )
+                       ->with(
+                               [ [ 'SomeNotExisitingDbKey' => 1, 'OtherNotExisitingDbKey' => 1 ] ],
+                               $this->isType( 'string' ),
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 'makeWhereFrom2d return value' ) );
+
+               $expectedCond =
+                       '((wl_namespace = 0) AND (' .
+                       "(((wl_title = 'SomeDbKey') AND (" .
+                       "(wl_notificationtimestamp >= 'TS111TS') OR (wl_notificationtimestamp IS NULL)" .
+                       ')) OR (' .
+                       "(wl_title = 'OtherDbKey') AND (" .
+                       "(wl_notificationtimestamp >= 'TS111TS') OR (wl_notificationtimestamp IS NULL)" .
+                       '))))' .
+                       ') OR ((wl_namespace = 1) AND (' .
+                       "(((wl_title = 'AnotherDbKey') AND (".
+                       "(wl_notificationtimestamp >= 'TS123TS') OR (wl_notificationtimestamp IS NULL)" .
+                       '))))' .
+                       ') OR ' .
+                       '(makeWhereFrom2d return value)';
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_namespace', 'wl_title', 'watchers' => 'COUNT(*)' ],
+                               $expectedCond,
+                               $this->isType( 'string' ),
+                               [
+                                       'GROUP BY' => [ 'wl_namespace', 'wl_title' ],
+                               ]
+                       )
+                       ->will(
+                               $this->returnValue( $dbResult )
+                       );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $expected = [
+                       0 => [
+                               'SomeDbKey' => 100, 'OtherDbKey' => 300,
+                               'SomeNotExisitingDbKey' => 100, 'OtherNotExisitingDbKey' => 200
+                       ],
+                       1 => [ 'AnotherDbKey' => 500 ],
+               ];
+               $this->assertEquals(
+                       $expected,
+                       $store->countVisitingWatchersMultiple( $titleValuesWithThresholds )
+               );
+       }
+
+       /**
+        * @dataProvider provideIntWithDbUnsafeVersion
+        */
+       public function testCountVisitingWatchersMultiple_withMinimumWatchers( $minWatchers ) {
+               $titleValuesWithThresholds = [
+                       [ new TitleValue( 0, 'SomeDbKey' ), '111' ],
+                       [ new TitleValue( 0, 'OtherDbKey' ), '111' ],
+                       [ new TitleValue( 1, 'AnotherDbKey' ), '123' ],
+               ];
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->any() )
+                       ->method( 'makeList' )
+                       ->will( $this->returnValue( 'makeList return value' ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_namespace', 'wl_title', 'watchers' => 'COUNT(*)' ],
+                               'makeList return value',
+                               $this->isType( 'string' ),
+                               [
+                                       'GROUP BY' => [ 'wl_namespace', 'wl_title' ],
+                                       'HAVING' => 'COUNT(*) >= 50',
+                               ]
+                       )
+                       ->will(
+                               $this->returnValue( [] )
+                       );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $expected = [
+                       0 => [ 'SomeDbKey' => 0, 'OtherDbKey' => 0 ],
+                       1 => [ 'AnotherDbKey' => 0 ],
+               ];
+               $this->assertEquals(
+                       $expected,
+                       $store->countVisitingWatchersMultiple( $titleValuesWithThresholds, $minWatchers )
+               );
+       }
+
+       public function testCountUnreadNotifications() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'selectRowCount' )
+                       ->with(
+                               'watchlist',
+                               '1',
+                               [
+                                       "wl_notificationtimestamp IS NOT NULL",
+                                       'wl_user' => 1,
+                               ],
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 9 ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals( 9, $store->countUnreadNotifications( $user ) );
+       }
+
+       /**
+        * @dataProvider provideIntWithDbUnsafeVersion
+        */
+       public function testCountUnreadNotifications_withUnreadLimit_overLimit( $limit ) {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'selectRowCount' )
+                       ->with(
+                               'watchlist',
+                               '1',
+                               [
+                                       "wl_notificationtimestamp IS NOT NULL",
+                                       'wl_user' => 1,
+                               ],
+                               $this->isType( 'string' ),
+                               [ 'LIMIT' => 50 ]
+                       )
+                       ->will( $this->returnValue( 50 ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertSame(
+                       true,
+                       $store->countUnreadNotifications( $user, $limit )
+               );
+       }
+
+       /**
+        * @dataProvider provideIntWithDbUnsafeVersion
+        */
+       public function testCountUnreadNotifications_withUnreadLimit_underLimit( $limit ) {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->exactly( 1 ) )
+                       ->method( 'selectRowCount' )
+                       ->with(
+                               'watchlist',
+                               '1',
+                               [
+                                       "wl_notificationtimestamp IS NOT NULL",
+                                       'wl_user' => 1,
+                               ],
+                               $this->isType( 'string' ),
+                               [ 'LIMIT' => 50 ]
+                       )
+                       ->will( $this->returnValue( 9 ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals(
+                       9,
+                       $store->countUnreadNotifications( $user, $limit )
+               );
+       }
+
        public function testDuplicateEntry_nothingToDuplicate() {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->once() )
@@ -100,9 +695,9 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        )
                        ->will( $this->returnValue( new FakeResultWrapper( [] ) ) );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
-                       new HashBagOStuff( [ 'maxKeys' => 100 ] )
+                       $this->getMockCache()
                );
 
                $store->duplicateEntry(
@@ -154,9 +749,13 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                $this->isType( 'string' )
                        );
 
-               $store = new WatchedItemStore(
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
-                       new HashBagOStuff( [ 'maxKeys' => 100 ] )
+                       $mockCache
                );
 
                $store->duplicateEntry(
@@ -196,9 +795,13 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        )
                        ->will( $this->returnValue( new FakeResultWrapper( [] ) ) );
 
-               $store = new WatchedItemStore(
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
-                       new HashBagOStuff( [ 'maxKeys' => 100 ] )
+                       $mockCache
                );
 
                $store->duplicateAllAssociatedEntries(
@@ -272,9 +875,13 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                $this->isType( 'string' )
                        );
 
-               $store = new WatchedItemStore(
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
-                       new HashBagOStuff( [ 'maxKeys' => 100 ] )
+                       $mockCache
                );
 
                $store->duplicateAllAssociatedEntries(
@@ -304,7 +911,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'delete' )
                        ->with( '0:Some_Page:1' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -324,7 +931,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                $mockCache->expects( $this->never() )
                        ->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -335,7 +942,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                );
        }
 
-       public function testAddWatchBatch_nonAnonymousUser() {
+       public function testAddWatchBatchForUser_nonAnonymousUser() {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->once() )
                        ->method( 'insert' )
@@ -367,7 +974,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'delete' )
                        ->with( '1:Some_Page:1' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -375,52 +982,14 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                $mockUser = $this->getMockNonAnonUserWithId( 1 );
 
                $this->assertTrue(
-                       $store->addWatchBatch(
-                               [
-                                       [ $mockUser, new TitleValue( 0, 'Some_Page' ) ],
-                                       [ $mockUser, new TitleValue( 1, 'Some_Page' ) ],
-                               ]
-                       )
-               );
-       }
-
-       public function testAddWatchBatch_anonymousUserCombinationsAreSkipped() {
-               $mockDb = $this->getMockDb();
-               $mockDb->expects( $this->once() )
-                       ->method( 'insert' )
-                       ->with(
-                               'watchlist',
-                               [
-                                       [
-                                               'wl_user' => 1,
-                                               'wl_namespace' => 0,
-                                               'wl_title' => 'Some_Page',
-                                               'wl_notificationtimestamp' => null,
-                                       ]
-                               ]
-                       );
-
-               $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->once() )
-                       ->method( 'delete' )
-                       ->with( '0:Some_Page:1' );
-
-               $store = new WatchedItemStore(
-                       $this->getMockLoadBalancer( $mockDb ),
-                       $mockCache
-               );
-
-               $this->assertTrue(
-                       $store->addWatchBatch(
-                               [
-                                       [ $this->getMockNonAnonUserWithId( 1 ), new TitleValue( 0, 'Some_Page' ) ],
-                                       [ $this->getAnonUser(), new TitleValue( 0, 'Other_Page' ) ],
-                               ]
+                       $store->addWatchBatchForUser(
+                               $mockUser,
+                               [ new TitleValue( 0, 'Some_Page' ), new TitleValue( 1, 'Some_Page' ) ]
                        )
                );
        }
 
-       public function testAddWatchBatchReturnsFalse_whenOnlyGivenAnonymousUserCombinations() {
+       public function testAddWatchBatchForUser_anonymousUsersAreSkipped() {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->never() )
                        ->method( 'insert' );
@@ -429,23 +998,21 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                $mockCache->expects( $this->never() )
                        ->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
-               $anonUser = $this->getAnonUser();
                $this->assertFalse(
-                       $store->addWatchBatch(
-                               [
-                                       [ $anonUser, new TitleValue( 0, 'Some_Page' ) ],
-                                       [ $anonUser, new TitleValue( 1, 'Other_Page' ) ],
-                               ]
+                       $store->addWatchBatchForUser(
+                               $this->getAnonUser(),
+                               [ new TitleValue( 0, 'Other_Page' ) ]
                        )
                );
        }
 
-       public function testAddWatchBatchReturnsFalse_whenGivenEmptyList() {
+       public function testAddWatchBatchReturnsTrue_whenGivenEmptyList() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->never() )
                        ->method( 'insert' );
@@ -454,13 +1021,13 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                $mockCache->expects( $this->never() )
                        ->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
-               $this->assertFalse(
-                       $store->addWatchBatch( [] )
+               $this->assertTrue(
+                       $store->addWatchBatchForUser( $user, [] )
                );
        }
 
@@ -488,7 +1055,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                '0:SomeDbKey:1'
                        );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -519,10 +1086,10 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->will( $this->returnValue( [] ) );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'delete' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -541,10 +1108,10 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'selectRow' );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'delete' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -574,11 +1141,12 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->will( $this->returnValue( 1 ) );
 
                $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
                $mockCache->expects( $this->once() )
                        ->method( 'delete' )
                        ->with( '0:SomeDbKey:1' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -608,11 +1176,12 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->will( $this->returnValue( 0 ) );
 
                $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
                $mockCache->expects( $this->once() )
                        ->method( 'delete' )
                        ->with( '0:SomeDbKey:1' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -631,10 +1200,11 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'delete' );
 
                $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
                $mockCache->expects( $this->never() )
                        ->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -665,6 +1235,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ) );
 
                $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'delete' );
                $mockCache->expects( $this->once() )
                        ->method( 'get' )
                        ->with(
@@ -677,7 +1248,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                '0:SomeDbKey:1'
                        );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -692,40 +1263,243 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                $this->assertEquals( 0, $watchedItem->getLinkTarget()->getNamespace() );
        }
 
-       public function testGetWatchedItem_cachedItem() {
+       public function testGetWatchedItem_cachedItem() {
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->never() )
+                       ->method( 'selectRow' );
+
+               $mockUser = $this->getMockNonAnonUserWithId( 1 );
+               $linkTarget = new TitleValue( 0, 'SomeDbKey' );
+               $cachedItem = new WatchedItem( $mockUser, $linkTarget, '20151212010101' );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'delete' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->once() )
+                       ->method( 'get' )
+                       ->with(
+                               '0:SomeDbKey:1'
+                       )
+                       ->will( $this->returnValue( $cachedItem ) );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals(
+                       $cachedItem,
+                       $store->getWatchedItem(
+                               $mockUser,
+                               $linkTarget
+                       )
+               );
+       }
+
+       public function testGetWatchedItem_noItem() {
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->once() )
+                       ->method( 'selectRow' )
+                       ->with(
+                               'watchlist',
+                               'wl_notificationtimestamp',
+                               [
+                                       'wl_user' => 1,
+                                       'wl_namespace' => 0,
+                                       'wl_title' => 'SomeDbKey',
+                               ]
+                       )
+                       ->will( $this->returnValue( [] ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+               $mockCache->expects( $this->once() )
+                       ->method( 'get' )
+                       ->with( '0:SomeDbKey:1' )
+                       ->will( $this->returnValue( false ) );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertFalse(
+                       $store->getWatchedItem(
+                               $this->getMockNonAnonUserWithId( 1 ),
+                               new TitleValue( 0, 'SomeDbKey' )
+                       )
+               );
+       }
+
+       public function testGetWatchedItem_anonymousUser() {
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->never() )
+                       ->method( 'selectRow' );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertFalse(
+                       $store->getWatchedItem(
+                               $this->getAnonUser(),
+                               new TitleValue( 0, 'SomeDbKey' )
+                       )
+               );
+       }
+
+       public function testGetWatchedItemsForUser() {
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
+                               [ 'wl_user' => 1 ]
+                       )
+                       ->will( $this->returnValue( [
+                               $this->getFakeRow( [
+                                       'wl_namespace' => 0,
+                                       'wl_title' => 'Foo1',
+                                       'wl_notificationtimestamp' => '20151212010101',
+                               ] ),
+                               $this->getFakeRow( [
+                                       'wl_namespace' => 1,
+                                       'wl_title' => 'Foo2',
+                                       'wl_notificationtimestamp' => null,
+                               ] ),
+                       ] ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'delete' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+               $user = $this->getMockNonAnonUserWithId( 1 );
+
+               $watchedItems = $store->getWatchedItemsForUser( $user );
+
+               $this->assertInternalType( 'array', $watchedItems );
+               $this->assertCount( 2, $watchedItems );
+               foreach ( $watchedItems as $watchedItem ) {
+                       $this->assertInstanceOf( 'WatchedItem', $watchedItem );
+               }
+               $this->assertEquals(
+                       new WatchedItem( $user, new TitleValue( 0, 'Foo1' ), '20151212010101' ),
+                       $watchedItems[0]
+               );
+               $this->assertEquals(
+                       new WatchedItem( $user, new TitleValue( 1, 'Foo2' ), null ),
+                       $watchedItems[1]
+               );
+       }
+
+       public function provideDbTypes() {
+               return [
+                       [ false, DB_SLAVE ],
+                       [ true, DB_MASTER ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideDbTypes
+        */
+       public function testGetWatchedItemsForUser_optionsAndEmptyResult( $forWrite, $dbType ) {
+               $mockDb = $this->getMockDb();
+               $mockCache = $this->getMockCache();
+               $mockLoadBalancer = $this->getMockLoadBalancer( $mockDb, $dbType );
+               $user = $this->getMockNonAnonUserWithId( 1 );
+
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
+                               [ 'wl_user' => 1 ],
+                               $this->isType( 'string' ),
+                               [ 'ORDER BY' => [ 'wl_namespace ASC', 'wl_title ASC' ] ]
+                       )
+                       ->will( $this->returnValue( [] ) );
+
+               $store = $this->newWatchedItemStore(
+                       $mockLoadBalancer,
+                       $mockCache
+               );
+
+               $watchedItems = $store->getWatchedItemsForUser(
+                       $user,
+                       [ 'forWrite' => $forWrite, 'sort' => WatchedItemStore::SORT_ASC ]
+               );
+               $this->assertEquals( [], $watchedItems );
+       }
+
+       public function testGetWatchedItemsForUser_badSortOptionThrowsException() {
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $this->getMockDb() ),
+                       $this->getMockCache()
+               );
+
+               $this->setExpectedException( 'InvalidArgumentException' );
+               $store->getWatchedItemsForUser(
+                       $this->getMockNonAnonUserWithId( 1 ),
+                       [ 'sort' => 'foo' ]
+               );
+       }
+
+       public function testIsWatchedItem_existingItem() {
                $mockDb = $this->getMockDb();
-               $mockDb->expects( $this->never() )
-                       ->method( 'selectRow' );
-
-               $mockUser = $this->getMockNonAnonUserWithId( 1 );
-               $linkTarget = new TitleValue( 0, 'SomeDbKey' );
-               $cachedItem = new WatchedItem( $mockUser, $linkTarget, '20151212010101' );
+               $mockDb->expects( $this->once() )
+                       ->method( 'selectRow' )
+                       ->with(
+                               'watchlist',
+                               'wl_notificationtimestamp',
+                               [
+                                       'wl_user' => 1,
+                                       'wl_namespace' => 0,
+                                       'wl_title' => 'SomeDbKey',
+                               ]
+                       )
+                       ->will( $this->returnValue(
+                               $this->getFakeRow( [ 'wl_notificationtimestamp' => '20151212010101' ] )
+                       ) );
 
                $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'delete' );
                $mockCache->expects( $this->once() )
                        ->method( 'get' )
+                       ->with( '0:SomeDbKey:1' )
+                       ->will( $this->returnValue( false ) );
+               $mockCache->expects( $this->once() )
+                       ->method( 'set' )
                        ->with(
                                '0:SomeDbKey:1'
-                       )
-                       ->will( $this->returnValue( $cachedItem ) );
-               $mockCache->expects( $this->never() )
-                       ->method( 'set' );
+                       );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
-               $this->assertEquals(
-                       $cachedItem,
-                       $store->getWatchedItem(
-                               $mockUser,
-                               $linkTarget
+               $this->assertTrue(
+                       $store->isWatched(
+                               $this->getMockNonAnonUserWithId( 1 ),
+                               new TitleValue( 0, 'SomeDbKey' )
                        )
                );
        }
 
-       public function testGetWatchedItem_noItem() {
+       public function testIsWatchedItem_noItem() {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->once() )
                        ->method( 'selectRow' )
@@ -741,132 +1515,291 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->will( $this->returnValue( [] ) );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+               $mockCache->expects( $this->once() )
+                       ->method( 'get' )
+                       ->with( '0:SomeDbKey:1' )
+                       ->will( $this->returnValue( false ) );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
                $this->assertFalse(
-                       $store->getWatchedItem(
+                       $store->isWatched(
                                $this->getMockNonAnonUserWithId( 1 ),
                                new TitleValue( 0, 'SomeDbKey' )
                        )
                );
        }
 
-       public function testGetWatchedItem_anonymousUser() {
+       public function testIsWatchedItem_anonymousUser() {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->never() )
                        ->method( 'selectRow' );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
                $this->assertFalse(
-                       $store->getWatchedItem(
+                       $store->isWatched(
                                $this->getAnonUser(),
                                new TitleValue( 0, 'SomeDbKey' )
                        )
                );
        }
 
-       public function testIsWatchedItem_existingItem() {
+       public function testGetNotificationTimestampsBatch() {
+               $targets = [
+                       new TitleValue( 0, 'SomeDbKey' ),
+                       new TitleValue( 1, 'AnotherDbKey' ),
+               ];
+
                $mockDb = $this->getMockDb();
+               $dbResult = [
+                       $this->getFakeRow( [
+                               'wl_namespace' => 0,
+                               'wl_title' => 'SomeDbKey',
+                               'wl_notificationtimestamp' => '20151212010101',
+                       ] ),
+                       $this->getFakeRow(
+                               [
+                                       'wl_namespace' => 1,
+                                       'wl_title' => 'AnotherDbKey',
+                                       'wl_notificationtimestamp' => null,
+                               ]
+                       ),
+               ];
+
                $mockDb->expects( $this->once() )
-                       ->method( 'selectRow' )
+                       ->method( 'makeWhereFrom2d' )
+                       ->with(
+                               [ [ 'SomeDbKey' => 1 ], [ 'AnotherDbKey' => 1 ] ],
+                               $this->isType( 'string' ),
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 'makeWhereFrom2d return value' ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
                        ->with(
                                'watchlist',
-                               'wl_notificationtimestamp',
+                               [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
                                [
-                                       'wl_user' => 1,
-                                       'wl_namespace' => 0,
-                                       'wl_title' => 'SomeDbKey',
-                               ]
+                                       'makeWhereFrom2d return value',
+                                       'wl_user' => 1
+                               ],
+                               $this->isType( 'string' )
                        )
-                       ->will( $this->returnValue(
-                               $this->getFakeRow( [ 'wl_notificationtimestamp' => '20151212010101' ] )
-                       ) );
+                       ->will( $this->returnValue( $dbResult ) );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->once() )
-                       ->method( 'set' )
-                       ->with(
-                               '0:SomeDbKey:1'
-                       );
+               $mockCache->expects( $this->exactly( 2 ) )
+                       ->method( 'get' )
+                       ->withConsecutive(
+                               [ '0:SomeDbKey:1' ],
+                               [ '1:AnotherDbKey:1' ]
+                       )
+                       ->will( $this->returnValue( null ) );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
-               $this->assertTrue(
-                       $store->isWatched(
-                               $this->getMockNonAnonUserWithId( 1 ),
-                               new TitleValue( 0, 'SomeDbKey' )
-                       )
+               $this->assertEquals(
+                       [
+                               0 => [ 'SomeDbKey' => '20151212010101', ],
+                               1 => [ 'AnotherDbKey' => null, ],
+                       ],
+                       $store->getNotificationTimestampsBatch( $this->getMockNonAnonUserWithId( 1 ), $targets )
                );
        }
 
-       public function testIsWatchedItem_noItem() {
+       public function testGetNotificationTimestampsBatch_notWatchedTarget() {
+               $targets = [
+                       new TitleValue( 0, 'OtherDbKey' ),
+               ];
+
                $mockDb = $this->getMockDb();
+
                $mockDb->expects( $this->once() )
-                       ->method( 'selectRow' )
+                       ->method( 'makeWhereFrom2d' )
+                       ->with(
+                               [ [ 'OtherDbKey' => 1 ] ],
+                               $this->isType( 'string' ),
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 'makeWhereFrom2d return value' ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
                        ->with(
                                'watchlist',
-                               'wl_notificationtimestamp',
+                               [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
                                [
-                                       'wl_user' => 1,
-                                       'wl_namespace' => 0,
-                                       'wl_title' => 'SomeDbKey',
-                               ]
+                                       'makeWhereFrom2d return value',
+                                       'wl_user' => 1
+                               ],
+                               $this->isType( 'string' )
                        )
-                       ->will( $this->returnValue( [] ) );
+                       ->will( $this->returnValue( $this->getFakeRow( [] ) ) );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'set' );
+               $mockCache->expects( $this->once() )
+                       ->method( 'get' )
+                       ->with( '0:OtherDbKey:1' )
+                       ->will( $this->returnValue( null ) );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
-               $this->assertFalse(
-                       $store->isWatched(
-                               $this->getMockNonAnonUserWithId( 1 ),
-                               new TitleValue( 0, 'SomeDbKey' )
+               $this->assertEquals(
+                       [
+                               0 => [ 'OtherDbKey' => false, ],
+                       ],
+                       $store->getNotificationTimestampsBatch( $this->getMockNonAnonUserWithId( 1 ), $targets )
+               );
+       }
+
+       public function testGetNotificationTimestampsBatch_cachedItem() {
+               $targets = [
+                       new TitleValue( 0, 'SomeDbKey' ),
+                       new TitleValue( 1, 'AnotherDbKey' ),
+               ];
+
+               $user = $this->getMockNonAnonUserWithId( 1 );
+               $cachedItem = new WatchedItem( $user, $targets[0], '20151212010101' );
+
+               $mockDb = $this->getMockDb();
+
+               $mockDb->expects( $this->once() )
+                       ->method( 'makeWhereFrom2d' )
+                       ->with(
+                               [ 1 => [ 'AnotherDbKey' => 1 ] ],
+                               $this->isType( 'string' ),
+                               $this->isType( 'string' )
+                       )
+                       ->will( $this->returnValue( 'makeWhereFrom2d return value' ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
+                               [
+                                       'makeWhereFrom2d return value',
+                                       'wl_user' => 1
+                               ],
+                               $this->isType( 'string' )
                        )
+                       ->will( $this->returnValue( [
+                               $this->getFakeRow(
+                                       [ 'wl_namespace' => 1, 'wl_title' => 'AnotherDbKey', 'wl_notificationtimestamp' => null, ]
+                               )
+                       ] ) );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->at( 1 ) )
+                       ->method( 'get' )
+                       ->with( '0:SomeDbKey:1' )
+                       ->will( $this->returnValue( $cachedItem ) );
+               $mockCache->expects( $this->at( 3 ) )
+                       ->method( 'get' )
+                       ->with( '1:AnotherDbKey:1' )
+                       ->will( $this->returnValue( null ) );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals(
+                       [
+                               0 => [ 'SomeDbKey' => '20151212010101', ],
+                               1 => [ 'AnotherDbKey' => null, ],
+                       ],
+                       $store->getNotificationTimestampsBatch( $user, $targets )
                );
        }
 
-       public function testIsWatchedItem_anonymousUser() {
+       public function testGetNotificationTimestampsBatch_allItemsCached() {
+               $targets = [
+                       new TitleValue( 0, 'SomeDbKey' ),
+                       new TitleValue( 1, 'AnotherDbKey' ),
+               ];
+
+               $user = $this->getMockNonAnonUserWithId( 1 );
+               $cachedItems = [
+                       new WatchedItem( $user, $targets[0], '20151212010101' ),
+                       new WatchedItem( $user, $targets[1], null ),
+               ];
                $mockDb = $this->getMockDb();
-               $mockDb->expects( $this->never() )
-                       ->method( 'selectRow' );
+               $mockDb->expects( $this->never() )->method( $this->anything() );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'set' );
+               $mockCache->expects( $this->at( 1 ) )
+                       ->method( 'get' )
+                       ->with( '0:SomeDbKey:1' )
+                       ->will( $this->returnValue( $cachedItems[0] ) );
+               $mockCache->expects( $this->at( 3 ) )
+                       ->method( 'get' )
+                       ->with( '1:AnotherDbKey:1' )
+                       ->will( $this->returnValue( $cachedItems[1] ) );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
-               $this->assertFalse(
-                       $store->isWatched(
-                               $this->getAnonUser(),
-                               new TitleValue( 0, 'SomeDbKey' )
-                       )
+               $this->assertEquals(
+                       [
+                               0 => [ 'SomeDbKey' => '20151212010101', ],
+                               1 => [ 'AnotherDbKey' => null, ],
+                       ],
+                       $store->getNotificationTimestampsBatch( $user, $targets )
+               );
+       }
+
+       public function testGetNotificationTimestampsBatch_anonymousUser() {
+               $targets = [
+                       new TitleValue( 0, 'SomeDbKey' ),
+                       new TitleValue( 1, 'AnotherDbKey' ),
+               ];
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->never() )->method( $this->anything() );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( $this->anything() );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               $this->assertEquals(
+                       [
+                               0 => [ 'SomeDbKey' => false, ],
+                               1 => [ 'AnotherDbKey' => false, ],
+                       ],
+                       $store->getNotificationTimestampsBatch( $this->getAnonUser(), $targets )
                );
        }
 
@@ -876,10 +1809,11 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'selectRow' );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -908,10 +1842,11 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->will( $this->returnValue( [] ) );
 
                $mockCache = $this->getMockCache();
-               $mockCache->expects( $this->never() )
-                       ->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -945,6 +1880,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ) );
 
                $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'get' );
                $mockCache->expects( $this->once() )
                        ->method( 'set' )
                        ->with(
@@ -955,7 +1891,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'delete' )
                        ->with( '0:SomeDbKey:1' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -966,7 +1902,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        $callableCallCounter++;
                        $this->assertInternalType( 'callable', $callable );
                };
-               $store->overrideDeferredUpdatesAddCallableUpdateCallback( $mockCallback );
+               $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback( $mockCallback );
 
                $this->assertTrue(
                        $store->resetNotificationTimestamp(
@@ -975,6 +1911,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        )
                );
                $this->assertEquals( 1, $callableCallCounter );
+
+               ScopedCallback::consume( $scopedOverride );
        }
 
        public function testResetNotificationTimestamp_noItemForced() {
@@ -986,12 +1924,14 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'selectRow' );
 
                $mockCache = $this->getMockCache();
+               $mockDb->expects( $this->never() )
+                       ->method( 'get' );
                $mockDb->expects( $this->never() )
                        ->method( 'set' );
                $mockDb->expects( $this->never() )
                        ->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
@@ -1002,7 +1942,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        $callableCallCounter++;
                        $this->assertInternalType( 'callable', $callable );
                };
-               $store->overrideDeferredUpdatesAddCallableUpdateCallback( $mockCallback );
+               $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback( $mockCallback );
 
                $this->assertTrue(
                        $store->resetNotificationTimestamp(
@@ -1012,6 +1952,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        )
                );
                $this->assertEquals( 1, $callableCallCounter );
+
+               ScopedCallback::consume( $scopedOverride );
        }
 
        /**
@@ -1048,19 +1990,21 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'selectRow' );
 
                $mockCache = $this->getMockCache();
+               $mockDb->expects( $this->never() )
+                       ->method( 'get' );
                $mockDb->expects( $this->never() )
                        ->method( 'set' );
                $mockDb->expects( $this->never() )
                        ->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
                // Note: This does not actually assert the job is correct
                $callableCallCounter = 0;
-               $store->overrideDeferredUpdatesAddCallableUpdateCallback(
+               $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
                        function( $callable ) use ( &$callableCallCounter ) {
                                $callableCallCounter++;
                                $this->assertInternalType( 'callable', $callable );
@@ -1076,6 +2020,8 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        )
                );
                $this->assertEquals( 1, $callableCallCounter );
+
+               ScopedCallback::consume( $scopedOverride );
        }
 
        public function testResetNotificationTimestamp_oldidSpecifiedNotLatestRevisionForced() {
@@ -1104,19 +2050,21 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ) );
 
                $mockCache = $this->getMockCache();
+               $mockDb->expects( $this->never() )
+                       ->method( 'get' );
                $mockDb->expects( $this->never() )
                        ->method( 'set' );
                $mockDb->expects( $this->never() )
                        ->method( 'delete' );
 
-               $store = new WatchedItemStore(
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
                        $mockCache
                );
 
                // Note: This does not actually assert the job is correct
                $addUpdateCallCounter = 0;
-               $store->overrideDeferredUpdatesAddCallableUpdateCallback(
+               $scopedOverrideDeferred = $store->overrideDeferredUpdatesAddCallableUpdateCallback(
                        function( $callable ) use ( &$addUpdateCallCounter ) {
                                $addUpdateCallCounter++;
                                $this->assertInternalType( 'callable', $callable );
@@ -1124,7 +2072,7 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                );
 
                $getTimestampCallCounter = 0;
-               $store->overrideRevisionGetTimestampFromIdCallback(
+               $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback(
                        function( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) {
                                $getTimestampCallCounter++;
                                $this->assertEquals( $title, $titleParam );
@@ -1142,6 +2090,9 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                );
                $this->assertEquals( 1, $addUpdateCallCounter );
                $this->assertEquals( 1, $getTimestampCallCounter );
+
+               ScopedCallback::consume( $scopedOverrideDeferred );
+               ScopedCallback::consume( $scopedOverrideRevision );
        }
 
        public function testUpdateNotificationTimestamp_watchersExist() {
@@ -1182,9 +2133,14 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                                ]
                        );
 
-               $store = new WatchedItemStore(
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
-                       new HashBagOStuff( [ 'maxKeys' => 100 ] )
+                       $mockCache
                );
 
                $this->assertEquals(
@@ -1219,9 +2175,14 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                $mockDb->expects( $this->never() )
                        ->method( 'update' );
 
-               $store = new WatchedItemStore(
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->never() )->method( 'set' );
+               $mockCache->expects( $this->never() )->method( 'get' );
+               $mockCache->expects( $this->never() )->method( 'delete' );
+
+               $store = $this->newWatchedItemStore(
                        $this->getMockLoadBalancer( $mockDb ),
-                       new HashBagOStuff( [ 'maxKeys' => 100 ] )
+                       $mockCache
                );
 
                $watchers = $store->updateNotificationTimestamp(
@@ -1233,4 +2194,57 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                $this->assertEmpty( $watchers );
        }
 
+       public function testUpdateNotificationTimestamp_clearsCachedItems() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+               $titleValue = new TitleValue( 0, 'SomeDbKey' );
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->once() )
+                       ->method( 'selectRow' )
+                       ->will( $this->returnValue(
+                               $this->getFakeRow( [ 'wl_notificationtimestamp' => '20151212010101' ] )
+                       ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'select' )
+                       ->will(
+                               $this->returnValue( [
+                                       $this->getFakeRow( [ 'wl_user' => '2' ] ),
+                                       $this->getFakeRow( [ 'wl_user' => '3' ] )
+                               ] )
+                       );
+               $mockDb->expects( $this->once() )
+                       ->method( 'onTransactionIdle' )
+                       ->with( $this->isType( 'callable' ) )
+                       ->will( $this->returnCallback( function( $callable ) {
+                               $callable();
+                       } ) );
+               $mockDb->expects( $this->once() )
+                       ->method( 'update' );
+
+               $mockCache = $this->getMockCache();
+               $mockCache->expects( $this->once() )
+                       ->method( 'set' )
+                       ->with( '0:SomeDbKey:1', $this->isType( 'object' ) );
+               $mockCache->expects( $this->once() )
+                       ->method( 'get' )
+                       ->with( '0:SomeDbKey:1' );
+               $mockCache->expects( $this->once() )
+                       ->method( 'delete' )
+                       ->with( '0:SomeDbKey:1' );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $mockCache
+               );
+
+               // This will add the item to the cache
+               $store->getWatchedItem( $user, $titleValue );
+
+               $store->updateNotificationTimestamp(
+                       $this->getMockNonAnonUserWithId( 1 ),
+                       $titleValue,
+                       '20151212010101'
+               );
+       }
+
 }
index bc37311..b4eaa76 100644 (file)
@@ -51,13 +51,15 @@ class WatchedItemUnitTest extends PHPUnit_Framework_TestCase {
                        ->method( 'loadWatchedItem' )
                        ->with( $user, $linkTarget )
                        ->will( $this->returnValue( new WatchedItem( $user, $linkTarget, $timestamp ) ) );
-               WatchedItemStore::overrideDefaultInstance( $store );
+               $scopedOverride = WatchedItemStore::overrideDefaultInstance( $store );
 
                $item = WatchedItem::fromUserTitle( $user, $linkTarget, User::IGNORE_USER_RIGHTS );
 
                $this->assertEquals( $user, $item->getUser() );
                $this->assertEquals( $linkTarget, $item->getLinkTarget() );
                $this->assertEquals( $timestamp, $item->getNotificationTimestamp() );
+
+               ScopedCallback::consume( $scopedOverride );
        }
 
        /**
@@ -83,10 +85,12 @@ class WatchedItemUnitTest extends PHPUnit_Framework_TestCase {
                                        return true;
                                }
                        ) );
-               WatchedItemStore::overrideDefaultInstance( $store );
+               $scopedOverride = WatchedItemStore::overrideDefaultInstance( $store );
 
                $item = new WatchedItem( $user, $linkTarget, $timestamp );
                $item->resetNotificationTimestamp( $force, $oldid );
+
+               ScopedCallback::consume( $scopedOverride );
        }
 
        public function testAddWatch() {
@@ -153,31 +157,47 @@ class WatchedItemUnitTest extends PHPUnit_Framework_TestCase {
                $store->expects( $this->once() )
                        ->method( 'duplicateAllAssociatedEntries' )
                        ->with( $oldTitle, $newTitle );
-               WatchedItemStore::overrideDefaultInstance( $store );
+               $scopedOverride = WatchedItemStore::overrideDefaultInstance( $store );
 
                WatchedItem::duplicateEntries( $oldTitle, $newTitle );
+
+               ScopedCallback::consume( $scopedOverride );
        }
 
        public function testBatchAddWatch() {
-               /** @var WatchedItem[] $items */
-               $items = [
-                       new WatchedItem( User::newFromId( 1 ), new TitleValue( 0, 'Title1' ), null ),
-                       new WatchedItem( User::newFromId( 3 ), Title::newFromText( 'Title2' ), '20150101010101' ),
-               ];
-
-               $userTargetCombinations = [];
-               foreach ( $items as $item ) {
-                       $userTargetCombinations[] = [ $item->getUser(), $item->getTitle()->getSubjectPage() ];
-                       $userTargetCombinations[] = [ $item->getUser(), $item->getTitle()->getTalkPage() ];
-               }
+               $itemOne = new WatchedItem( User::newFromId( 1 ), new TitleValue( 0, 'Title1' ), null );
+               $itemTwo = new WatchedItem(
+                       User::newFromId( 3 ),
+                       Title::newFromText( 'Title2' ),
+                       '20150101010101'
+               );
 
                $store = $this->getMockWatchedItemStore();
-               $store->expects( $this->once() )
-                       ->method( 'addWatchBatch' )
-                       ->with( $userTargetCombinations );
-               WatchedItemStore::overrideDefaultInstance( $store );
-
-               WatchedItem::batchAddWatch( $items );
+               $store->expects( $this->exactly( 2 ) )
+                       ->method( 'addWatchBatchForUser' );
+               $store->expects( $this->at( 0 ) )
+                       ->method( 'addWatchBatchForUser' )
+                       ->with(
+                               $itemOne->getUser(),
+                               [
+                                       $itemOne->getTitle()->getSubjectPage(),
+                                       $itemOne->getTitle()->getTalkPage(),
+                               ]
+                       );
+               $store->expects( $this->at( 1 ) )
+                       ->method( 'addWatchBatchForUser' )
+                       ->with(
+                               $itemTwo->getUser(),
+                               [
+                                       $itemTwo->getTitle()->getSubjectPage(),
+                                       $itemTwo->getTitle()->getTalkPage(),
+                               ]
+                       );
+               $scopedOverride = WatchedItemStore::overrideDefaultInstance( $store );
+
+               WatchedItem::batchAddWatch( [ $itemOne, $itemTwo ] );
+
+               ScopedCallback::consume( $scopedOverride );
        }
 
 }
index c5314cb..00d429e 100644 (file)
@@ -31,6 +31,7 @@ class XmlTest extends MediaWikiTestCase {
                $this->setMwGlobals( [
                        'wgLang' => $langObj,
                        'wgWellFormedXml' => true,
+                       'wgUseMediaWikiUIEverywhere' => false,
                ] );
        }
 
@@ -152,7 +153,7 @@ class XmlTest extends MediaWikiTestCase {
 
                $this->assertEquals(
                        '<label for="year">From year (and earlier):</label> ' .
-                               '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year" /> ' .
+                               '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year"/> ' .
                                '<label for="month">From month (and earlier):</label> ' .
                                '<select name="month" id="month" class="mw-month-selector">' .
                                '<option value="-1">all</option>' . "\n" .
@@ -173,7 +174,7 @@ class XmlTest extends MediaWikiTestCase {
                );
                $this->assertEquals(
                        '<label for="year">From year (and earlier):</label> ' .
-                               '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year" /> ' .
+                               '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year"/> ' .
                                '<label for="month">From month (and earlier):</label> ' .
                                '<select name="month" id="month" class="mw-month-selector">' .
                                '<option value="-1">all</option>' . "\n" .
@@ -207,7 +208,7 @@ class XmlTest extends MediaWikiTestCase {
 
                $this->assertEquals(
                        '<label for="year">From year (and earlier):</label> ' .
-                               '<input id="year" maxlength="4" size="7" type="number" name="year" /> ' .
+                               '<input id="year" maxlength="4" size="7" type="number" name="year"/> ' .
                                '<label for="month">From month (and earlier):</label> ' .
                                '<select name="month" id="month" class="mw-month-selector">' .
                                '<option value="-1">all</option>' . "\n" .
index f51997c..d2dccf9 100644 (file)
@@ -17,7 +17,7 @@ class ApiBlockTest extends ApiTestCase {
                return $this->getTokenList( self::$users['sysop'] );
        }
 
-       function addDBData() {
+       function addDBDataOnce() {
                $user = User::newFromName( 'UTApiBlockee' );
 
                if ( $user->getId() == 0 ) {
index 00701db..bcd884e 100644 (file)
@@ -27,7 +27,7 @@ class ApiLoginTest extends ApiTestCase {
                global $wgServer;
 
                $user = self::$users['sysop'];
-               $user->getUser()->logOut();
+               $user->getUser()->logout();
 
                if ( !isset( $wgServer ) ) {
                        $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
@@ -72,7 +72,7 @@ class ApiLoginTest extends ApiTestCase {
                }
 
                $user = self::$users['sysop'];
-               $user->getUser()->logOut();
+               $user->getUser()->logout();
 
                $ret = $this->doApiRequest( [
                                "action" => "login",
@@ -153,7 +153,7 @@ class ApiLoginTest extends ApiTestCase {
                $this->assertNotEquals( false, $serverName );
                $serializedCookie = $cj->serializeToHttpRequest( $wgScriptPath, $serverName );
                $this->assertNotEquals( '', $serializedCookie );
-               $this->assertRegexp(
+               $this->assertRegExp(
                        '/_session=[^;]*; .*UserID=[0-9]*; .*UserName=' . $user->userName . '; .*Token=/',
                        $serializedCookie
                );
@@ -193,7 +193,7 @@ class ApiLoginTest extends ApiTestCase {
                $this->setMwGlobals( [
                        'wgSessionProviders' => array_merge( $wgSessionProviders, [
                                [
-                                       'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider',
+                                       'class' => MediaWiki\Session\BotPasswordSessionProvider::class,
                                        'args' => [ [ 'priority' => 40 ] ],
                                ]
                        ] ),
@@ -207,14 +207,14 @@ class ApiLoginTest extends ApiTestCase {
 
                // Make sure our session provider is present
                $manager = TestingAccessWrapper::newFromObject( MediaWiki\Session\SessionManager::singleton() );
-               if ( !isset( $manager->sessionProviders['MediaWiki\\Session\\BotPasswordSessionProvider'] ) ) {
+               if ( !isset( $manager->sessionProviders[MediaWiki\Session\BotPasswordSessionProvider::class] ) ) {
                        $tmp = $manager->sessionProviders;
                        $manager->sessionProviders = null;
                        $manager->sessionProviders = $tmp + $manager->getProviders();
                }
                $this->assertNotNull(
                        MediaWiki\Session\SessionManager::singleton()->getProvider(
-                               'MediaWiki\\Session\\BotPasswordSessionProvider'
+                               MediaWiki\Session\BotPasswordSessionProvider::class
                        ),
                        'sanity check'
                );
index bacc061..873917e 100644 (file)
@@ -137,7 +137,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $this->assertFalse( $exception );
 
                // clean up
-               $this->deleteFileByFilename( $fileName );
+               $this->deleteFileByFileName( $fileName );
        }
 
        /**
@@ -173,7 +173,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $this->assertTrue( $exception );
 
                // clean up
-               $this->deleteFileByFilename( $fileName );
+               $this->deleteFileByFileName( $fileName );
        }
 
        /**
@@ -243,7 +243,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $this->assertFalse( $exception );
 
                // clean up
-               $this->deleteFileByFilename( $fileName );
+               $this->deleteFileByFileName( $fileName );
        }
 
        /**
@@ -322,8 +322,8 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $this->assertFalse( $exception );
 
                // clean up
-               $this->deleteFileByFilename( $fileNames[0] );
-               $this->deleteFileByFilename( $fileNames[1] );
+               $this->deleteFileByFileName( $fileNames[0] );
+               $this->deleteFileByFileName( $fileNames[1] );
        }
 
        /**
@@ -406,7 +406,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $this->assertFalse( $exception, "No UsageException exception." );
 
                // clean up
-               $this->deleteFileByFilename( $fileName );
+               $this->deleteFileByFileName( $fileName );
        }
 
        /**
@@ -550,6 +550,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
                $this->assertFalse( $exception );
 
                // clean up
-               $this->deleteFileByFilename( $fileName );
+               $this->deleteFileByFileName( $fileName );
        }
 }
index 1f4e26c..9942a0f 100644 (file)
@@ -10,7 +10,7 @@ class UserWrapper {
                $this->password = $password;
 
                $this->user = User::newFromName( $this->userName );
-               if ( !$this->user->getID() ) {
+               if ( !$this->user->getId() ) {
                        $this->user = User::createNew( $this->userName, [
                                "email" => "test@example.com",
                                "real_name" => "Test User" ] );
index 690ba3a..0028bbb 100644 (file)
@@ -22,80 +22,80 @@ class ApiFormatPhpTest extends ApiFormatTestBase {
        public static function provideGeneralEncoding() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
                return array_merge(
-                       self::addFormatVersion( 1, array(
+                       self::addFormatVersion( 1, [
                                // Basic types
-                               array( array( null ), 'a:1:{i:0;N;}' ),
-                               array( array( true ), 'a:1:{i:0;s:0:"";}' ),
-                               array( array( false ), 'a:0:{}' ),
-                               array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
-                                       'a:1:{i:0;b:1;}' ),
-                               array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
-                                       'a:1:{i:0;b:0;}' ),
-                               array( array( 42 ), 'a:1:{i:0;i:42;}' ),
-                               array( array( 42.5 ), 'a:1:{i:0;d:42.5;}' ),
-                               array( array( 1e42 ), 'a:1:{i:0;d:1.0E+42;}' ),
-                               array( array( 'foo' ), 'a:1:{i:0;s:3:"foo";}' ),
-                               array( array( 'fóo' ), 'a:1:{i:0;s:4:"fóo";}' ),
+                               [ [ null ], 'a:1:{i:0;N;}' ],
+                               [ [ true ], 'a:1:{i:0;s:0:"";}' ],
+                               [ [ false ], 'a:0:{}' ],
+                               [ [ true, ApiResult::META_BC_BOOLS => [ 0 ] ],
+                                       'a:1:{i:0;b:1;}' ],
+                               [ [ false, ApiResult::META_BC_BOOLS => [ 0 ] ],
+                                       'a:1:{i:0;b:0;}' ],
+                               [ [ 42 ], 'a:1:{i:0;i:42;}' ],
+                               [ [ 42.5 ], 'a:1:{i:0;d:42.5;}' ],
+                               [ [ 1e42 ], 'a:1:{i:0;d:1.0E+42;}' ],
+                               [ [ 'foo' ], 'a:1:{i:0;s:3:"foo";}' ],
+                               [ [ 'fóo' ], 'a:1:{i:0;s:4:"fóo";}' ],
 
                                // Arrays and objects
-                               array( array( array() ), 'a:1:{i:0;a:0:{}}' ),
-                               array( array( array( 1 ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
-                               array( array( array( 'x' => 1 ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
-                               array( array( array( 2 => 1 ) ), 'a:1:{i:0;a:1:{i:2;i:1;}}' ),
-                               array( array( (object)array() ), 'a:1:{i:0;a:0:{}}' ),
-                               array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
-                                       'a:1:{i:0;a:1:{i:0;a:2:{s:3:"key";s:1:"x";s:1:"*";i:1;}}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
-                               array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ),
+                               [ [ [] ], 'a:1:{i:0;a:0:{}}' ],
+                               [ [ [ 1 ] ], 'a:1:{i:0;a:1:{i:0;i:1;}}' ],
+                               [ [ [ 'x' => 1 ] ], 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ],
+                               [ [ [ 2 => 1 ] ], 'a:1:{i:0;a:1:{i:2;i:1;}}' ],
+                               [ [ (object)[] ], 'a:1:{i:0;a:0:{}}' ],
+                               [ [ [ 1, ApiResult::META_TYPE => 'assoc' ] ], 'a:1:{i:0;a:1:{i:0;i:1;}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'array' ] ], 'a:1:{i:0;a:1:{i:0;i:1;}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'kvp' ] ], 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ] ],
+                                       'a:1:{i:0;a:1:{i:0;a:2:{s:3:"key";s:1:"x";s:1:"*";i:1;}}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'BCarray' ] ], 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ],
+                               [ [ [ 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ] ], 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ],
 
                                // Content
-                               array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
-                                       'a:1:{s:1:"*";s:3:"foo";}' ),
+                               [ [ 'content' => 'foo', ApiResult::META_CONTENT => 'content' ],
+                                       'a:1:{s:1:"*";s:3:"foo";}' ],
 
                                // BC Subelements
-                               array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
-                                       'a:1:{s:3:"foo";a:1:{s:1:"*";s:3:"foo";}}' ),
-                       ) ),
-                       self::addFormatVersion( 2, array(
+                               [ [ 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => [ 'foo' ] ],
+                                       'a:1:{s:3:"foo";a:1:{s:1:"*";s:3:"foo";}}' ],
+                       ] ),
+                       self::addFormatVersion( 2, [
                                // Basic types
-                               array( array( null ), 'a:1:{i:0;N;}' ),
-                               array( array( true ), 'a:1:{i:0;b:1;}' ),
-                               array( array( false ), 'a:1:{i:0;b:0;}' ),
-                               array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
-                                       'a:1:{i:0;b:1;}' ),
-                               array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
-                                       'a:1:{i:0;b:0;}' ),
-                               array( array( 42 ), 'a:1:{i:0;i:42;}' ),
-                               array( array( 42.5 ), 'a:1:{i:0;d:42.5;}' ),
-                               array( array( 1e42 ), 'a:1:{i:0;d:1.0E+42;}' ),
-                               array( array( 'foo' ), 'a:1:{i:0;s:3:"foo";}' ),
-                               array( array( 'fóo' ), 'a:1:{i:0;s:4:"fóo";}' ),
+                               [ [ null ], 'a:1:{i:0;N;}' ],
+                               [ [ true ], 'a:1:{i:0;b:1;}' ],
+                               [ [ false ], 'a:1:{i:0;b:0;}' ],
+                               [ [ true, ApiResult::META_BC_BOOLS => [ 0 ] ],
+                                       'a:1:{i:0;b:1;}' ],
+                               [ [ false, ApiResult::META_BC_BOOLS => [ 0 ] ],
+                                       'a:1:{i:0;b:0;}' ],
+                               [ [ 42 ], 'a:1:{i:0;i:42;}' ],
+                               [ [ 42.5 ], 'a:1:{i:0;d:42.5;}' ],
+                               [ [ 1e42 ], 'a:1:{i:0;d:1.0E+42;}' ],
+                               [ [ 'foo' ], 'a:1:{i:0;s:3:"foo";}' ],
+                               [ [ 'fóo' ], 'a:1:{i:0;s:4:"fóo";}' ],
 
                                // Arrays and objects
-                               array( array( array() ), 'a:1:{i:0;a:0:{}}' ),
-                               array( array( array( 1 ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
-                               array( array( array( 'x' => 1 ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
-                               array( array( array( 2 => 1 ) ), 'a:1:{i:0;a:1:{i:2;i:1;}}' ),
-                               array( array( (object)array() ), 'a:1:{i:0;a:0:{}}' ),
-                               array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
-                                       'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
-                               array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
-                               array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ),
+                               [ [ [] ], 'a:1:{i:0;a:0:{}}' ],
+                               [ [ [ 1 ] ], 'a:1:{i:0;a:1:{i:0;i:1;}}' ],
+                               [ [ [ 'x' => 1 ] ], 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ],
+                               [ [ [ 2 => 1 ] ], 'a:1:{i:0;a:1:{i:2;i:1;}}' ],
+                               [ [ (object)[] ], 'a:1:{i:0;a:0:{}}' ],
+                               [ [ [ 1, ApiResult::META_TYPE => 'assoc' ] ], 'a:1:{i:0;a:1:{i:0;i:1;}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'array' ] ], 'a:1:{i:0;a:1:{i:0;i:1;}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'kvp' ] ], 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ] ],
+                                       'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ],
+                               [ [ [ 'x' => 1, ApiResult::META_TYPE => 'BCarray' ] ], 'a:1:{i:0;a:1:{i:0;i:1;}}' ],
+                               [ [ [ 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ] ], 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ],
 
                                // Content
-                               array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
-                                       'a:1:{s:7:"content";s:3:"foo";}' ),
+                               [ [ 'content' => 'foo', ApiResult::META_CONTENT => 'content' ],
+                                       'a:1:{s:7:"content";s:3:"foo";}' ],
 
                                // BC Subelements
-                               array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
-                                       'a:1:{s:3:"foo";s:3:"foo";}' ),
-                       ) )
+                               [ [ 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => [ 'foo' ] ],
+                                       'a:1:{s:3:"foo";s:3:"foo";}' ],
+                       ] )
                );
                // @codingStandardsIgnoreEnd
        }
index 0b7ae35..3fef0b0 100644 (file)
@@ -25,98 +25,98 @@ class ApiFormatXmlTest extends ApiFormatTestBase {
 
        public static function provideGeneralEncoding() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
+               return [
                        // Basic types
-                       array( array( null, 'a' => null ), '<?xml version="1.0"?><api><_v _idx="0" /></api>' ),
-                       array( array( true, 'a' => true ), '<?xml version="1.0"?><api a=""><_v _idx="0">true</_v></api>' ),
-                       array( array( false, 'a' => false ), '<?xml version="1.0"?><api><_v _idx="0">false</_v></api>' ),
-                       array( array( true, 'a' => true, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ),
-                               '<?xml version="1.0"?><api a=""><_v _idx="0">1</_v></api>' ),
-                       array( array( false, 'a' => false, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ),
-                               '<?xml version="1.0"?><api><_v _idx="0"></_v></api>' ),
-                       array( array( 42, 'a' => 42 ), '<?xml version="1.0"?><api a="42"><_v _idx="0">42</_v></api>' ),
-                       array( array( 42.5, 'a' => 42.5 ), '<?xml version="1.0"?><api a="42.5"><_v _idx="0">42.5</_v></api>' ),
-                       array( array( 1e42, 'a' => 1e42 ), '<?xml version="1.0"?><api a="1.0E+42"><_v _idx="0">1.0E+42</_v></api>' ),
-                       array( array( 'foo', 'a' => 'foo' ), '<?xml version="1.0"?><api a="foo"><_v _idx="0">foo</_v></api>' ),
-                       array( array( 'fóo', 'a' => 'fóo' ), '<?xml version="1.0"?><api a="fóo"><_v _idx="0">fóo</_v></api>' ),
+                       [ [ null, 'a' => null ], '<?xml version="1.0"?><api><_v _idx="0" /></api>' ],
+                       [ [ true, 'a' => true ], '<?xml version="1.0"?><api a=""><_v _idx="0">true</_v></api>' ],
+                       [ [ false, 'a' => false ], '<?xml version="1.0"?><api><_v _idx="0">false</_v></api>' ],
+                       [ [ true, 'a' => true, ApiResult::META_BC_BOOLS => [ 0, 'a' ] ],
+                               '<?xml version="1.0"?><api a=""><_v _idx="0">1</_v></api>' ],
+                       [ [ false, 'a' => false, ApiResult::META_BC_BOOLS => [ 0, 'a' ] ],
+                               '<?xml version="1.0"?><api><_v _idx="0"></_v></api>' ],
+                       [ [ 42, 'a' => 42 ], '<?xml version="1.0"?><api a="42"><_v _idx="0">42</_v></api>' ],
+                       [ [ 42.5, 'a' => 42.5 ], '<?xml version="1.0"?><api a="42.5"><_v _idx="0">42.5</_v></api>' ],
+                       [ [ 1e42, 'a' => 1e42 ], '<?xml version="1.0"?><api a="1.0E+42"><_v _idx="0">1.0E+42</_v></api>' ],
+                       [ [ 'foo', 'a' => 'foo' ], '<?xml version="1.0"?><api a="foo"><_v _idx="0">foo</_v></api>' ],
+                       [ [ 'fóo', 'a' => 'fóo' ], '<?xml version="1.0"?><api a="fóo"><_v _idx="0">fóo</_v></api>' ],
 
                        // Arrays and objects
-                       array( array( array() ), '<?xml version="1.0"?><api><_v /></api>' ),
-                       array( array( array( 'x' => 1 ) ), '<?xml version="1.0"?><api><_v x="1" /></api>' ),
-                       array( array( array( 2 => 1 ) ), '<?xml version="1.0"?><api><_v><_v _idx="2">1</_v></_v></api>' ),
-                       array( array( (object)array() ), '<?xml version="1.0"?><api><_v /></api>' ),
-                       array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '<?xml version="1.0"?><api><_v><_v _idx="0">1</_v></_v></api>' ),
-                       array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '<?xml version="1.0"?><api><_v><_v>1</_v></_v></api>' ),
-                       array( array( array( 'x' => 1, 'y' => array( 'z' => 1 ), ApiResult::META_TYPE => 'kvp' ) ),
-                               '<?xml version="1.0"?><api><_v><_v _name="x" xml:space="preserve">1</_v><_v _name="y"><z xml:space="preserve">1</z></_v></_v></api>' ),
-                       array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp', ApiResult::META_INDEXED_TAG_NAME => 'i', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
-                               '<?xml version="1.0"?><api><_v><i key="x" xml:space="preserve">1</i></_v></api>' ),
-                       array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
-                               '<?xml version="1.0"?><api><_v><_v key="x" xml:space="preserve">1</_v></_v></api>' ),
-                       array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '<?xml version="1.0"?><api><_v x="1" /></api>' ),
-                       array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '<?xml version="1.0"?><api><_v><_v _idx="0">a</_v><_v _idx="1">b</_v></_v></api>' ),
+                       [ [ [] ], '<?xml version="1.0"?><api><_v /></api>' ],
+                       [ [ [ 'x' => 1 ] ], '<?xml version="1.0"?><api><_v x="1" /></api>' ],
+                       [ [ [ 2 => 1 ] ], '<?xml version="1.0"?><api><_v><_v _idx="2">1</_v></_v></api>' ],
+                       [ [ (object)[] ], '<?xml version="1.0"?><api><_v /></api>' ],
+                       [ [ [ 1, ApiResult::META_TYPE => 'assoc' ] ], '<?xml version="1.0"?><api><_v><_v _idx="0">1</_v></_v></api>' ],
+                       [ [ [ 'x' => 1, ApiResult::META_TYPE => 'array' ] ], '<?xml version="1.0"?><api><_v><_v>1</_v></_v></api>' ],
+                       [ [ [ 'x' => 1, 'y' => [ 'z' => 1 ], ApiResult::META_TYPE => 'kvp' ] ],
+                               '<?xml version="1.0"?><api><_v><_v _name="x" xml:space="preserve">1</_v><_v _name="y"><z xml:space="preserve">1</z></_v></_v></api>' ],
+                       [ [ [ 'x' => 1, ApiResult::META_TYPE => 'kvp', ApiResult::META_INDEXED_TAG_NAME => 'i', ApiResult::META_KVP_KEY_NAME => 'key' ] ],
+                               '<?xml version="1.0"?><api><_v><i key="x" xml:space="preserve">1</i></_v></api>' ],
+                       [ [ [ 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ] ],
+                               '<?xml version="1.0"?><api><_v><_v key="x" xml:space="preserve">1</_v></_v></api>' ],
+                       [ [ [ 'x' => 1, ApiResult::META_TYPE => 'BCarray' ] ], '<?xml version="1.0"?><api><_v x="1" /></api>' ],
+                       [ [ [ 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ] ], '<?xml version="1.0"?><api><_v><_v _idx="0">a</_v><_v _idx="1">b</_v></_v></api>' ],
 
                        // Content
-                       array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
-                               '<?xml version="1.0"?><api xml:space="preserve">foo</api>' ),
+                       [ [ 'content' => 'foo', ApiResult::META_CONTENT => 'content' ],
+                               '<?xml version="1.0"?><api xml:space="preserve">foo</api>' ],
 
                        // Specified element name
-                       array( array( 'foo', 'bar', ApiResult::META_INDEXED_TAG_NAME => 'itn' ),
-                               '<?xml version="1.0"?><api><itn>foo</itn><itn>bar</itn></api>' ),
+                       [ [ 'foo', 'bar', ApiResult::META_INDEXED_TAG_NAME => 'itn' ],
+                               '<?xml version="1.0"?><api><itn>foo</itn><itn>bar</itn></api>' ],
 
                        // Subelements
-                       array( array( 'a' => 1, 's' => 1, '_subelements' => array( 's' ) ),
-                               '<?xml version="1.0"?><api a="1"><s xml:space="preserve">1</s></api>' ),
+                       [ [ 'a' => 1, 's' => 1, '_subelements' => [ 's' ] ],
+                               '<?xml version="1.0"?><api a="1"><s xml:space="preserve">1</s></api>' ],
 
                        // Content and subelement
-                       array( array( 'a' => 1, 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
-                               '<?xml version="1.0"?><api a="1" xml:space="preserve">foo</api>' ),
-                       array( array( 's' => array(), 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
-                               '<?xml version="1.0"?><api><s /><content xml:space="preserve">foo</content></api>' ),
-                       array(
-                               array(
+                       [ [ 'a' => 1, 'content' => 'foo', ApiResult::META_CONTENT => 'content' ],
+                               '<?xml version="1.0"?><api a="1" xml:space="preserve">foo</api>' ],
+                       [ [ 's' => [], 'content' => 'foo', ApiResult::META_CONTENT => 'content' ],
+                               '<?xml version="1.0"?><api><s /><content xml:space="preserve">foo</content></api>' ],
+                       [
+                               [
                                        's' => 1,
                                        'content' => 'foo',
                                        ApiResult::META_CONTENT => 'content',
-                                       ApiResult::META_SUBELEMENTS => array( 's' )
-                               ),
+                                       ApiResult::META_SUBELEMENTS => [ 's' ]
+                               ],
                                '<?xml version="1.0"?><api><s xml:space="preserve">1</s><content xml:space="preserve">foo</content></api>'
-                       ),
+                       ],
 
                        // BC Subelements
-                       array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
-                               '<?xml version="1.0"?><api><foo xml:space="preserve">foo</foo></api>' ),
+                       [ [ 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => [ 'foo' ] ],
+                               '<?xml version="1.0"?><api><foo xml:space="preserve">foo</foo></api>' ],
 
                        // Name mangling
-                       array( array( 'foo.bar' => 1 ), '<?xml version="1.0"?><api foo.bar="1" />' ),
-                       array( array( '' => 1 ), '<?xml version="1.0"?><api _="1" />' ),
-                       array( array( 'foo bar' => 1 ), '<?xml version="1.0"?><api _foo.20.bar="1" />' ),
-                       array( array( 'foo:bar' => 1 ), '<?xml version="1.0"?><api _foo.3A.bar="1" />' ),
-                       array( array( 'foo%.bar' => 1 ), '<?xml version="1.0"?><api _foo.25..2E.bar="1" />' ),
-                       array( array( '4foo' => 1, 'foo4' => 1 ), '<?xml version="1.0"?><api _4foo="1" foo4="1" />' ),
-                       array( array( "foo\xe3\x80\x80bar" => 1 ), '<?xml version="1.0"?><api _foo.3000.bar="1" />' ),
-                       array( array( 'foo:bar' => 1, ApiResult::META_PRESERVE_KEYS => array( 'foo:bar' ) ),
-                               '<?xml version="1.0"?><api foo:bar="1" />' ),
-                       array( array( 'a', 'b', ApiResult::META_INDEXED_TAG_NAME => 'foo bar' ),
-                               '<?xml version="1.0"?><api><_foo.20.bar>a</_foo.20.bar><_foo.20.bar>b</_foo.20.bar></api>' ),
+                       [ [ 'foo.bar' => 1 ], '<?xml version="1.0"?><api foo.bar="1" />' ],
+                       [ [ '' => 1 ], '<?xml version="1.0"?><api _="1" />' ],
+                       [ [ 'foo bar' => 1 ], '<?xml version="1.0"?><api _foo.20.bar="1" />' ],
+                       [ [ 'foo:bar' => 1 ], '<?xml version="1.0"?><api _foo.3A.bar="1" />' ],
+                       [ [ 'foo%.bar' => 1 ], '<?xml version="1.0"?><api _foo.25..2E.bar="1" />' ],
+                       [ [ '4foo' => 1, 'foo4' => 1 ], '<?xml version="1.0"?><api _4foo="1" foo4="1" />' ],
+                       [ [ "foo\xe3\x80\x80bar" => 1 ], '<?xml version="1.0"?><api _foo.3000.bar="1" />' ],
+                       [ [ 'foo:bar' => 1, ApiResult::META_PRESERVE_KEYS => [ 'foo:bar' ] ],
+                               '<?xml version="1.0"?><api foo:bar="1" />' ],
+                       [ [ 'a', 'b', ApiResult::META_INDEXED_TAG_NAME => 'foo bar' ],
+                               '<?xml version="1.0"?><api><_foo.20.bar>a</_foo.20.bar><_foo.20.bar>b</_foo.20.bar></api>' ],
 
                        // includenamespace param
-                       array( array( 'x' => 'foo' ), '<?xml version="1.0"?><api x="foo" xmlns="http://www.mediawiki.org/xml/api/" />',
-                               array( 'includexmlnamespace' => 1 ) ),
+                       [ [ 'x' => 'foo' ], '<?xml version="1.0"?><api x="foo" xmlns="http://www.mediawiki.org/xml/api/" />',
+                               [ 'includexmlnamespace' => 1 ] ],
 
                        // xslt param
-                       array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Invalid or non-existent stylesheet specified</xml></warnings></api>',
-                               array( 'xslt' => 'DoesNotExist' ) ),
-                       array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should be in the MediaWiki namespace.</xml></warnings></api>',
-                               array( 'xslt' => 'ApiFormatXmlTest' ) ),
-                       array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should have .xsl extension.</xml></warnings></api>',
-                               array( 'xslt' => 'MediaWiki:ApiFormatXmlTest' ) ),
-                       array( array(),
+                       [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Invalid or non-existent stylesheet specified</xml></warnings></api>',
+                               [ 'xslt' => 'DoesNotExist' ] ],
+                       [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should be in the MediaWiki namespace.</xml></warnings></api>',
+                               [ 'xslt' => 'ApiFormatXmlTest' ] ],
+                       [ [], '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should have .xsl extension.</xml></warnings></api>',
+                               [ 'xslt' => 'MediaWiki:ApiFormatXmlTest' ] ],
+                       [ [],
                                '<?xml version="1.0"?><?xml-stylesheet href="' .
                                        htmlspecialchars( Title::newFromText( 'MediaWiki:ApiFormatXmlTest.xsl' )->getLocalURL( 'action=raw' ) ) .
                                        '" type="text/xsl" ?><api />',
-                               array( 'xslt' => 'MediaWiki:ApiFormatXmlTest.xsl' ) ),
-               );
+                               [ 'xslt' => 'MediaWiki:ApiFormatXmlTest.xsl' ] ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index 9ba4587..e5971b4 100644 (file)
@@ -36,9 +36,10 @@ class ApiQueryBasicTest extends ApiQueryTestBase {
 
        /**
         * Create a set of pages. These must not change, otherwise the tests might give wrong results.
-        * @see MediaWikiTestCase::addDBData()
+        *
+*@see MediaWikiTestCase::addDBDataOnce()
         */
-       function addDBData() {
+       function addDBDataOnce() {
                try {
                        if ( Title::newFromText( 'AQBT-All' )->exists() ) {
                                return;
index 8f11a51..944d31c 100644 (file)
@@ -29,9 +29,10 @@ class ApiQueryContinue2Test extends ApiQueryContinueTestBase {
 
        /**
         * Create a set of pages. These must not change, otherwise the tests might give wrong results.
-        * @see MediaWikiTestCase::addDBData()
+        *
+*@see MediaWikiTestCase::addDBDataOnce()
         */
-       function addDBData() {
+       function addDBDataOnce() {
                try {
                        $this->editPage( 'AQCT73462-A', '**AQCT73462-A**  [[AQCT73462-B]] [[AQCT73462-C]]' );
                        $this->editPage( 'AQCT73462-B', '[[AQCT73462-A]]  **AQCT73462-B** [[AQCT73462-C]]' );
index a6269ed..b31627b 100644 (file)
@@ -33,9 +33,10 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
 
        /**
         * Create a set of pages. These must not change, otherwise the tests might give wrong results.
-        * @see MediaWikiTestCase::addDBData()
+        *
+*@see MediaWikiTestCase::addDBDataOnce()
         */
-       function addDBData() {
+       function addDBDataOnce() {
                try {
                        $this->editPage( 'Template:AQCT-T1', '**Template:AQCT-T1**' );
                        $this->editPage( 'Template:AQCT-T2', '**Template:AQCT-T2**' );
index a441b3d..e329f8d 100644 (file)
@@ -6,12 +6,12 @@
  */
 class GenderCacheTest extends MediaWikiLangTestCase {
 
-       function addDBData() {
+       function addDBDataOnce() {
                // ensure the correct default gender
                $this->mergeMwGlobalArrayValue( 'wgDefaultUserOptions', [ 'gender' => 'unknown' ] );
 
                $user = User::newFromName( 'UTMale' );
-               if ( $user->getID() == 0 ) {
+               if ( $user->getId() == 0 ) {
                        $user->addToDatabase();
                        TestUser::setPasswordForUser( $user, 'UTMalePassword' );
                }
@@ -20,7 +20,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
                $user->saveSettings();
 
                $user = User::newFromName( 'UTFemale' );
-               if ( $user->getID() == 0 ) {
+               if ( $user->getId() == 0 ) {
                        $user->addToDatabase();
                        TestUser::setPasswordForUser( $user, 'UTFemalePassword' );
                }
@@ -29,7 +29,7 @@ class GenderCacheTest extends MediaWikiLangTestCase {
                $user->saveSettings();
 
                $user = User::newFromName( 'UTDefaultGender' );
-               if ( $user->getID() == 0 ) {
+               if ( $user->getId() == 0 ) {
                        $user->addToDatabase();
                        TestUser::setPasswordForUser( $user, 'UTDefaultGenderPassword' );
                }
index 7d62b01..697eb2d 100644 (file)
@@ -15,7 +15,7 @@ class LocalisationCacheTest extends MediaWikiTestCase {
        }
 
        /**
-        * @return PHPUnit_Framework_MockObject_MockObject|LocalisationCache
+        * @return LocalisationCache
         */
        protected function getMockLocalisationCache() {
                global $IP;
index 38cc863..bd744c0 100644 (file)
@@ -23,7 +23,7 @@ class MessageCacheTest extends MediaWikiLangTestCase {
                $this->setContentLang( 'de' );
        }
 
-       function addDBData() {
+       function addDBDataOnce() {
                $this->configureLanguages();
 
                // Set up messages and fallbacks ab -> ru -> de
index 70da12e..6369b33 100644 (file)
@@ -24,6 +24,16 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
         */
        private static $mockRecentChange;
 
+       /**
+        * @var Revision
+        */
+       private static $pageRev = null;
+
+       /**
+        * @var string
+        */
+       private static $pageName = 'CategoryMembershipChangeTestPage';
+
        public static function newForCategorizationCallback() {
                self::$lastNotifyArgs = func_get_args();
                self::$notifyCallCounter += 1;
@@ -34,10 +44,20 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
                parent::setUp();
                self::$notifyCallCounter = 0;
                self::$mockRecentChange = self::getMock( 'RecentChange' );
+
+               $this->setContentLang( 'qqx' );
+       }
+
+       public function addDBDataOnce() {
+               $info = $this->insertPage( self::$pageName );
+               $title = $info['title'];
+
+               $page = WikiPage::factory( $title );
+               self::$pageRev = $page->getRevision();
        }
 
        private function newChange( Revision $revision = null ) {
-               $change = new CategoryMembershipChange( Title::newFromText( 'UTPage' ), $revision );
+               $change = new CategoryMembershipChange( Title::newFromText( self::$pageName ), $revision );
                $change->overrideNewForCategorizationCallback(
                        'CategoryMembershipChangeTest::newForCategorizationCallback'
                );
@@ -53,9 +73,10 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
 
                $this->assertTrue( strlen( self::$lastNotifyArgs[0] ) === 14 );
                $this->assertEquals( 'Category:CategoryName', self::$lastNotifyArgs[1]->getPrefixedText() );
-               $this->assertEquals( 'MediaWiki automatic change', self::$lastNotifyArgs[2]->getName() );
-               $this->assertEquals( '[[:UTPage]] added to category', self::$lastNotifyArgs[3] );
-               $this->assertEquals( 'UTPage', self::$lastNotifyArgs[4]->getPrefixedText() );
+               $this->assertEquals( '(autochange-username)', self::$lastNotifyArgs[2]->getName() );
+               $this->assertEquals( '(recentchanges-page-added-to-category: ' . self::$pageName . ', 0)',
+                       self::$lastNotifyArgs[3] );
+               $this->assertEquals( self::$pageName, self::$lastNotifyArgs[4]->getPrefixedText() );
                $this->assertEquals( 0, self::$lastNotifyArgs[5] );
                $this->assertEquals( 0, self::$lastNotifyArgs[6] );
                $this->assertEquals( null, self::$lastNotifyArgs[7] );
@@ -72,9 +93,10 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
 
                $this->assertTrue( strlen( self::$lastNotifyArgs[0] ) === 14 );
                $this->assertEquals( 'Category:CategoryName', self::$lastNotifyArgs[1]->getPrefixedText() );
-               $this->assertEquals( 'MediaWiki automatic change', self::$lastNotifyArgs[2]->getName() );
-               $this->assertEquals( '[[:UTPage]] removed from category', self::$lastNotifyArgs[3] );
-               $this->assertEquals( 'UTPage', self::$lastNotifyArgs[4]->getPrefixedText() );
+               $this->assertEquals( '(autochange-username)', self::$lastNotifyArgs[2]->getName() );
+               $this->assertEquals( '(recentchanges-page-removed-from-category: ' . self::$pageName . ', 0)',
+                       self::$lastNotifyArgs[3] );
+               $this->assertEquals( self::$pageName, self::$lastNotifyArgs[4]->getPrefixedText() );
                $this->assertEquals( 0, self::$lastNotifyArgs[5] );
                $this->assertEquals( 0, self::$lastNotifyArgs[6] );
                $this->assertEquals( null, self::$lastNotifyArgs[7] );
@@ -84,7 +106,7 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
        }
 
        public function testChangeAddedWithRev() {
-               $revision = Revision::newFromId( Title::newFromText( 'UTPage' )->getLatestRevID() );
+               $revision = Revision::newFromId( Title::newFromText( self::$pageName )->getLatestRevID() );
                $change = $this->newChange( $revision );
                $change->triggerCategoryAddedNotification( Title::newFromText( 'CategoryName', NS_CATEGORY ) );
 
@@ -93,9 +115,10 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
                $this->assertTrue( strlen( self::$lastNotifyArgs[0] ) === 14 );
                $this->assertEquals( 'Category:CategoryName', self::$lastNotifyArgs[1]->getPrefixedText() );
                $this->assertEquals( 'UTSysop', self::$lastNotifyArgs[2]->getName() );
-               $this->assertEquals( '[[:UTPage]] added to category', self::$lastNotifyArgs[3] );
-               $this->assertEquals( 'UTPage', self::$lastNotifyArgs[4]->getPrefixedText() );
-               $this->assertEquals( 0, self::$lastNotifyArgs[5] );
+               $this->assertEquals( '(recentchanges-page-added-to-category: ' . self::$pageName . ', 0)',
+                       self::$lastNotifyArgs[3] );
+               $this->assertEquals( self::$pageName, self::$lastNotifyArgs[4]->getPrefixedText() );
+               $this->assertEquals( self::$pageRev->getParentId(), self::$lastNotifyArgs[5] );
                $this->assertEquals( $revision->getId(), self::$lastNotifyArgs[6] );
                $this->assertEquals( null, self::$lastNotifyArgs[7] );
                $this->assertEquals( 0, self::$lastNotifyArgs[8] );
@@ -104,7 +127,7 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
        }
 
        public function testChangeRemovedWithRev() {
-               $revision = Revision::newFromId( Title::newFromText( 'UTPage' )->getLatestRevID() );
+               $revision = Revision::newFromId( Title::newFromText( self::$pageName )->getLatestRevID() );
                $change = $this->newChange( $revision );
                $change->triggerCategoryRemovedNotification( Title::newFromText( 'CategoryName', NS_CATEGORY ) );
 
@@ -113,9 +136,10 @@ class CategoryMembershipChangeTest extends MediaWikiLangTestCase {
                $this->assertTrue( strlen( self::$lastNotifyArgs[0] ) === 14 );
                $this->assertEquals( 'Category:CategoryName', self::$lastNotifyArgs[1]->getPrefixedText() );
                $this->assertEquals( 'UTSysop', self::$lastNotifyArgs[2]->getName() );
-               $this->assertEquals( '[[:UTPage]] removed from category', self::$lastNotifyArgs[3] );
-               $this->assertEquals( 'UTPage', self::$lastNotifyArgs[4]->getPrefixedText() );
-               $this->assertEquals( 0, self::$lastNotifyArgs[5] );
+               $this->assertEquals( '(recentchanges-page-removed-from-category: ' . self::$pageName . ', 0)',
+                       self::$lastNotifyArgs[3] );
+               $this->assertEquals( self::$pageName, self::$lastNotifyArgs[4]->getPrefixedText() );
+               $this->assertEquals( self::$pageRev->getParentId(), self::$lastNotifyArgs[5] );
                $this->assertEquals( $revision->getId(), self::$lastNotifyArgs[6] );
                $this->assertEquals( null, self::$lastNotifyArgs[7] );
                $this->assertEquals( 0, self::$lastNotifyArgs[8] );
index c4829d2..2288507 100644 (file)
@@ -2,12 +2,6 @@
 
 class ConfigFactoryTest extends MediaWikiTestCase {
 
-       public function tearDown() {
-               // Reset this since we mess with it a bit
-               ConfigFactory::destroyDefaultInstance();
-               parent::tearDown();
-       }
-
        /**
         * @covers ConfigFactory::register
         */
@@ -54,17 +48,10 @@ class ConfigFactoryTest extends MediaWikiTestCase {
         * @covers ConfigFactory::getDefaultInstance
         */
        public function testGetDefaultInstance() {
-               // Set $wgConfigRegistry, and check the default
-               // instance read from it
-               $this->setMwGlobals( 'wgConfigRegistry', [
-                       'conf1' => 'GlobalVarConfig::newInstance',
-                       'conf2' => 'GlobalVarConfig::newInstance',
-               ] );
-               ConfigFactory::destroyDefaultInstance();
                $factory = ConfigFactory::getDefaultInstance();
-               $this->assertInstanceOf( 'Config', $factory->makeConfig( 'conf1' ) );
-               $this->assertInstanceOf( 'Config', $factory->makeConfig( 'conf2' ) );
+               $this->assertInstanceOf( 'Config', $factory->makeConfig( 'main' ) );
+
                $this->setExpectedException( 'ConfigException' );
-               $factory->makeConfig( 'conf3' );
+               $factory->makeConfig( 'xyzzy' );
        }
 }
index 9643d13..d92fb8f 100644 (file)
@@ -22,11 +22,20 @@ class CssContentHandlerTest extends MediaWikiLangTestCase {
         */
        public static function provideMakeRedirectContent() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array( 'MediaWiki:MonoBook.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=MediaWiki:MonoBook.css&action=raw&ctype=text/css);" ),
-                       array( 'User:FooBar/common.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=User:FooBar/common.css&action=raw&ctype=text/css);" ),
-                       array( 'Gadget:FooBaz.css', "/* #REDIRECT */@import url(//example.org/w/index.php?title=Gadget:FooBaz.css&action=raw&ctype=text/css);" ),
-               );
+               return [
+                       [
+                               'MediaWiki:MonoBook.css',
+                               "/* #REDIRECT */@import url(//example.org/w/index.php?title=MediaWiki:MonoBook.css&action=raw&ctype=text/css);"
+                       ],
+                       [
+                               'User:FooBar/common.css',
+                               "/* #REDIRECT */@import url(//example.org/w/index.php?title=User:FooBar/common.css&action=raw&ctype=text/css);"
+                       ],
+                       [
+                               'Gadget:FooBaz.css',
+                               "/* #REDIRECT */@import url(//example.org/w/index.php?title=Gadget:FooBaz.css&action=raw&ctype=text/css);"
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 }
index 17f653c..d229623 100644 (file)
@@ -22,11 +22,20 @@ class JavaScriptContentHandlerTest extends MediaWikiLangTestCase {
         */
        public static function provideMakeRedirectContent() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array( 'MediaWiki:MonoBook.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");' ),
-                       array( 'User:FooBar/common.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:FooBar/common.js\u0026action=raw\u0026ctype=text/javascript");' ),
-                       array( 'Gadget:FooBaz.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=Gadget:FooBaz.js\u0026action=raw\u0026ctype=text/javascript");' ),
-               );
+               return [
+                       [
+                               'MediaWiki:MonoBook.js',
+                               '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
+                       [
+                               'User:FooBar/common.js',
+                               '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:FooBar/common.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
+                       [
+                               'Gadget:FooBaz.js',
+                               '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=Gadget:FooBaz.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 }
index abe352a..1c746bc 100644 (file)
@@ -141,26 +141,6 @@ class JavaScriptContentTest extends TextContentTest {
                ];
        }
 
-       /**
-        * @todo Test needs database!
-        */
-       /*
-       public function getRedirectChain() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectArray( $text );
-       }
-       */
-
-       /**
-        * @todo Test needs database!
-        */
-       /*
-       public function getUltimateRedirectTarget() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectRecurse( $text );
-       }
-       */
-
        public static function dataIsCountable() {
                return [
                        [ '',
@@ -278,10 +258,10 @@ class JavaScriptContentTest extends TextContentTest {
                        ],
 
                        // @codingStandardsIgnoreStart Generic.Files.LineLength
-                       array(
+                       [
                                '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");',
                                '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=TestUpdateRedirect_target\u0026action=raw\u0026ctype=text/javascript");'
-                       )
+                       ]
                        // @codingStandardsIgnoreEnd
                ];
        }
@@ -333,15 +313,30 @@ class JavaScriptContentTest extends TextContentTest {
         */
        public static function provideGetRedirectTarget() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array( 'MediaWiki:MonoBook.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");' ),
-                       array( 'User:FooBar/common.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:FooBar/common.js\u0026action=raw\u0026ctype=text/javascript");' ),
-                       array( 'Gadget:FooBaz.js', '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=Gadget:FooBaz.js\u0026action=raw\u0026ctype=text/javascript");' ),
+               return [
+                       [
+                               'MediaWiki:MonoBook.js',
+                               '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=MediaWiki:MonoBook.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
+                       [
+                               'User:FooBar/common.js',
+                               '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=User:FooBar/common.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
+                       [
+                               'Gadget:FooBaz.js',
+                               '/* #REDIRECT */mw.loader.load("//example.org/w/index.php?title=Gadget:FooBaz.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
                        // No #REDIRECT comment
-                       array( null, 'mw.loader.load("//example.org/w/index.php?title=MediaWiki:NoRedirect.js\u0026action=raw\u0026ctype=text/javascript");' ),
+                       [
+                               null,
+                               'mw.loader.load("//example.org/w/index.php?title=MediaWiki:NoRedirect.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
                        // Different domain
-                       array( null, '/* #REDIRECT */mw.loader.load("//example.com/w/index.php?title=MediaWiki:OtherWiki.js\u0026action=raw\u0026ctype=text/javascript");' ),
-               );
+                       [
+                               null,
+                               '/* #REDIRECT */mw.loader.load("//example.com/w/index.php?title=MediaWiki:OtherWiki.js\u0026action=raw\u0026ctype=text/javascript");'
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 }
index 93bf716..ac83428 100644 (file)
@@ -180,26 +180,6 @@ class TextContentTest extends MediaWikiLangTestCase {
                $this->assertEquals( !is_null( $expected ), $content->isRedirect() );
        }
 
-       /**
-        * @todo Test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getRedirectChain() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectArray( $text );
-       }
-       */
-
-       /**
-        * @todo Test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getUltimateRedirectTarget() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectRecurse( $text );
-       }
-       */
-
        public static function dataIsCountable() {
                return [
                        [ '',
index c7fba50..32e71e0 100644 (file)
@@ -91,7 +91,7 @@ class RequestContextTest extends MediaWikiTestCase {
                        MediaWiki\Session\SessionManager::getGlobalSession()->getId(),
                        "Correct context session ID."
                );
-               if ( \MediaWiki\Session\PhpSessionHandler::isEnabled() ) {
+               if ( \MediaWiki\Session\PHPSessionHandler::isEnabled() ) {
                        $this->assertEquals( $sinfo['sessionId'], session_id(), "Correct context session ID." );
                } else {
                        $this->assertEquals( $oldSessionId, session_id(), "Unchanged PHP session ID." );
index 168b2c6..bb747c7 100644 (file)
@@ -339,7 +339,7 @@ class DatabaseMysqlBaseTest extends MediaWikiTestCase {
 
                $db->expects( $this->any() )
                        ->method( 'getHeartbeatData' )
-                       ->with( 172 )
+                       ->with( [ 'server_id' => 172 ] )
                        ->will( $this->returnValue( [ $ptTimeISO, $now ] ) );
 
                $db->setLBInfo( 'clusterMasterHost', 'db1052' );
index 18de9be..80fb826 100644 (file)
@@ -330,7 +330,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
 
                foreach ( $versions as $version ) {
                        $versions = "upgrading from $version to $wgVersion";
-                       $db = $this->prepareDB( $version );
+                       $db = $this->prepareTestDB( $version );
                        $tables = $this->getTables( $db );
                        $this->assertEquals( $currentTables, $tables, "Different tables $versions" );
                        foreach ( $tables as $table ) {
@@ -389,7 +389,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
                $this->assertTrue( $db->close(), "closing database" );
        }
 
-       private function prepareDB( $version ) {
+       private function prepareTestDB( $version ) {
                static $maint = null;
                if ( $maint === null ) {
                        $maint = new FakeMaintenance();
index a9a1e7a..938397a 100644 (file)
@@ -47,9 +47,9 @@ class AvroFormatterTest extends MediaWikiTestCase {
                // disable conversion of notices
                PHPUnit_Framework_Error_Notice::$enabled = false;
                // have to keep the user notice from being output
-               wfSuppressWarnings();
+               \MediaWiki\suppressWarnings();
                $res = $formatter->format( [ 'channel' => 'marty' ] );
-               wfRestoreWarnings();
+               \MediaWiki\restoreWarnings();
                PHPUnit_Framework_Error_Notice::$enabled = $noticeEnabled;
                $this->assertNull( $res );
        }
index 3029948..e29d207 100644 (file)
@@ -64,6 +64,7 @@ class KafkaHandlerTest extends MediaWikiTestCase {
                        'channel' => 'foo',
                        'level' => Logger::EMERGENCY,
                        'extra' => [],
+                       'context' => [],
                ] );
        }
 
@@ -98,6 +99,7 @@ class KafkaHandlerTest extends MediaWikiTestCase {
                        'channel' => 'foo',
                        'level' => Logger::EMERGENCY,
                        'extra' => [],
+                       'context' => [],
                ] );
 
                if ( !$expectException ) {
@@ -128,6 +130,7 @@ class KafkaHandlerTest extends MediaWikiTestCase {
                        'channel' => 'foo',
                        'level' => Logger::EMERGENCY,
                        'extra' => [],
+                       'context' => [],
                ] );
 
                if ( !$expectException ) {
@@ -163,6 +166,7 @@ class KafkaHandlerTest extends MediaWikiTestCase {
                                'channel' => 'foo',
                                'level' => Logger::EMERGENCY,
                                'extra' => [],
+                               'context' => [],
                        ] );
                }
        }
@@ -190,16 +194,19 @@ class KafkaHandlerTest extends MediaWikiTestCase {
                                'channel' => 'foo',
                                'level' => Logger::EMERGENCY,
                                'extra' => [],
+                               'context' => [],
                        ],
                        [
                                'channel' => 'foo',
                                'level' => Logger::EMERGENCY,
                                'extra' => [],
+                               'context' => [],
                        ],
                        [
                                'channel' => 'foo',
                                'level' => Logger::EMERGENCY,
                                'extra' => [],
+                               'context' => [],
                        ],
                ] );
        }
index 75af87e..ac75e55 100644 (file)
@@ -6,7 +6,7 @@
  * ^--- make sure temporary tables are used.
  */
 class LinksUpdateTest extends MediaWikiLangTestCase {
-       protected $testingPageId;
+       protected static $testingPageId;
 
        function __construct( $name = null, array $data = [], $dataName = '' ) {
                parent::__construct( $name, $data, $dataName );
@@ -45,9 +45,9 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                $this->setMwGlobals( 'wgRCWatchCategoryMembership', true );
        }
 
-       public function addDBData() {
+       public function addDBDataOnce() {
                $res = $this->insertPage( 'Testing' );
-               $this->testingPageId = $res['id'];
+               self::$testingPageId = $res['id'];
                $this->insertPage( 'Some_other_page' );
                $this->insertPage( 'Template:TestingTemplate' );
        }
@@ -68,7 +68,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
        public function testUpdate_pagelinks() {
                /** @var Title $t */
                /** @var ParserOutput $po */
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $po->addLink( Title::newFromText( "Foo" ) );
                $po->addLink( Title::newFromText( "Special:Foo" ) ); // special namespace should be ignored
@@ -81,7 +81,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        'pagelinks',
                        'pl_namespace,
                        pl_title',
-                       'pl_from = ' . $this->testingPageId,
+                       'pl_from = ' . self::$testingPageId,
                        [ [ NS_MAIN, 'Foo' ] ]
                );
                $this->assertArrayEquals( [
@@ -100,7 +100,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        'pagelinks',
                        'pl_namespace,
                        pl_title',
-                       'pl_from = ' . $this->testingPageId,
+                       'pl_from = ' . self::$testingPageId,
                        [
                                [ NS_MAIN, 'Bar' ],
                                [ NS_TALK, 'Bar' ],
@@ -120,7 +120,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
         */
        public function testUpdate_externallinks() {
                /** @var ParserOutput $po */
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $po->addExternalLink( "http://testing.com/wiki/Foo" );
 
@@ -129,7 +129,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        $po,
                        'externallinks',
                        'el_to, el_index',
-                       'el_from = ' . $this->testingPageId,
+                       'el_from = ' . self::$testingPageId,
                        [
                                [ 'http://testing.com/wiki/Foo', 'http://com.testing./wiki/Foo' ],
                        ]
@@ -143,7 +143,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                /** @var ParserOutput $po */
                $this->setMwGlobals( 'wgCategoryCollation', 'uppercase' );
 
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $po->addCategory( "Foo", "FOO" );
 
@@ -152,7 +152,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        $po,
                        'categorylinks',
                        'cl_to, cl_sortkey',
-                       'cl_from = ' . $this->testingPageId,
+                       'cl_from = ' . self::$testingPageId,
                        [ [ 'Foo', "FOO\nTESTING" ] ]
                );
        }
@@ -223,7 +223,11 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        $templateTitle,
                        $templatePage->getParserOutput( new ParserOptions() ),
                        Title::newFromText( 'Baz' ),
-                       [ [ 'Baz', '[[:Template:TestingTemplate]] and 2 pages added to category' ] ]
+                       [ [
+                               'Baz',
+                               '[[:Template:TestingTemplate]] and [[Special:WhatLinksHere/Template:TestingTemplate|2 pages]] '
+                               . 'added to category'
+                       ] ]
                );
        }
 
@@ -232,7 +236,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
         */
        public function testUpdate_iwlinks() {
                /** @var ParserOutput $po */
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $target = Title::makeTitleSafe( NS_MAIN, "Foo", '', 'linksupdatetest' );
                $po->addInterwikiLink( $target );
@@ -242,7 +246,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        $po,
                        'iwlinks',
                        'iwl_prefix, iwl_title',
-                       'iwl_from = ' . $this->testingPageId,
+                       'iwl_from = ' . self::$testingPageId,
                        [ [ 'linksupdatetest', 'Foo' ] ]
                );
        }
@@ -252,7 +256,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
         */
        public function testUpdate_templatelinks() {
                /** @var ParserOutput $po */
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $po->addTemplate( Title::newFromText( "Template:Foo" ), 23, 42 );
 
@@ -262,7 +266,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        'templatelinks',
                        'tl_namespace,
                        tl_title',
-                       'tl_from = ' . $this->testingPageId,
+                       'tl_from = ' . self::$testingPageId,
                        [ [ NS_TEMPLATE, 'Foo' ] ]
                );
        }
@@ -272,7 +276,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
         */
        public function testUpdate_imagelinks() {
                /** @var ParserOutput $po */
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $po->addImage( "Foo.png" );
 
@@ -281,7 +285,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        $po,
                        'imagelinks',
                        'il_to',
-                       'il_from = ' . $this->testingPageId,
+                       'il_from = ' . self::$testingPageId,
                        [ [ 'Foo.png' ] ]
                );
        }
@@ -295,7 +299,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                ] );
 
                /** @var ParserOutput $po */
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $po->addLanguageLink( Title::newFromText( "en:Foo" )->getFullText() );
 
@@ -304,7 +308,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        $po,
                        'langlinks',
                        'll_lang, ll_title',
-                       'll_from = ' . $this->testingPageId,
+                       'll_from = ' . self::$testingPageId,
                        [ [ 'En', 'Foo' ] ]
                );
        }
@@ -316,7 +320,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                global $wgPagePropsHaveSortkey;
 
                /** @var ParserOutput $po */
-               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", $this->testingPageId );
+               list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId );
 
                $fields = [ 'pp_propname', 'pp_value' ];
                $expected = [];
@@ -349,7 +353,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                }
 
                $this->assertLinksUpdate(
-                       $t, $po, 'page_props', $fields, 'pp_page = ' . $this->testingPageId, $expected );
+                       $t, $po, 'page_props', $fields, 'pp_page = ' . self::$testingPageId, $expected );
        }
 
        public function testUpdate_page_props_without_sortkey() {
index e7f3a21..90ccd1e 100644 (file)
@@ -22,7 +22,7 @@ class HttpErrorTest extends MediaWikiTestCase {
         */
        public function testGetHtml( array $expected, $content, $header ) {
                $httpError = new HttpError( 500, $content, $header );
-               $errorHtml = $httpError->getHtml();
+               $errorHtml = $httpError->getHTML();
 
                foreach ( $expected as $key => $html ) {
                        $this->assertContains( $html, $errorHtml, $key );
index bf59ab5..4aeddc6 100644 (file)
@@ -57,7 +57,7 @@ class FileBackendTest extends MediaWikiTestCase {
                        'name' => 'localtesting',
                        'lockManager' => LockManagerGroup::singleton()->get( 'fsLockManager' ),
                        'parallelize' => 'implicit',
-                       'wikiId' => wfWikiId() . wfRandomString(),
+                       'wikiId' => wfWikiID() . wfRandomString(),
                        'backends' => [
                                [
                                        'name' => 'localmultitesting1',
@@ -2431,7 +2431,7 @@ class FileBackendTest extends MediaWikiTestCase {
                $be = TestingAccessWrapper::newFromObject(
                        new FileBackendMultiWrite( [
                                'name' => 'localtesting',
-                               'wikiId' => wfWikiId() . mt_rand(),
+                               'wikiId' => wfWikiID() . mt_rand(),
                                'backends' => [
                                        [ // backend 0
                                                'name' => 'multitesting0',
@@ -2481,7 +2481,7 @@ class FileBackendTest extends MediaWikiTestCase {
                $be = TestingAccessWrapper::newFromObject(
                        new FileBackendMultiWrite( [
                                'name' => 'localtesting',
-                               'wikiId' => wfWikiId() . mt_rand(),
+                               'wikiId' => wfWikiID() . mt_rand(),
                                'backends' => [
                                        [ // backend 0
                                                'name' => 'multitesting0',
index 77a7320..8366541 100644 (file)
@@ -120,7 +120,7 @@ class FileBackendDBRepoWrapperTest extends MediaWikiTestCase {
                        [],
                        [ [
                                'name' => $this->backendName,
-                               'wikiId' => wfWikiId()
+                               'wikiId' => wfWikiID()
                        ] ] );
 
                $wrapperMock = $this->getMock( 'FileBackendDBRepoWrapper',
index a7408f2..c5fd369 100644 (file)
@@ -137,7 +137,7 @@ class FileTest extends MediaWikiMediaTestCase {
         */
        public function testGetThumbnailSource( $data ) {
                $backendMock = $this->getMockBuilder( 'FSFileBackend' )
-                       ->setConstructorArgs( [ [ 'name' => 'backendMock', 'wikiId' => wfWikiId() ] ] )
+                       ->setConstructorArgs( [ [ 'name' => 'backendMock', 'wikiId' => wfWikiID() ] ] )
                        ->getMock();
 
                $repoMock = $this->getMockBuilder( 'FileRepo' )
@@ -247,7 +247,7 @@ class FileTest extends MediaWikiMediaTestCase {
                $this->setMwGlobals( 'wgThumbnailBuckets', $data['buckets'] );
 
                $backendMock = $this->getMockBuilder( 'FSFileBackend' )
-                       ->setConstructorArgs( [ [ 'name' => 'backendMock', 'wikiId' => wfWikiId() ] ] )
+                       ->setConstructorArgs( [ [ 'name' => 'backendMock', 'wikiId' => wfWikiID() ] ] )
                        ->getMock();
 
                $repoMock = $this->getMockBuilder( 'FileRepo' )
index 9c7040a..ffaa2c3 100644 (file)
@@ -20,7 +20,7 @@ class LocalFileTest extends MediaWikiTestCase {
                        'transformVia404' => false,
                        'backend' => new FSFileBackend( [
                                'name' => 'local-backend',
-                               'wikiId' => wfWikiId(),
+                               'wikiId' => wfWikiID(),
                                'containerPaths' => [
                                        'cont1' => "/testdir/local-backend/tempimages/cont1",
                                        'cont2' => "/testdir/local-backend/tempimages/cont2"
index f4aac23..9d05d15 100644 (file)
@@ -37,8 +37,8 @@ class ImportTest extends MediaWikiLangTestCase {
 
        public function getUnknownTagsXML() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array(
+               return [
+                       [
                                <<< EOF
 <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
   <page unknown="123" dontknow="533">
@@ -68,8 +68,8 @@ EOF
                                ,
                                'noitazinagro tseb eht si ikiWaideM',
                                'TestImportPage'
-                       )
-               );
+                       ]
+               ];
                // @codingStandardsIgnoreEnd
        }
 
@@ -102,8 +102,8 @@ EOF
 
        public function getRedirectXML() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array(
+               return [
+                       [
                                <<< EOF
 <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
        <page>
@@ -129,8 +129,8 @@ EOF
 EOF
                        ,
                                'Test22'
-                       ),
-                       array(
+                       ],
+                       [
                                <<< EOF
 <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.9/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.9/ http://www.mediawiki.org/xml/export-0.9.xsd" version="0.9" xml:lang="en">
        <page>
@@ -154,8 +154,8 @@ EOF
 EOF
                        ,
                                null
-                       ),
-               );
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
@@ -185,8 +185,8 @@ EOF
 
        public function getSiteInfoXML() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array(
+               return [
+                       [
                                <<< EOF
 <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
   <siteinfo>
@@ -204,7 +204,7 @@ EOF
 </mediawiki>
 EOF
                        ,
-                               array(
+                               [
                                        '-2' => 'Media',
                                        '-1' => 'Special',
                                        '0' => '',
@@ -213,9 +213,9 @@ EOF
                                        '3' => 'User talk',
                                        '100' => 'Portal',
                                        '101' => 'Portal talk',
-                               )
-                       ),
-               );
+                               ]
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index 65ffa49..3c648f9 100644 (file)
@@ -52,6 +52,29 @@ class JobTest extends MediaWikiTestCase {
                                $this->getMockJob( [ $mockToStringObj ] ),
                                'someCommand  0={STRING_OBJ_VAL}'
                        ],
+                       [
+                               $this->getMockJob( [
+                                       "pages" => [
+                                               "932737" => [
+                                                       0,
+                                                       "Robert_James_Waller"
+                                               ]
+                                       ],
+                                       "rootJobSignature" => "45868e99bba89064e4483743ebb9b682ef95c1a7",
+                                       "rootJobTimestamp" => "20160309110158",
+                                       "masterPos" => [
+                                               "file" => "db1023-bin.001288",
+                                               "pos" => "308257743",
+                                               "asOfTime" => 1457521464.3814
+                                       ],
+                                       "triggeredRecursive" => true
+                               ] ),
+                               'someCommand  pages={"932737":[0,"Robert_James_Waller"]} ' .
+                               'rootJobSignature=45868e99bba89064e4483743ebb9b682ef95c1a7 ' .
+                               'rootJobTimestamp=20160309110158 masterPos=' .
+                               '{"file":"db1023-bin.001288","pos":"308257743","asOfTime":1457521464.3814} ' .
+                               'triggeredRecursive=1'
+                       ],
                ];
        }
 
index 50a24ad..54178fe 100644 (file)
@@ -21,10 +21,11 @@ class CategoryMembershipChangeJobTest extends MediaWikiTestCase {
        public function setUp() {
                parent::setUp();
                $this->setMwGlobals( 'wgRCWatchCategoryMembership', true );
+               $this->setContentLang( 'qqx' );
        }
 
-       public function addDBData() {
-               parent::addDBData();
+       public function addDBDataOnce() {
+               parent::addDBDataOnce();
                $insertResult = $this->insertPage( self::TITLE_STRING, 'UT Content' );
                $this->title = $insertResult['title'];
        }
@@ -74,11 +75,11 @@ class CategoryMembershipChangeJobTest extends MediaWikiTestCase {
                $removedRevId = $this->editPageText( 'Blank' );
 
                $this->assertEquals(
-                       '[[:' . self::TITLE_STRING . ']] added to category',
+                       '(recentchanges-page-added-to-category: ' . self::TITLE_STRING . ', 0)',
                        $this->getCategorizeRecentChangeForRevId( $addedRevId )->getAttribute( 'rc_comment' )
                );
                $this->assertEquals(
-                       '[[:' . self::TITLE_STRING . ']] removed from category',
+                       '(recentchanges-page-removed-from-category: ' . self::TITLE_STRING . ', 0)',
                        $this->getCategorizeRecentChangeForRevId( $removedRevId )->getAttribute( 'rc_comment' )
                );
        }
index 8902ecd..5f5a1e8 100644 (file)
@@ -189,192 +189,192 @@ class CSSMinTest extends MediaWikiTestCase {
                        . '%228%22%3E%0A%3Ccircle%20cx%3D%224%22%20cy%3D%224%22%20r%3D%222%22%2F%3E%0A%3C%2Fsvg%3E%0A';
 
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
-                       array(
+               return [
+                       [
                                'Regular file',
                                'foo { background: url(red.gif); }',
                                'foo { background: url(http://localhost/w/red.gif?34ac6); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Regular file (missing)',
                                'foo { background: url(theColorOfHerHair.gif); }',
                                'foo { background: url(http://localhost/w/theColorOfHerHair.gif); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Remote URL',
                                'foo { background: url(http://example.org/w/foo.png); }',
                                'foo { background: url(http://example.org/w/foo.png); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Protocol-relative remote URL',
                                'foo { background: url(//example.org/w/foo.png); }',
                                'foo { background: url(//example.org/w/foo.png); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Remote URL with query',
                                'foo { background: url(http://example.org/w/foo.png?query=yes); }',
                                'foo { background: url(http://example.org/w/foo.png?query=yes); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Protocol-relative remote URL with query',
                                'foo { background: url(//example.org/w/foo.png?query=yes); }',
                                'foo { background: url(//example.org/w/foo.png?query=yes); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Domain-relative URL',
                                'foo { background: url(/static/foo.png); }',
                                'foo { background: url(http://doc.example.org/static/foo.png); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Domain-relative URL with query',
                                'foo { background: url(/static/foo.png?query=yes); }',
                                'foo { background: url(http://doc.example.org/static/foo.png?query=yes); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Remote URL (unnecessary quotes not preserved)',
                                'foo { background: url("http://example.org/w/foo.png"); }',
                                'foo { background: url(http://example.org/w/foo.png); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Embedded file',
                                'foo { /* @embed */ background: url(red.gif); }',
                                "foo { background: url($red); background: url(http://localhost/w/red.gif?34ac6)!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Embedded file, other comments before the rule',
                                "foo { /* Bar. */ /* @embed */ background: url(red.gif); }",
                                "foo { /* Bar. */ background: url($red); /* Bar. */ background: url(http://localhost/w/red.gif?34ac6)!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Can not re-embed data: URIs',
                                "foo { /* @embed */ background: url($red); }",
                                "foo { background: url($red); }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Can not remap data: URIs',
                                "foo { background: url($red); }",
                                "foo { background: url($red); }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Can not embed remote URLs',
                                'foo { /* @embed */ background: url(http://example.org/w/foo.png); }',
                                'foo { background: url(http://example.org/w/foo.png); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Embedded file (inline @embed)',
                                'foo { background: /* @embed */ url(red.gif); }',
                                "foo { background: url($red); "
                                        . "background: url(http://localhost/w/red.gif?34ac6)!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Can not embed large files',
                                'foo { /* @embed */ background: url(large.png); }',
                                "foo { background: url(http://localhost/w/large.png?e3d1f); }",
-                       ),
-                       array(
+                       ],
+                       [
                                'SVG files are embedded without base64 encoding and unnecessary IE 6 and 7 fallback',
                                'foo { /* @embed */ background: url(circle.svg); }',
                                "foo { background: url($svg); }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Two regular files in one rule',
                                'foo { background: url(red.gif), url(green.gif); }',
                                'foo { background: url(http://localhost/w/red.gif?34ac6), '
                                        . 'url(http://localhost/w/green.gif?13651); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Two embedded files in one rule',
                                'foo { /* @embed */ background: url(red.gif), url(green.gif); }',
                                "foo { background: url($red), url($green); "
                                        . "background: url(http://localhost/w/red.gif?34ac6), "
                                        . "url(http://localhost/w/green.gif?13651)!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Two embedded files in one rule (inline @embed)',
                                'foo { background: /* @embed */ url(red.gif), /* @embed */ url(green.gif); }',
                                "foo { background: url($red), url($green); "
                                        . "background: url(http://localhost/w/red.gif?34ac6), "
                                        . "url(http://localhost/w/green.gif?13651)!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Two embedded files in one rule (inline @embed), one too large',
                                'foo { background: /* @embed */ url(red.gif), /* @embed */ url(large.png); }',
                                "foo { background: url($red), url(http://localhost/w/large.png?e3d1f); "
                                        . "background: url(http://localhost/w/red.gif?34ac6), "
                                        . "url(http://localhost/w/large.png?e3d1f)!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Practical example with some noise',
                                'foo { /* @embed */ background: #f9f9f9 url(red.gif) 0 0 no-repeat; }',
                                "foo { background: #f9f9f9 url($red) 0 0 no-repeat; "
                                        . "background: #f9f9f9 url(http://localhost/w/red.gif?34ac6) 0 0 no-repeat!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Does not mess with other properties',
                                'foo { color: red; background: url(red.gif); font-size: small; }',
                                'foo { color: red; background: url(http://localhost/w/red.gif?34ac6); font-size: small; }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Spacing and miscellanea not changed (1)',
                                'foo {   background:    url(red.gif);  }',
                                'foo {   background:    url(http://localhost/w/red.gif?34ac6);  }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Spacing and miscellanea not changed (2)',
                                'foo {background:url(red.gif)}',
                                'foo {background:url(http://localhost/w/red.gif?34ac6)}',
-                       ),
-                       array(
+                       ],
+                       [
                                'Spaces within url() parentheses are ignored',
                                'foo { background: url( red.gif ); }',
                                'foo { background: url(http://localhost/w/red.gif?34ac6); }',
-                       ),
-                       array(
+                       ],
+                       [
                                '@import rule to local file (should we remap this?)',
                                '@import url(/styles.css)',
                                '@import url(http://doc.example.org/styles.css)',
-                       ),
-                       array(
+                       ],
+                       [
                                '@import rule to URL (should we remap this?)',
                                '@import url(//localhost/styles.css?query=yes)',
                                '@import url(//localhost/styles.css?query=yes)',
-                       ),
-                       array(
+                       ],
+                       [
                                'Simple case with comments before url',
                                'foo { prop: /* some {funny;} comment */ url(bar.png); }',
                                'foo { prop: /* some {funny;} comment */ url(http://localhost/w/bar.png); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Simple case with comments after url',
                                'foo { prop: url(red.gif)/* some {funny;} comment */ ; }',
                                'foo { prop: url(http://localhost/w/red.gif?34ac6)/* some {funny;} comment */ ; }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Embedded file with comment before url',
                                'foo { /* @embed */ background: /* some {funny;} comment */ url(red.gif); }',
                                "foo { background: /* some {funny;} comment */ url($red); background: /* some {funny;} comment */ url(http://localhost/w/red.gif?34ac6)!ie; }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Embedded file with comments inside and outside the rule',
                                'foo { /* @embed */ background: url(red.gif) /* some {foo;} comment */; /* some {bar;} comment */ }',
                                "foo { background: url($red) /* some {foo;} comment */; background: url(http://localhost/w/red.gif?34ac6) /* some {foo;} comment */!ie; /* some {bar;} comment */ }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Embedded file with comment outside the rule',
                                'foo { /* @embed */ background: url(red.gif); /* some {funny;} comment */ }',
                                "foo { background: url($red); background: url(http://localhost/w/red.gif?34ac6)!ie; /* some {funny;} comment */ }",
-                       ),
-                       array(
+                       ],
+                       [
                                'Rule with two urls, each with comments',
                                '{ background: /*asd*/ url(something.png); background: /*jkl*/ url(something.png); }',
                                '{ background: /*asd*/ url(http://localhost/w/something.png); background: /*jkl*/ url(http://localhost/w/something.png); }',
-                       ),
-                       array(
+                       ],
+                       [
                                'Sanity check for offending line from jquery.ui.theme.css (bug 60077)',
                                '.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
                                '.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(http://localhost/w/images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
-                       ),
-               );
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index b57c0da..8075944 100644 (file)
@@ -3,35 +3,12 @@
 class StringUtilsTest extends PHPUnit_Framework_TestCase {
 
        /**
-        * 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'
-               );
+       public function testIsUtf8( $expected, $string ) {
+               $this->assertEquals( $expected, StringUtils::isUtf8( $string ),
+                       'Testing string "' . $this->escaped( $string ) . '"' );
        }
 
        /**
index 6090803..a70c005 100644 (file)
@@ -131,7 +131,7 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
                        $this->markTestSkipped( "This test needs the xml extension." );
                }
                $handler = new BitmapMetadataHandler();
-               $result = $handler->png( $this->filePath . 'xmp.png' );
+               $result = $handler->PNG( $this->filePath . 'xmp.png' );
                $expected = [
                        'frameCount' => 0,
                        'loopCount' => 1,
@@ -151,7 +151,7 @@ class BitmapMetadataHandlerTest extends MediaWikiTestCase {
         */
        public function testPNGNative() {
                $handler = new BitmapMetadataHandler();
-               $result = $handler->png( $this->filePath . 'Png-native-test.png' );
+               $result = $handler->PNG( $this->filePath . 'Png-native-test.png' );
                $expected = 'http://example.com/url';
                $this->assertEquals( $expected, $result['metadata']['Identifier']['x-default'] );
        }
index bf23890..f24b68b 100644 (file)
@@ -78,7 +78,10 @@ class GIFHandlerTest extends MediaWikiMediaTestCase {
                        [ null, GIFHandler::METADATA_BAD ],
                        [ 'Something invalid!', GIFHandler::METADATA_BAD ],
                        // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-                       array( 'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}', GIFHandler::METADATA_GOOD ),
+                       [
+                               'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}',
+                               GIFHandler::METADATA_GOOD
+                       ],
                        // @codingStandardsIgnoreEnd
                ];
        }
@@ -98,8 +101,14 @@ class GIFHandlerTest extends MediaWikiMediaTestCase {
        public static function provideGetMetadata() {
                return [
                        // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-                       array( 'nonanimated.gif', 'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}' ),
-                       array( 'animated-xmp.gif', 'a:4:{s:10:"frameCount";i:4;s:6:"looped";b:1;s:8:"duration";d:2.399999999999999911182158029987476766109466552734375;s:8:"metadata";a:5:{s:6:"Artist";s:7:"Bawolff";s:16:"ImageDescription";a:2:{s:9:"x-default";s:18:"A file to test GIF";s:5:"_type";s:4:"lang";}s:15:"SublocationDest";s:13:"The interwebs";s:14:"GIFFileComment";a:1:{i:0;s:16:"GIƒ·test·file";}s:15:"_MW_GIF_VERSION";i:1;}}' ),
+                       [
+                               'nonanimated.gif',
+                               'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}'
+                       ],
+                       [
+                               'animated-xmp.gif',
+                               'a:4:{s:10:"frameCount";i:4;s:6:"looped";b:1;s:8:"duration";d:2.399999999999999911182158029987476766109466552734375;s:8:"metadata";a:5:{s:6:"Artist";s:7:"Bawolff";s:16:"ImageDescription";a:2:{s:9:"x-default";s:18:"A file to test GIF";s:5:"_type";s:4:"lang";}s:15:"SublocationDest";s:13:"The interwebs";s:14:"GIFFileComment";a:1:{i:0;s:16:"GIƒ·test·file";}s:15:"_MW_GIF_VERSION";i:1;}}'
+                       ],
                        // @codingStandardsIgnoreEnd
                ];
        }
index 5887d38..5042121 100644 (file)
@@ -25,7 +25,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
 
                $this->backend = new FSFileBackend( [
                        'name' => 'localtesting',
-                       'wikiId' => wfWikiId(),
+                       'wikiId' => wfWikiID(),
                        'containerPaths' => $containers
                ] );
                $this->repo = new FSRepo( $this->getRepoOptions() );
index 4417c4f..afc338e 100644 (file)
@@ -79,7 +79,10 @@ class PNGHandlerTest extends MediaWikiMediaTestCase {
                        [ null, PNGHandler::METADATA_BAD ],
                        [ 'Something invalid!', PNGHandler::METADATA_BAD ],
                        // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-                       array( 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}', PNGHandler::METADATA_GOOD ),
+                       [
+                               'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}',
+                               PNGHandler::METADATA_GOOD
+                       ],
                        // @codingStandardsIgnoreEnd
                ];
        }
@@ -100,8 +103,14 @@ class PNGHandlerTest extends MediaWikiMediaTestCase {
        public static function provideGetMetadata() {
                return [
                        // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-                       array( 'rgb-na-png.png', 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}' ),
-                       array( 'xmp.png', 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:1;s:9:"colorType";s:14:"index-coloured";s:8:"metadata";a:2:{s:12:"SerialNumber";s:9:"123456789";s:15:"_MW_PNG_VERSION";i:1;}}' ),
+                       [
+                               'rgb-na-png.png',
+                               'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}'
+                       ],
+                       [
+                               'xmp.png',
+                               'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:1;s:9:"colorType";s:14:"index-coloured";s:8:"metadata";a:2:{s:12:"SerialNumber";s:9:"123456789";s:15:"_MW_PNG_VERSION";i:1;}}'
+                       ],
                        // @codingStandardsIgnoreEnd
                ];
        }
index dfa92f1..f51693d 100644 (file)
@@ -20,53 +20,53 @@ class WebPHandlerTest extends MediaWikiTestCase {
        }
        public function provideTestExtractMetaData() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
+               return [
                        // Files from https://developers.google.com/speed/webp/gallery2
-                       array( "\x52\x49\x46\x46\x90\x68\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x83\x68\x01\x00\x2F\x8F\x01\x4B\x10\x8D\x38\x6C\xDB\x46\x92\xE0\xE0\x82\x7B\x6C",
-                               array( 'compression' => 'lossless', 'width' => 400, 'height' => 301 ) ),
-                       array( "\x52\x49\x46\x46\x64\x5B\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x8F\x01\x00\x2C\x01\x00\x41\x4C\x50\x48\xE5\x0E",
-                               array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 400, 'height' => 301 ) ),
-                       array( "\x52\x49\x46\x46\xA8\x72\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x9B\x72\x00\x00\x2F\x81\x81\x62\x10\x8D\x40\x8C\x24\x39\x6E\x73\x73\x38\x01\x96",
-                               array( 'compression' => 'lossless', 'width' => 386, 'height' => 395 ) ),
-                       array( "\x52\x49\x46\x46\xE0\x42\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x81\x01\x00\x8A\x01\x00\x41\x4C\x50\x48\x56\x10",
-                               array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 386, 'height' => 395 ) ),
-                       array( "\x52\x49\x46\x46\x70\x61\x02\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x63\x61\x02\x00\x2F\x1F\xC3\x95\x10\x8D\xC8\x72\xDB\xC8\x92\x24\xD8\x91\xD9\x91",
-                               array( 'compression' => 'lossless', 'width' => 800, 'height' => 600 ) ),
-                       array( "\x52\x49\x46\x46\x1C\x1D\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x1F\x03\x00\x57\x02\x00\x41\x4C\x50\x48\x25\x8B",
-                               array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 800, 'height' => 600 ) ),
-                       array( "\x52\x49\x46\x46\xFA\xC5\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xEE\xC5\x00\x00\x2F\xA4\x81\x28\x10\x8D\x40\x68\x24\xC9\x91\xA4\xAE\xF3\x97\x75",
-                               array( 'compression' => 'lossless', 'width' => 421, 'height' => 163 ) ),
-                       array( "\x52\x49\x46\x46\xF6\x5D\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\xA4\x01\x00\xA2\x00\x00\x41\x4C\x50\x48\x38\x1A",
-                               array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 421, 'height' => 163 ) ),
-                       array( "\x52\x49\x46\x46\xC4\x96\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xB8\x96\x01\x00\x2F\x2B\xC1\x4A\x10\x11\x87\x6D\xDB\x48\x12\xFC\x60\xB0\x83\x24",
-                               array( 'compression' => 'lossless', 'width' => 300, 'height' => 300 ) ),
-                       array( "\x52\x49\x46\x46\x0A\x11\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x2B\x01\x00\x2B\x01\x00\x41\x4C\x50\x48\x67\x6E",
-                               array( 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 300, 'height' => 300 ) ),
+                       [ "\x52\x49\x46\x46\x90\x68\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x83\x68\x01\x00\x2F\x8F\x01\x4B\x10\x8D\x38\x6C\xDB\x46\x92\xE0\xE0\x82\x7B\x6C",
+                               [ 'compression' => 'lossless', 'width' => 400, 'height' => 301 ] ],
+                       [ "\x52\x49\x46\x46\x64\x5B\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x8F\x01\x00\x2C\x01\x00\x41\x4C\x50\x48\xE5\x0E",
+                               [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 400, 'height' => 301 ] ],
+                       [ "\x52\x49\x46\x46\xA8\x72\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x9B\x72\x00\x00\x2F\x81\x81\x62\x10\x8D\x40\x8C\x24\x39\x6E\x73\x73\x38\x01\x96",
+                               [ 'compression' => 'lossless', 'width' => 386, 'height' => 395 ] ],
+                       [ "\x52\x49\x46\x46\xE0\x42\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x81\x01\x00\x8A\x01\x00\x41\x4C\x50\x48\x56\x10",
+                               [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 386, 'height' => 395 ] ],
+                       [ "\x52\x49\x46\x46\x70\x61\x02\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x63\x61\x02\x00\x2F\x1F\xC3\x95\x10\x8D\xC8\x72\xDB\xC8\x92\x24\xD8\x91\xD9\x91",
+                               [ 'compression' => 'lossless', 'width' => 800, 'height' => 600 ] ],
+                       [ "\x52\x49\x46\x46\x1C\x1D\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x1F\x03\x00\x57\x02\x00\x41\x4C\x50\x48\x25\x8B",
+                               [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 800, 'height' => 600 ] ],
+                       [ "\x52\x49\x46\x46\xFA\xC5\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xEE\xC5\x00\x00\x2F\xA4\x81\x28\x10\x8D\x40\x68\x24\xC9\x91\xA4\xAE\xF3\x97\x75",
+                               [ 'compression' => 'lossless', 'width' => 421, 'height' => 163 ] ],
+                       [ "\x52\x49\x46\x46\xF6\x5D\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\xA4\x01\x00\xA2\x00\x00\x41\x4C\x50\x48\x38\x1A",
+                               [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 421, 'height' => 163 ] ],
+                       [ "\x52\x49\x46\x46\xC4\x96\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xB8\x96\x01\x00\x2F\x2B\xC1\x4A\x10\x11\x87\x6D\xDB\x48\x12\xFC\x60\xB0\x83\x24",
+                               [ 'compression' => 'lossless', 'width' => 300, 'height' => 300 ] ],
+                       [ "\x52\x49\x46\x46\x0A\x11\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x2B\x01\x00\x2B\x01\x00\x41\x4C\x50\x48\x67\x6E",
+                               [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 300, 'height' => 300 ] ],
 
                        // Lossy files from https://developers.google.com/speed/webp/gallery1
-                       array( "\x52\x49\x46\x46\x68\x76\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\x5C\x76\x00\x00\xD2\xBE\x01\x9D\x01\x2A\x26\x02\x70\x01\x3E\xD5\x4E\x97\x43\xA2",
-                               array( 'compression' => 'lossy', 'width' => 550, 'height' => 368 ) ),
-                       array( "\x52\x49\x46\x46\xB0\xEC\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\xA4\xEC\x00\x00\xB2\x4B\x02\x9D\x01\x2A\x26\x02\x94\x01\x3E\xD1\x50\x96\x46\x26",
-                               array( 'compression' => 'lossy', 'width' => 550, 'height' => 404 ) ),
-                       array( "\x52\x49\x46\x46\x7A\x19\x03\x00\x57\x45\x42\x50\x56\x50\x38\x20\x6E\x19\x03\x00\xB2\xF8\x09\x9D\x01\x2A\x00\x05\xD0\x02\x3E\xAD\x46\x99\x4A\xA5",
-                               array( 'compression' => 'lossy', 'width' => 1280, 'height' => 720 ) ),
-                       array( "\x52\x49\x46\x46\x44\xB3\x02\x00\x57\x45\x42\x50\x56\x50\x38\x20\x38\xB3\x02\x00\x52\x57\x06\x9D\x01\x2A\x00\x04\x04\x03\x3E\xA5\x44\x96\x49\x26",
-                               array( 'compression' => 'lossy', 'width' => 1024, 'height' => 772 ) ),
-                       array( "\x52\x49\x46\x46\x02\x43\x01\x00\x57\x45\x42\x50\x56\x50\x38\x20\xF6\x42\x01\x00\x12\xC0\x05\x9D\x01\x2A\x00\x04\xF0\x02\x3E\x79\x34\x93\x47\xA4",
-                               array( 'compression' => 'lossy', 'width' => 1024, 'height' => 752 ) ),
+                       [ "\x52\x49\x46\x46\x68\x76\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\x5C\x76\x00\x00\xD2\xBE\x01\x9D\x01\x2A\x26\x02\x70\x01\x3E\xD5\x4E\x97\x43\xA2",
+                               [ 'compression' => 'lossy', 'width' => 550, 'height' => 368 ] ],
+                       [ "\x52\x49\x46\x46\xB0\xEC\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\xA4\xEC\x00\x00\xB2\x4B\x02\x9D\x01\x2A\x26\x02\x94\x01\x3E\xD1\x50\x96\x46\x26",
+                               [ 'compression' => 'lossy', 'width' => 550, 'height' => 404 ] ],
+                       [ "\x52\x49\x46\x46\x7A\x19\x03\x00\x57\x45\x42\x50\x56\x50\x38\x20\x6E\x19\x03\x00\xB2\xF8\x09\x9D\x01\x2A\x00\x05\xD0\x02\x3E\xAD\x46\x99\x4A\xA5",
+                               [ 'compression' => 'lossy', 'width' => 1280, 'height' => 720 ] ],
+                       [ "\x52\x49\x46\x46\x44\xB3\x02\x00\x57\x45\x42\x50\x56\x50\x38\x20\x38\xB3\x02\x00\x52\x57\x06\x9D\x01\x2A\x00\x04\x04\x03\x3E\xA5\x44\x96\x49\x26",
+                               [ 'compression' => 'lossy', 'width' => 1024, 'height' => 772 ] ],
+                       [ "\x52\x49\x46\x46\x02\x43\x01\x00\x57\x45\x42\x50\x56\x50\x38\x20\xF6\x42\x01\x00\x12\xC0\x05\x9D\x01\x2A\x00\x04\xF0\x02\x3E\x79\x34\x93\x47\xA4",
+                               [ 'compression' => 'lossy', 'width' => 1024, 'height' => 752 ] ],
 
                        // Animated file from https://groups.google.com/a/chromium.org/d/topic/blink-dev/Y8tRC4mdQz8/discussion
-                       array( "\x52\x49\x46\x46\xD0\x0B\x02\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x12\x00\x00\x00\x3F\x01\x00\x3F\x01\x00\x41\x4E",
-                               array( 'compression' => 'unknown', 'animated' => true, 'transparency' => true, 'width' => 320, 'height' => 320 ) ),
+                       [ "\x52\x49\x46\x46\xD0\x0B\x02\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x12\x00\x00\x00\x3F\x01\x00\x3F\x01\x00\x41\x4E",
+                               [ 'compression' => 'unknown', 'animated' => true, 'transparency' => true, 'width' => 320, 'height' => 320 ] ],
 
                        // Error cases
-                       array( '', false ),
-                       array( '                                    ', false ),
-                       array( 'RIFF                                ', false ),
-                       array( 'RIFF1234WEBP                        ', false ),
-                       array( 'RIFF1234WEBPVP8                     ', false ),
-                       array( 'RIFF1234WEBPVP8L                    ', false ),
-               );
+                       [ '', false ],
+                       [ '                                    ', false ],
+                       [ 'RIFF                                ', false ],
+                       [ 'RIFF1234WEBP                        ', false ],
+                       [ 'RIFF1234WEBPVP8                     ', false ],
+                       [ 'RIFF1234WEBPVP8L                    ', false ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index d488eee..10e0f59 100644 (file)
@@ -767,22 +767,6 @@ more stuff
                ];
        }
 
-       /**
-        * @dataProvider dataReplaceSection
-        * @covers WikiPage::replaceSection
-        */
-       public function testReplaceSection( $title, $model, $text, $section, $with,
-               $sectionTitle, $expected
-       ) {
-               $this->hideDeprecated( "WikiPage::replaceSection" );
-
-               $page = $this->createPage( $title, $text, $model );
-               $text = $page->replaceSection( $section, $with, $sectionTitle );
-               $text = trim( $text );
-
-               $this->assertEquals( $expected, $text );
-       }
-
        /**
         * @dataProvider dataReplaceSection
         * @covers WikiPage::replaceSectionContent
index 04d6067..b1119a1 100644 (file)
@@ -102,7 +102,6 @@ class NewParserTest extends MediaWikiTestCase {
                $tmpGlobals['wgAllowExternalImages'] = true;
                $tmpGlobals['wgRawHtml'] = false;
                $tmpGlobals['wgWellFormedXml'] = true;
-               $tmpGlobals['wgAllowMicrodataAttributes'] = true;
                $tmpGlobals['wgExperimentalHtmlIds'] = false;
                $tmpGlobals['wgAdaptiveMessageCache'] = true;
                $tmpGlobals['wgUseDatabaseMessages'] = true;
@@ -211,15 +210,15 @@ class NewParserTest extends MediaWikiTestCase {
                parent::tearDownAfterClass();
        }
 
-       function addDBData() {
-               $this->tablesUsed[] = 'site_stats';
+       function addDBDataOnce() {
                # disabled for performance
                # $this->tablesUsed[] = 'image';
 
                # Update certain things in site_stats
                $this->db->insert( 'site_stats',
                        [ 'ss_row_id' => 1, 'ss_images' => 2, 'ss_good_articles' => 1 ],
-                       __METHOD__
+                       __METHOD__,
+                       [ 'IGNORE' ]
                );
 
                $user = User::newFromId( 0 );
@@ -412,7 +411,7 @@ class NewParserTest extends MediaWikiTestCase {
                        # informations.
                        $backend = new MockFileBackend( [
                                'name' => 'local-backend',
-                               'wikiId' => wfWikiId()
+                               'wikiId' => wfWikiID()
                        ] );
                }
 
@@ -434,6 +433,7 @@ class NewParserTest extends MediaWikiTestCase {
                        'wgThumbLimits' => [ self::getOptionValue( 'thumbsize', $opts, 180 ) ],
                        'wgMaxTocLevel' => $maxtoclevel,
                        'wgUseTeX' => isset( $opts['math'] ) || isset( $opts['texvc'] ),
+                       'wgWellFormedXml' => true,
                        'wgMathDirectory' => $uploadDir . '/math',
                        'wgDefaultLanguageVariant' => $variant,
                        'wgLinkHolderBatchSize' => $linkHolderBatchSize,
index e55b9e5..a62503a 100644 (file)
@@ -29,93 +29,93 @@ class PreprocessorTest extends MediaWikiTestCase {
 
        public static function provideCases() {
                // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-               return array(
-                       array( "Foo", "<root>Foo</root>" ),
-                       array( "<!-- Foo -->", "<root><comment>&lt;!-- Foo --&gt;</comment></root>" ),
-                       array( "<!-- Foo --><!-- Bar -->", "<root><comment>&lt;!-- Foo --&gt;</comment><comment>&lt;!-- Bar --&gt;</comment></root>" ),
-                       array( "<!-- Foo -->  <!-- Bar -->", "<root><comment>&lt;!-- Foo --&gt;</comment>  <comment>&lt;!-- Bar --&gt;</comment></root>" ),
-                       array( "<!-- Foo --> \n <!-- Bar -->", "<root><comment>&lt;!-- Foo --&gt;</comment> \n <comment>&lt;!-- Bar --&gt;</comment></root>" ),
-                       array( "<!-- Foo --> \n <!-- Bar -->\n", "<root><comment>&lt;!-- Foo --&gt;</comment> \n<comment> &lt;!-- Bar --&gt;\n</comment></root>" ),
-                       array( "<!-- Foo -->  <!-- Bar -->\n", "<root><comment>&lt;!-- Foo --&gt;</comment>  <comment>&lt;!-- Bar --&gt;</comment>\n</root>" ),
-                       array( "<!-->Bar", "<root><comment>&lt;!--&gt;Bar</comment></root>" ),
-                       array( "<!-- Comment -- comment", "<root><comment>&lt;!-- Comment -- comment</comment></root>" ),
-                       array( "== Foo ==\n  <!-- Bar -->\n== Baz ==\n", "<root><h level=\"2\" i=\"1\">== Foo ==</h>\n<comment>  &lt;!-- Bar --&gt;\n</comment><h level=\"2\" i=\"2\">== Baz ==</h>\n</root>" ),
-                       array( "<gallery/>", "<root><ext><name>gallery</name><attr></attr></ext></root>" ),
-                       array( "Foo <gallery/> Bar", "<root>Foo <ext><name>gallery</name><attr></attr></ext> Bar</root>" ),
-                       array( "<gallery></gallery>", "<root><ext><name>gallery</name><attr></attr><inner></inner><close>&lt;/gallery&gt;</close></ext></root>" ),
-                       array( "<foo> <gallery></gallery>", "<root>&lt;foo&gt; <ext><name>gallery</name><attr></attr><inner></inner><close>&lt;/gallery&gt;</close></ext></root>" ),
-                       array( "<foo> <gallery><gallery></gallery>", "<root>&lt;foo&gt; <ext><name>gallery</name><attr></attr><inner>&lt;gallery&gt;</inner><close>&lt;/gallery&gt;</close></ext></root>" ),
-                       array( "<noinclude> Foo bar </noinclude>", "<root><ignore>&lt;noinclude&gt;</ignore> Foo bar <ignore>&lt;/noinclude&gt;</ignore></root>" ),
-                       array( "<noinclude>\n{{Foo}}\n</noinclude>", "<root><ignore>&lt;noinclude&gt;</ignore>\n<template lineStart=\"1\"><title>Foo</title></template>\n<ignore>&lt;/noinclude&gt;</ignore></root>" ),
-                       array( "<noinclude>\n{{Foo}}\n</noinclude>\n", "<root><ignore>&lt;noinclude&gt;</ignore>\n<template lineStart=\"1\"><title>Foo</title></template>\n<ignore>&lt;/noinclude&gt;</ignore>\n</root>" ),
-                       array( "<gallery>foo bar", "<root><ext><name>gallery</name><attr></attr><inner>foo bar</inner></ext></root>" ),
-                       array( "<{{foo}}>", "<root>&lt;<template><title>foo</title></template>&gt;</root>" ),
-                       array( "<{{{foo}}}>", "<root>&lt;<tplarg><title>foo</title></tplarg>&gt;</root>" ),
-                       array( "<gallery></gallery</gallery>", "<root><ext><name>gallery</name><attr></attr><inner>&lt;/gallery</inner><close>&lt;/gallery&gt;</close></ext></root>" ),
-                       array( "=== Foo === ", "<root><h level=\"3\" i=\"1\">=== Foo === </h></root>" ),
-                       array( "==<!-- -->= Foo === ", "<root><h level=\"2\" i=\"1\">==<comment>&lt;!-- --&gt;</comment>= Foo === </h></root>" ),
-                       array( "=== Foo ==<!-- -->= ", "<root><h level=\"1\" i=\"1\">=== Foo ==<comment>&lt;!-- --&gt;</comment>= </h></root>" ),
-                       array( "=== Foo ===<!-- -->\n", "<root><h level=\"3\" i=\"1\">=== Foo ===<comment>&lt;!-- --&gt;</comment></h>\n</root>" ),
-                       array( "=== Foo ===<!-- --> <!-- -->\n", "<root><h level=\"3\" i=\"1\">=== Foo ===<comment>&lt;!-- --&gt;</comment> <comment>&lt;!-- --&gt;</comment></h>\n</root>" ),
-                       array( "== Foo ==\n== Bar == \n", "<root><h level=\"2\" i=\"1\">== Foo ==</h>\n<h level=\"2\" i=\"2\">== Bar == </h>\n</root>" ),
-                       array( "===========", "<root><h level=\"5\" i=\"1\">===========</h></root>" ),
-                       array( "Foo\n=\n==\n=\n", "<root>Foo\n=\n==\n=\n</root>" ),
-                       array( "{{Foo}}", "<root><template><title>Foo</title></template></root>" ),
-                       array( "\n{{Foo}}", "<root>\n<template lineStart=\"1\"><title>Foo</title></template></root>" ),
-                       array( "{{Foo|bar}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template></root>" ),
-                       array( "{{Foo|bar}}a", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template>a</root>" ),
-                       array( "{{Foo|bar|baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name index=\"2\" /><value>baz</value></part></template></root>" ),
-                       array( "{{Foo|1=bar}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part></template></root>" ),
-                       array( "{{Foo|=bar}}", "<root><template><title>Foo</title><part><name></name>=<value>bar</value></part></template></root>" ),
-                       array( "{{Foo|bar=baz}}", "<root><template><title>Foo</title><part><name>bar</name>=<value>baz</value></part></template></root>" ),
-                       array( "{{Foo|{{bar}}=baz}}", "<root><template><title>Foo</title><part><name><template><title>bar</title></template></name>=<value>baz</value></part></template></root>" ),
-                       array( "{{Foo|1=bar|baz}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name index=\"1\" /><value>baz</value></part></template></root>" ),
-                       array( "{{Foo|1=bar|2=baz}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name>2</name>=<value>baz</value></part></template></root>" ),
-                       array( "{{Foo|bar|foo=baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name>foo</name>=<value>baz</value></part></template></root>" ),
-                       array( "{{{1}}}", "<root><tplarg><title>1</title></tplarg></root>" ),
-                       array( "{{{1|}}}", "<root><tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg></root>" ),
-                       array( "{{{Foo}}}", "<root><tplarg><title>Foo</title></tplarg></root>" ),
-                       array( "{{{Foo|}}}", "<root><tplarg><title>Foo</title><part><name index=\"1\" /><value></value></part></tplarg></root>" ),
-                       array( "{{{Foo|bar|baz}}}", "<root><tplarg><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name index=\"2\" /><value>baz</value></part></tplarg></root>" ),
-                       array( "{<!-- -->{Foo}}", "<root>{<comment>&lt;!-- --&gt;</comment>{Foo}}</root>" ),
-                       array( "{{{{Foobar}}}}", "<root>{<tplarg><title>Foobar</title></tplarg>}</root>" ),
-                       array( "{{{ {{Foo}} }}}", "<root><tplarg><title> <template><title>Foo</title></template> </title></tplarg></root>" ),
-                       array( "{{ {{{Foo}}} }}", "<root><template><title> <tplarg><title>Foo</title></tplarg> </title></template></root>" ),
-                       array( "{{{{{Foo}}}}}", "<root><template><title><tplarg><title>Foo</title></tplarg></title></template></root>" ),
-                       array( "{{{{{Foo}} }}}", "<root><tplarg><title><template><title>Foo</title></template> </title></tplarg></root>" ),
-                       array( "{{{{{{Foo}}}}}}", "<root><tplarg><title><tplarg><title>Foo</title></tplarg></title></tplarg></root>" ),
-                       array( "{{{{{{Foo}}}}}", "<root>{<template><title><tplarg><title>Foo</title></tplarg></title></template></root>" ),
-                       array( "[[[Foo]]", "<root>[[[Foo]]</root>" ),
-                       array( "{{Foo|[[[[bar]]|baz]]}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>[[[[bar]]|baz]]</value></part></template></root>" ), // This test is important, since it means the difference between having the [[ rule stacked or not
-                       array( "{{Foo|[[[[bar]|baz]]}}", "<root>{{Foo|[[[[bar]|baz]]}}</root>" ),
-                       array( "{{Foo|Foo [[[[bar]|baz]]}}", "<root>{{Foo|Foo [[[[bar]|baz]]}}</root>" ),
-                       array( "Foo <display map>Bar</display map             >Baz", "<root>Foo <ext><name>display map</name><attr></attr><inner>Bar</inner><close>&lt;/display map             &gt;</close></ext>Baz</root>" ),
-                       array( "Foo <display map foo>Bar</display map             >Baz", "<root>Foo <ext><name>display map</name><attr> foo</attr><inner>Bar</inner><close>&lt;/display map             &gt;</close></ext>Baz</root>" ),
-                       array( "Foo <gallery bar=\"baz\" />", "<root>Foo <ext><name>gallery</name><attr> bar=&quot;baz&quot; </attr></ext></root>" ),
-                       array( "Foo <gallery bar=\"1\" baz=2 />", "<root>Foo <ext><name>gallery</name><attr> bar=&quot;1&quot; baz=2 </attr></ext></root>" ),
-                       array( "</foo>Foo<//foo>", "<root><ext><name>/foo</name><attr></attr><inner>Foo</inner><close>&lt;//foo&gt;</close></ext></root>" ), # Worth blacklisting IMHO
-                       array( "{{#ifexpr: ({{{1|1}}} = 2) | Foo | Bar }}", "<root><template><title>#ifexpr: (<tplarg><title>1</title><part><name index=\"1\" /><value>1</value></part></tplarg> = 2) </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>" ),
-                       array( "{{#if: {{{1|}}} | Foo | {{Bar}} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> <template><title>Bar</title></template> </value></part></template></root>" ),
-                       array( "{{#if: {{{1|}}} | Foo | [[Bar]] }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> [[Bar]] </value></part></template></root>" ),
-                       array( "{{#if: {{{1|}}} | [[Foo]] | Bar }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> [[Foo]] </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>" ),
-                       array( "{{#if: {{{1|}}} | 1 | {{#if: {{{1|}}} | 2 | 3 }} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 1 </value></part><part><name index=\"2\" /><value> <template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 2 </value></part><part><name index=\"2\" /><value> 3 </value></part></template> </value></part></template></root>" ),
-                       array( "{{ {{Foo}}", "<root>{{ <template><title>Foo</title></template></root>" ),
-                       array( "{{Foobar {{Foo}} {{Bar}} {{Baz}} ", "<root>{{Foobar <template><title>Foo</title></template> <template><title>Bar</title></template> <template><title>Baz</title></template> </root>" ),
-                       array( "[[Foo]] |", "<root>[[Foo]] |</root>" ),
-                       array( "{{Foo|Bar|", "<root>{{Foo|Bar|</root>" ),
-                       array( "[[Foo]", "<root>[[Foo]</root>" ),
-                       array( "[[Foo|Bar]", "<root>[[Foo|Bar]</root>" ),
-                       array( "{{Foo| [[Bar] }}", "<root>{{Foo| [[Bar] }}</root>" ),
-                       array( "{{Foo| [[Bar|Baz] }}", "<root>{{Foo| [[Bar|Baz] }}</root>" ),
-                       array( "{{Foo|bar=[[baz]}}", "<root>{{Foo|bar=[[baz]}}</root>" ),
-                       array( "{{foo|", "<root>{{foo|</root>" ),
-                       array( "{{foo|}", "<root>{{foo|}</root>" ),
-                       array( "{{foo|} }}", "<root><template><title>foo</title><part><name index=\"1\" /><value>} </value></part></template></root>" ),
-                       array( "{{foo|bar=|}", "<root>{{foo|bar=|}</root>" ),
-                       array( "{{Foo|} Bar=", "<root>{{Foo|} Bar=</root>" ),
-                       array( "{{Foo|} Bar=}}", "<root><template><title>Foo</title><part><name>} Bar</name>=<value></value></part></template></root>" ),
-                       /* array( file_get_contents( __DIR__ . '/QuoteQuran.txt' ), file_get_contents( __DIR__ . '/QuoteQuranExpanded.txt' ) ), */
-               );
+               return [
+                       [ "Foo", "<root>Foo</root>" ],
+                       [ "<!-- Foo -->", "<root><comment>&lt;!-- Foo --&gt;</comment></root>" ],
+                       [ "<!-- Foo --><!-- Bar -->", "<root><comment>&lt;!-- Foo --&gt;</comment><comment>&lt;!-- Bar --&gt;</comment></root>" ],
+                       [ "<!-- Foo -->  <!-- Bar -->", "<root><comment>&lt;!-- Foo --&gt;</comment>  <comment>&lt;!-- Bar --&gt;</comment></root>" ],
+                       [ "<!-- Foo --> \n <!-- Bar -->", "<root><comment>&lt;!-- Foo --&gt;</comment> \n <comment>&lt;!-- Bar --&gt;</comment></root>" ],
+                       [ "<!-- Foo --> \n <!-- Bar -->\n", "<root><comment>&lt;!-- Foo --&gt;</comment> \n<comment> &lt;!-- Bar --&gt;\n</comment></root>" ],
+                       [ "<!-- Foo -->  <!-- Bar -->\n", "<root><comment>&lt;!-- Foo --&gt;</comment>  <comment>&lt;!-- Bar --&gt;</comment>\n</root>" ],
+                       [ "<!-->Bar", "<root><comment>&lt;!--&gt;Bar</comment></root>" ],
+                       [ "<!-- Comment -- comment", "<root><comment>&lt;!-- Comment -- comment</comment></root>" ],
+                       [ "== Foo ==\n  <!-- Bar -->\n== Baz ==\n", "<root><h level=\"2\" i=\"1\">== Foo ==</h>\n<comment>  &lt;!-- Bar --&gt;\n</comment><h level=\"2\" i=\"2\">== Baz ==</h>\n</root>" ],
+                       [ "<gallery/>", "<root><ext><name>gallery</name><attr></attr></ext></root>" ],
+                       [ "Foo <gallery/> Bar", "<root>Foo <ext><name>gallery</name><attr></attr></ext> Bar</root>" ],
+                       [ "<gallery></gallery>", "<root><ext><name>gallery</name><attr></attr><inner></inner><close>&lt;/gallery&gt;</close></ext></root>" ],
+                       [ "<foo> <gallery></gallery>", "<root>&lt;foo&gt; <ext><name>gallery</name><attr></attr><inner></inner><close>&lt;/gallery&gt;</close></ext></root>" ],
+                       [ "<foo> <gallery><gallery></gallery>", "<root>&lt;foo&gt; <ext><name>gallery</name><attr></attr><inner>&lt;gallery&gt;</inner><close>&lt;/gallery&gt;</close></ext></root>" ],
+                       [ "<noinclude> Foo bar </noinclude>", "<root><ignore>&lt;noinclude&gt;</ignore> Foo bar <ignore>&lt;/noinclude&gt;</ignore></root>" ],
+                       [ "<noinclude>\n{{Foo}}\n</noinclude>", "<root><ignore>&lt;noinclude&gt;</ignore>\n<template lineStart=\"1\"><title>Foo</title></template>\n<ignore>&lt;/noinclude&gt;</ignore></root>" ],
+                       [ "<noinclude>\n{{Foo}}\n</noinclude>\n", "<root><ignore>&lt;noinclude&gt;</ignore>\n<template lineStart=\"1\"><title>Foo</title></template>\n<ignore>&lt;/noinclude&gt;</ignore>\n</root>" ],
+                       [ "<gallery>foo bar", "<root>&lt;gallery&gt;foo bar</root>" ],
+                       [ "<{{foo}}>", "<root>&lt;<template><title>foo</title></template>&gt;</root>" ],
+                       [ "<{{{foo}}}>", "<root>&lt;<tplarg><title>foo</title></tplarg>&gt;</root>" ],
+                       [ "<gallery></gallery</gallery>", "<root><ext><name>gallery</name><attr></attr><inner>&lt;/gallery</inner><close>&lt;/gallery&gt;</close></ext></root>" ],
+                       [ "=== Foo === ", "<root><h level=\"3\" i=\"1\">=== Foo === </h></root>" ],
+                       [ "==<!-- -->= Foo === ", "<root><h level=\"2\" i=\"1\">==<comment>&lt;!-- --&gt;</comment>= Foo === </h></root>" ],
+                       [ "=== Foo ==<!-- -->= ", "<root><h level=\"1\" i=\"1\">=== Foo ==<comment>&lt;!-- --&gt;</comment>= </h></root>" ],
+                       [ "=== Foo ===<!-- -->\n", "<root><h level=\"3\" i=\"1\">=== Foo ===<comment>&lt;!-- --&gt;</comment></h>\n</root>" ],
+                       [ "=== Foo ===<!-- --> <!-- -->\n", "<root><h level=\"3\" i=\"1\">=== Foo ===<comment>&lt;!-- --&gt;</comment> <comment>&lt;!-- --&gt;</comment></h>\n</root>" ],
+                       [ "== Foo ==\n== Bar == \n", "<root><h level=\"2\" i=\"1\">== Foo ==</h>\n<h level=\"2\" i=\"2\">== Bar == </h>\n</root>" ],
+                       [ "===========", "<root><h level=\"5\" i=\"1\">===========</h></root>" ],
+                       [ "Foo\n=\n==\n=\n", "<root>Foo\n=\n==\n=\n</root>" ],
+                       [ "{{Foo}}", "<root><template><title>Foo</title></template></root>" ],
+                       [ "\n{{Foo}}", "<root>\n<template lineStart=\"1\"><title>Foo</title></template></root>" ],
+                       [ "{{Foo|bar}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template></root>" ],
+                       [ "{{Foo|bar}}a", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part></template>a</root>" ],
+                       [ "{{Foo|bar|baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name index=\"2\" /><value>baz</value></part></template></root>" ],
+                       [ "{{Foo|1=bar}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part></template></root>" ],
+                       [ "{{Foo|=bar}}", "<root><template><title>Foo</title><part><name></name>=<value>bar</value></part></template></root>" ],
+                       [ "{{Foo|bar=baz}}", "<root><template><title>Foo</title><part><name>bar</name>=<value>baz</value></part></template></root>" ],
+                       [ "{{Foo|{{bar}}=baz}}", "<root><template><title>Foo</title><part><name><template><title>bar</title></template></name>=<value>baz</value></part></template></root>" ],
+                       [ "{{Foo|1=bar|baz}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name index=\"1\" /><value>baz</value></part></template></root>" ],
+                       [ "{{Foo|1=bar|2=baz}}", "<root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name>2</name>=<value>baz</value></part></template></root>" ],
+                       [ "{{Foo|bar|foo=baz}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name>foo</name>=<value>baz</value></part></template></root>" ],
+                       [ "{{{1}}}", "<root><tplarg><title>1</title></tplarg></root>" ],
+                       [ "{{{1|}}}", "<root><tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg></root>" ],
+                       [ "{{{Foo}}}", "<root><tplarg><title>Foo</title></tplarg></root>" ],
+                       [ "{{{Foo|}}}", "<root><tplarg><title>Foo</title><part><name index=\"1\" /><value></value></part></tplarg></root>" ],
+                       [ "{{{Foo|bar|baz}}}", "<root><tplarg><title>Foo</title><part><name index=\"1\" /><value>bar</value></part><part><name index=\"2\" /><value>baz</value></part></tplarg></root>" ],
+                       [ "{<!-- -->{Foo}}", "<root>{<comment>&lt;!-- --&gt;</comment>{Foo}}</root>" ],
+                       [ "{{{{Foobar}}}}", "<root>{<tplarg><title>Foobar</title></tplarg>}</root>" ],
+                       [ "{{{ {{Foo}} }}}", "<root><tplarg><title> <template><title>Foo</title></template> </title></tplarg></root>" ],
+                       [ "{{ {{{Foo}}} }}", "<root><template><title> <tplarg><title>Foo</title></tplarg> </title></template></root>" ],
+                       [ "{{{{{Foo}}}}}", "<root><template><title><tplarg><title>Foo</title></tplarg></title></template></root>" ],
+                       [ "{{{{{Foo}} }}}", "<root><tplarg><title><template><title>Foo</title></template> </title></tplarg></root>" ],
+                       [ "{{{{{{Foo}}}}}}", "<root><tplarg><title><tplarg><title>Foo</title></tplarg></title></tplarg></root>" ],
+                       [ "{{{{{{Foo}}}}}", "<root>{<template><title><tplarg><title>Foo</title></tplarg></title></template></root>" ],
+                       [ "[[[Foo]]", "<root>[[[Foo]]</root>" ],
+                       [ "{{Foo|[[[[bar]]|baz]]}}", "<root><template><title>Foo</title><part><name index=\"1\" /><value>[[[[bar]]|baz]]</value></part></template></root>" ], // This test is important, since it means the difference between having the [[ rule stacked or not
+                       [ "{{Foo|[[[[bar]|baz]]}}", "<root>{{Foo|[[[[bar]|baz]]}}</root>" ],
+                       [ "{{Foo|Foo [[[[bar]|baz]]}}", "<root>{{Foo|Foo [[[[bar]|baz]]}}</root>" ],
+                       [ "Foo <display map>Bar</display map             >Baz", "<root>Foo <ext><name>display map</name><attr></attr><inner>Bar</inner><close>&lt;/display map             &gt;</close></ext>Baz</root>" ],
+                       [ "Foo <display map foo>Bar</display map             >Baz", "<root>Foo <ext><name>display map</name><attr> foo</attr><inner>Bar</inner><close>&lt;/display map             &gt;</close></ext>Baz</root>" ],
+                       [ "Foo <gallery bar=\"baz\" />", "<root>Foo <ext><name>gallery</name><attr> bar=&quot;baz&quot; </attr></ext></root>" ],
+                       [ "Foo <gallery bar=\"1\" baz=2 />", "<root>Foo <ext><name>gallery</name><attr> bar=&quot;1&quot; baz=2 </attr></ext></root>" ],
+                       [ "</foo>Foo<//foo>", "<root><ext><name>/foo</name><attr></attr><inner>Foo</inner><close>&lt;//foo&gt;</close></ext></root>" ], # Worth blacklisting IMHO
+                       [ "{{#ifexpr: ({{{1|1}}} = 2) | Foo | Bar }}", "<root><template><title>#ifexpr: (<tplarg><title>1</title><part><name index=\"1\" /><value>1</value></part></tplarg> = 2) </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>" ],
+                       [ "{{#if: {{{1|}}} | Foo | {{Bar}} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> <template><title>Bar</title></template> </value></part></template></root>" ],
+                       [ "{{#if: {{{1|}}} | Foo | [[Bar]] }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> Foo </value></part><part><name index=\"2\" /><value> [[Bar]] </value></part></template></root>" ],
+                       [ "{{#if: {{{1|}}} | [[Foo]] | Bar }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> [[Foo]] </value></part><part><name index=\"2\" /><value> Bar </value></part></template></root>" ],
+                       [ "{{#if: {{{1|}}} | 1 | {{#if: {{{1|}}} | 2 | 3 }} }}", "<root><template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 1 </value></part><part><name index=\"2\" /><value> <template><title>#if: <tplarg><title>1</title><part><name index=\"1\" /><value></value></part></tplarg> </title><part><name index=\"1\" /><value> 2 </value></part><part><name index=\"2\" /><value> 3 </value></part></template> </value></part></template></root>" ],
+                       [ "{{ {{Foo}}", "<root>{{ <template><title>Foo</title></template></root>" ],
+                       [ "{{Foobar {{Foo}} {{Bar}} {{Baz}} ", "<root>{{Foobar <template><title>Foo</title></template> <template><title>Bar</title></template> <template><title>Baz</title></template> </root>" ],
+                       [ "[[Foo]] |", "<root>[[Foo]] |</root>" ],
+                       [ "{{Foo|Bar|", "<root>{{Foo|Bar|</root>" ],
+                       [ "[[Foo]", "<root>[[Foo]</root>" ],
+                       [ "[[Foo|Bar]", "<root>[[Foo|Bar]</root>" ],
+                       [ "{{Foo| [[Bar] }}", "<root>{{Foo| [[Bar] }}</root>" ],
+                       [ "{{Foo| [[Bar|Baz] }}", "<root>{{Foo| [[Bar|Baz] }}</root>" ],
+                       [ "{{Foo|bar=[[baz]}}", "<root>{{Foo|bar=[[baz]}}</root>" ],
+                       [ "{{foo|", "<root>{{foo|</root>" ],
+                       [ "{{foo|}", "<root>{{foo|}</root>" ],
+                       [ "{{foo|} }}", "<root><template><title>foo</title><part><name index=\"1\" /><value>} </value></part></template></root>" ],
+                       [ "{{foo|bar=|}", "<root>{{foo|bar=|}</root>" ],
+                       [ "{{Foo|} Bar=", "<root>{{Foo|} Bar=</root>" ],
+                       [ "{{Foo|} Bar=}}", "<root><template><title>Foo</title><part><name>} Bar</name>=<value></value></part></template></root>" ],
+                       /* [ file_get_contents( __DIR__ . '/QuoteQuran.txt' ], file_get_contents( __DIR__ . '/QuoteQuranExpanded.txt' ) ], */
+               ];
                // @codingStandardsIgnoreEnd
        }
 
@@ -162,13 +162,13 @@ class PreprocessorTest extends MediaWikiTestCase {
         */
        public static function provideFiles() {
                // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-               return array(
-                       array( "QuoteQuran" ), # http://en.wikipedia.org/w/index.php?title=Template:QuoteQuran/sandbox&oldid=237348988 GFDL + CC BY-SA by Striver
-                       array( "Factorial" ), # http://en.wikipedia.org/w/index.php?title=Template:Factorial&oldid=98548758 GFDL + CC BY-SA by Polonium
-                       array( "All_system_messages" ), # http://tl.wiktionary.org/w/index.php?title=Suleras:All_system_messages&oldid=2765 GPL text generated by MediaWiki
-                       array( "Fundraising" ), # http://tl.wiktionary.org/w/index.php?title=MediaWiki:Sitenotice&oldid=5716 GFDL + CC BY-SA, copied there by Sky Harbor.
-                       array( "NestedTemplates" ), # bug 27936
-               );
+               return [
+                       [ "QuoteQuran" ], # http://en.wikipedia.org/w/index.php?title=Template:QuoteQuran/sandbox&oldid=237348988 GFDL + CC BY-SA by Striver
+                       [ "Factorial" ], # http://en.wikipedia.org/w/index.php?title=Template:Factorial&oldid=98548758 GFDL + CC BY-SA by Polonium
+                       [ "All_system_messages" ], # http://tl.wiktionary.org/w/index.php?title=Suleras:All_system_messages&oldid=2765 GPL text generated by MediaWiki
+                       [ "Fundraising" ], # http://tl.wiktionary.org/w/index.php?title=MediaWiki:Sitenotice&oldid=5716 GFDL + CC BY-SA, copied there by Sky Harbor.
+                       [ "NestedTemplates" ], # bug 27936
+               ];
                // @codingStandardsIgnoreEnd
        }
 
@@ -197,43 +197,43 @@ class PreprocessorTest extends MediaWikiTestCase {
         */
        public static function provideHeadings() {
                // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-               return array( /* These should become headings: */
-                       array( "== h ==<!--c1-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment></h></root>" ),
-                       array( "== h ==         <!--c1-->", "<root><h level=\"2\" i=\"1\">== h ==       <comment>&lt;!--c1--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1-->        ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>      </h></root>" ),
-                       array( "== h ==         <!--c1-->       ", "<root><h level=\"2\" i=\"1\">== h ==        <comment>&lt;!--c1--&gt;</comment>      </h></root>" ),
-                       array( "== h ==<!--c1--><!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment></h></root>" ),
-                       array( "== h ==         <!--c1--><!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==      <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1--><!--c2-->       ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>    </h></root>" ),
-                       array( "== h ==         <!--c1--><!--c2-->      ", "<root><h level=\"2\" i=\"1\">== h ==        <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>    </h></root>" ),
-                       array( "== h ==         <!--c1-->  <!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==    <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1-->  <!--c2-->     ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  </h></root>" ),
-                       array( "== h ==         <!--c1-->  <!--c2-->    ", "<root><h level=\"2\" i=\"1\">== h ==        <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  </h></root>" ),
-                       array( "== h ==<!--c1--><!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1-->  <!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1--><!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1-->  <!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==  <!--c1--><!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==  <!--c1-->  <!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==  <!--c1--><!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==  <!--c1-->  <!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1--><!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==<!--c1-->  <!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==<!--c1--><!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==<!--c1-->  <!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==  <!--c1--><!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==  <!--c1-->  <!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==  <!--c1--><!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==  <!--c1-->  <!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ),
-                       array( "== h ==<!--c1-->        <!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>     <comment>&lt;!--c2--&gt;</comment></h></root>" ),
-                       array( "== h ==         <!--c1-->       <!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==       <comment>&lt;!--c1--&gt;</comment>      <comment>&lt;!--c2--&gt;</comment></h></root>" ),
-                       array( "== h ==<!--c1-->        <!--c2-->       ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>      <comment>&lt;!--c2--&gt;</comment>      </h></root>" ),
+               return [ /* These should become headings: */
+                       [ "== h ==<!--c1-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment></h></root>" ],
+                       [ "== h ==      <!--c1-->", "<root><h level=\"2\" i=\"1\">== h ==       <comment>&lt;!--c1--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1-->     ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>      </h></root>" ],
+                       [ "== h ==      <!--c1-->       ", "<root><h level=\"2\" i=\"1\">== h ==        <comment>&lt;!--c1--&gt;</comment>      </h></root>" ],
+                       [ "== h ==<!--c1--><!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment></h></root>" ],
+                       [ "== h ==      <!--c1--><!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==      <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1--><!--c2-->    ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>    </h></root>" ],
+                       [ "== h ==      <!--c1--><!--c2-->      ", "<root><h level=\"2\" i=\"1\">== h ==        <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>    </h></root>" ],
+                       [ "== h ==      <!--c1-->  <!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==    <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1-->  <!--c2-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  </h></root>" ],
+                       [ "== h ==      <!--c1-->  <!--c2-->    ", "<root><h level=\"2\" i=\"1\">== h ==        <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  </h></root>" ],
+                       [ "== h ==<!--c1--><!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1-->  <!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1--><!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1-->  <!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==  <!--c1--><!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==  <!--c1-->  <!--c2--><!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==  <!--c1--><!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==  <!--c1-->  <!--c2-->  <!--c3-->", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1--><!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==<!--c1-->  <!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==<!--c1--><!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==<!--c1-->  <!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==  <!--c1--><!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==  <!--c1-->  <!--c2--><!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==  <!--c1--><!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==  <!--c1-->  <!--c2-->  <!--c3-->  ", "<root><h level=\"2\" i=\"1\">== h ==  <comment>&lt;!--c1--&gt;</comment>  <comment>&lt;!--c2--&gt;</comment>  <comment>&lt;!--c3--&gt;</comment>  </h></root>" ],
+                       [ "== h ==<!--c1-->     <!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>     <comment>&lt;!--c2--&gt;</comment></h></root>" ],
+                       [ "== h ==      <!--c1-->       <!--c2-->", "<root><h level=\"2\" i=\"1\">== h ==       <comment>&lt;!--c1--&gt;</comment>      <comment>&lt;!--c2--&gt;</comment></h></root>" ],
+                       [ "== h ==<!--c1-->     <!--c2-->       ", "<root><h level=\"2\" i=\"1\">== h ==<comment>&lt;!--c1--&gt;</comment>      <comment>&lt;!--c2--&gt;</comment>      </h></root>" ],
 
                        /* These are not working: */
-                       array( "== h == x <!--c1--><!--c2--><!--c3-->  ", "<root>== h == x <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </root>" ),
-                       array( "== h ==<!--c1--> x <!--c2--><!--c3-->  ", "<root>== h ==<comment>&lt;!--c1--&gt;</comment> x <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </root>" ),
-                       array( "== h ==<!--c1--><!--c2--><!--c3--> x ", "<root>== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment> x </root>" ),
-               );
+                       [ "== h == x <!--c1--><!--c2--><!--c3-->  ", "<root>== h == x <comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </root>" ],
+                       [ "== h ==<!--c1--> x <!--c2--><!--c3-->  ", "<root>== h ==<comment>&lt;!--c1--&gt;</comment> x <comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment>  </root>" ],
+                       [ "== h ==<!--c1--><!--c2--><!--c3--> x ", "<root>== h ==<comment>&lt;!--c1--&gt;</comment><comment>&lt;!--c2--&gt;</comment><comment>&lt;!--c3--&gt;</comment> x </root>" ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index d6940b5..8f80362 100644 (file)
@@ -13,28 +13,28 @@ class BcryptPasswordTest extends PasswordTestCase {
 
        public static function providePasswordTests() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
+               return [
                        // Tests from glibc bcrypt implementation
-                       array( true, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "U*U" ),
-                       array( true, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$VGOzA784oUp/Z0DY336zx7pLYAy0lwK', "U*U*" ),
-                       array( true, ':bcrypt:5$XXXXXXXXXXXXXXXXXXXXXO$AcXxm9kjPGEMsLznoKqmqw7tc8WCx4a', "U*U*U" ),
-                       array( true, ':bcrypt:5$abcdefghijklmnopqrstuu$5s2v8.iXieOjg/.AySBTTZIIVFJeBui', "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789chars after 72 are ignored" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$CE5elHaaO4EbggVDjb8P19RukzXSM3e', "\xff\xff\xa3" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq', "\xa3" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq', "\xa3" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$o./n25XVfn6oAPaUvHe.Csk4zRfsYPi', "\xff\xa334\xff\xff\xff\xa3345" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$nRht2l/HRhr6zmCp9vYUvvsqynflf9e', "\xff\xa3345" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$nRht2l/HRhr6zmCp9vYUvvsqynflf9e', "\xff\xa3345" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$6IflQkJytoRVc1yuaNtHfiuq.FRlSIS', "\xa3ab" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$6IflQkJytoRVc1yuaNtHfiuq.FRlSIS', "\xa3ab" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6', "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaachars after 72 are ignored as usual" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy', "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" ),
-                       array( true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe', "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" ),
-                       array( true, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy', "" ),
+                       [ true, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "U*U" ],
+                       [ true, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$VGOzA784oUp/Z0DY336zx7pLYAy0lwK', "U*U*" ],
+                       [ true, ':bcrypt:5$XXXXXXXXXXXXXXXXXXXXXO$AcXxm9kjPGEMsLznoKqmqw7tc8WCx4a', "U*U*U" ],
+                       [ true, ':bcrypt:5$abcdefghijklmnopqrstuu$5s2v8.iXieOjg/.AySBTTZIIVFJeBui', "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789chars after 72 are ignored" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$CE5elHaaO4EbggVDjb8P19RukzXSM3e', "\xff\xff\xa3" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq', "\xa3" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq', "\xa3" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$o./n25XVfn6oAPaUvHe.Csk4zRfsYPi', "\xff\xa334\xff\xff\xff\xa3345" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$nRht2l/HRhr6zmCp9vYUvvsqynflf9e', "\xff\xa3345" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$nRht2l/HRhr6zmCp9vYUvvsqynflf9e', "\xff\xa3345" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$6IflQkJytoRVc1yuaNtHfiuq.FRlSIS', "\xa3ab" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$6IflQkJytoRVc1yuaNtHfiuq.FRlSIS', "\xa3ab" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6', "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaachars after 72 are ignored as usual" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy', "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" ],
+                       [ true, ':bcrypt:5$/OK.fbVrR/bpIqNJ5ianF.$9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe', "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" ],
+                       [ true, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy', "" ],
                        // One or two false sanity tests
-                       array( false, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "UXU" ),
-                       array( false, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "" ),
-               );
+                       [ false, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "UXU" ],
+                       [ false, ':bcrypt:5$CCCCCCCCCCCCCCCCCCCCC.$E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW', "" ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 }
index cccec5f..773f033 100644 (file)
@@ -28,9 +28,13 @@ class LayeredParameterizedPasswordTest extends PasswordTestCase {
 
        public static function providePasswordTests() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength.TooLong
-               return array(
-                       array( true, ':testLargeLayeredTop:sha512:1024:512!sha512:1024:512!sha512:1024:512!sha512:1024:512!5!vnRy+2SrSA0fHt3dwhTP5g==!AVnwfZsAQjn+gULv7FSGjA==!xvHUX3WcpkeSn1lvjWcvBg==!It+OC/N9tu+d3ByHhuB0BQ==!Tb.gqUOiD.aWktVwHM.Q/O!7CcyMfXUPky5ptyATJsR2nq3vUqtnBC', 'testPassword123' ),
-               );
+               return [
+                       [
+                               true,
+                               ':testLargeLayeredTop:sha512:1024:512!sha512:1024:512!sha512:1024:512!sha512:1024:512!5!vnRy+2SrSA0fHt3dwhTP5g==!AVnwfZsAQjn+gULv7FSGjA==!xvHUX3WcpkeSn1lvjWcvBg==!It+OC/N9tu+d3ByHhuB0BQ==!Tb.gqUOiD.aWktVwHM.Q/O!7CcyMfXUPky5ptyATJsR2nq3vUqtnBC',
+                               'testPassword123' 
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index af34282..6357510 100644 (file)
@@ -42,7 +42,7 @@ class PasswordPolicyChecksTest extends MediaWikiTestCase {
                        'Password is shorter than minimal policy'
                );
                $this->assertTrue(
-                       $statusShort->isOk(),
+                       $statusShort->isOK(),
                        'Password is shorter than minimal policy, not fatal'
                );
        }
@@ -67,7 +67,7 @@ class PasswordPolicyChecksTest extends MediaWikiTestCase {
                        'Password is shorter than minimum login policy'
                );
                $this->assertFalse(
-                       $statusShort->isOk(),
+                       $statusShort->isOK(),
                        'Password is shorter than minimum login policy, fatal'
                );
        }
@@ -90,7 +90,7 @@ class PasswordPolicyChecksTest extends MediaWikiTestCase {
                $this->assertFalse( $statusLong->isGood(),
                        'Password is longer than maximal policy'
                );
-               $this->assertFalse( $statusLong->isOk(),
+               $this->assertFalse( $statusLong->isOK(),
                        'Password is longer than maximal policy, fatal'
                );
        }
@@ -111,7 +111,7 @@ class PasswordPolicyChecksTest extends MediaWikiTestCase {
                        'user'  // password
                );
                $this->assertFalse( $statusLong->isGood(), 'Password matches username' );
-               $this->assertTrue( $statusLong->isOk(), 'Password matches username, not fatal' );
+               $this->assertTrue( $statusLong->isOK(), 'Password matches username, not fatal' );
        }
 
        /**
@@ -130,7 +130,7 @@ class PasswordPolicyChecksTest extends MediaWikiTestCase {
                        'Passpass1'  // password
                );
                $this->assertFalse( $statusLong->isGood(), 'Password matches blacklist' );
-               $this->assertTrue( $statusLong->isOk(), 'Password matches blacklist, not fatal' );
+               $this->assertTrue( $statusLong->isOK(), 'Password matches blacklist, not fatal' );
        }
 
 }
index d820040..d16200b 100644 (file)
@@ -112,7 +112,7 @@ class UserPasswordPolicyTest extends MediaWikiTestCase {
 
                $status = $upp->checkUserPassword( $user, $password );
                $this->assertSame( $valid, $status->isGood(), $msg . ' - password valid' );
-               $this->assertSame( $ok, $status->isOk(), $msg . ' - can login' );
+               $this->assertSame( $ok, $status->isOK(), $msg . ' - can login' );
        }
 
        public function provideCheckUserPassword() {
index 2a3a5fe..6a3f95b 100644 (file)
@@ -10,7 +10,7 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
         */
        private $search;
 
-       public function addDBData() {
+       public function addDBDataOnce() {
                if ( !$this->isWikitextNS( NS_MAIN ) ) {
                        // tests are skipped if NS_MAIN is not wikitext
                        return;
index b680d5e..055e982 100644 (file)
@@ -44,7 +44,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                parent::tearDown();
        }
 
-       public function addDBData() {
+       public function addDBDataOnce() {
                if ( !$this->isWikitextNS( NS_MAIN ) ) {
                        // @todo cover the case of non-wikitext content in the main namespace
                        return;
index 590f287..edab0dc 100644 (file)
@@ -33,8 +33,8 @@ class BotPasswordSessionProviderTest extends MediaWikiTestCase {
                                'EnableBotPasswords' => true,
                                'BotPasswordsDatabase' => false,
                                'SessionProviders' => $wgSessionProviders + [
-                                       'MediaWiki\\Session\\BotPasswordSessionProvider' => [
-                                               'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider',
+                                       BotPasswordSessionProvider::class => [
+                                               'class' => BotPasswordSessionProvider::class,
                                                'args' => [ $params ],
                                        ]
                                ],
@@ -46,7 +46,7 @@ class BotPasswordSessionProviderTest extends MediaWikiTestCase {
                        'store' => new TestBagOStuff,
                ] );
 
-               return $manager->getProvider( 'MediaWiki\\Session\\BotPasswordSessionProvider' );
+               return $manager->getProvider( BotPasswordSessionProvider::class );
        }
 
        protected function setUp() {
@@ -62,7 +62,7 @@ class BotPasswordSessionProviderTest extends MediaWikiTestCase {
                ] );
        }
 
-       public function addDBData() {
+       public function addDBDataOnce() {
                $passwordFactory = new \PasswordFactory();
                $passwordFactory->init( \RequestContext::getMain()->getConfig() );
                // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
@@ -154,7 +154,7 @@ class BotPasswordSessionProviderTest extends MediaWikiTestCase {
        public function testBasics() {
                $provider = $this->getProvider();
 
-               $this->assertTrue( $provider->persistsSessionID() );
+               $this->assertTrue( $provider->persistsSessionId() );
                $this->assertFalse( $provider->canChangeUser() );
 
                $this->assertNull( $provider->newSessionInfo() );
@@ -172,7 +172,7 @@ class BotPasswordSessionProviderTest extends MediaWikiTestCase {
                }
 
                $info = $provider->provideSessionInfo( $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\SessionInfo', $info );
+               $this->assertInstanceOf( SessionInfo::class, $info );
                $this->assertSame( 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $info->getId() );
 
                $this->config->set( 'EnableBotPasswords', false );
@@ -191,7 +191,7 @@ class BotPasswordSessionProviderTest extends MediaWikiTestCase {
                $bp = \BotPassword::newFromUser( $user, 'BotPasswordSessionProvider' );
 
                $session = $provider->newSessionForRequest( $user, $bp, $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
 
                $this->assertEquals( $session->getId(), $request->getSession()->getId() );
                $this->assertEquals( $user->getName(), $session->getUser()->getName() );
index a52aa4b..70e89d4 100644 (file)
@@ -145,7 +145,7 @@ class CookieSessionProviderTest extends MediaWikiTestCase {
        public function testBasics() {
                $provider = new CookieSessionProvider( [ 'priority' => 10 ] );
 
-               $this->assertTrue( $provider->persistsSessionID() );
+               $this->assertTrue( $provider->persistsSessionId() );
                $this->assertTrue( $provider->canChangeUser() );
 
                $msg = $provider->whyNoSession();
index 2412a3b..d705fc0 100644 (file)
@@ -24,7 +24,7 @@ class ImmutableSessionProviderWithCookieTest extends MediaWikiTestCase {
                        $params['sessionCookieOptions']['prefix'] = $prefix;
                }
 
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\ImmutableSessionProviderWithCookie' )
+               $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie::class )
                        ->setConstructorArgs( [ $params ] )
                        ->getMockForAbstractClass();
                $provider->setLogger( new \TestLogger() );
@@ -35,13 +35,13 @@ class ImmutableSessionProviderWithCookieTest extends MediaWikiTestCase {
        }
 
        public function testConstructor() {
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\ImmutableSessionProviderWithCookie' )
+               $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie::class )
                        ->getMockForAbstractClass();
                $priv = \TestingAccessWrapper::newFromObject( $provider );
                $this->assertNull( $priv->sessionCookieName );
                $this->assertSame( [], $priv->sessionCookieOptions );
 
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\ImmutableSessionProviderWithCookie' )
+               $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie::class )
                        ->setConstructorArgs( [ [
                                'sessionCookieName' => 'Foo',
                                'sessionCookieOptions' => [ 'Bar' ],
@@ -52,7 +52,7 @@ class ImmutableSessionProviderWithCookieTest extends MediaWikiTestCase {
                $this->assertSame( [ 'Bar' ], $priv->sessionCookieOptions );
 
                try {
-                       $provider = $this->getMockBuilder( 'MediaWiki\\Session\\ImmutableSessionProviderWithCookie' )
+                       $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie::class )
                                ->setConstructorArgs( [ [
                                        'sessionCookieName' => false,
                                ] ] )
@@ -66,7 +66,7 @@ class ImmutableSessionProviderWithCookieTest extends MediaWikiTestCase {
                }
 
                try {
-                       $provider = $this->getMockBuilder( 'MediaWiki\\Session\\ImmutableSessionProviderWithCookie' )
+                       $provider = $this->getMockBuilder( ImmutableSessionProviderWithCookie::class )
                                ->setConstructorArgs( [ [
                                        'sessionCookieOptions' => 'x',
                                ] ] )
index 64b16db..ce0f1b0 100644 (file)
@@ -23,7 +23,7 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
                } );
                $reset[] = new \ScopedCallback( 'restore_error_handler' );
 
-               $rProp = new \ReflectionProperty( 'MediaWiki\\Session\\PHPSessionHandler', 'instance' );
+               $rProp = new \ReflectionProperty( PHPSessionHandler::class, 'instance' );
                $rProp->setAccessible( true );
                if ( $rProp->getValue() ) {
                        $old = \TestingAccessWrapper::newFromObject( $rProp->getValue() );
@@ -31,7 +31,7 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
                        $oldStore = $old->store;
                        $oldLogger = $old->logger;
                        $reset[] = new \ScopedCallback(
-                               [ 'MediaWiki\\Session\\PHPSessionHandler', 'install' ],
+                               [ PHPSessionHandler::class, 'install' ],
                                [ $oldManager, $oldStore, $oldLogger ]
                        );
                }
@@ -41,13 +41,13 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
 
        public function testEnableFlags() {
                $handler = \TestingAccessWrapper::newFromObject(
-                       $this->getMockBuilder( 'MediaWiki\\Session\\PHPSessionHandler' )
+                       $this->getMockBuilder( PHPSessionHandler::class )
                                ->setMethods( null )
                                ->disableOriginalConstructor()
                                ->getMock()
                );
 
-               $rProp = new \ReflectionProperty( 'MediaWiki\\Session\\PHPSessionHandler', 'instance' );
+               $rProp = new \ReflectionProperty( PHPSessionHandler::class, 'instance' );
                $rProp->setAccessible( true );
                $reset = new \ScopedCallback( [ $rProp, 'setValue' ], [ $rProp->getValue() ] );
                $rProp->setValue( $handler );
@@ -292,7 +292,9 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
                // Test that write doesn't break if the session is invalid
                $session = $manager->getEmptySession();
                $session->persist();
-               session_id( $session->getId() );
+               $id = $session->getId();
+               unset( $session );
+               session_id( $id );
                session_start();
                $this->mergeMwGlobalArrayValue( 'wgHooks', [
                        'SessionCheckInfo' => [ function ( &$reason ) {
@@ -300,12 +302,13 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
                                return false;
                        } ],
                ] );
-               $this->assertNull( $manager->getSessionById( $session->getId(), true ), 'sanity check' );
+               $this->assertNull( $manager->getSessionById( $id, true ), 'sanity check' );
                session_write_close();
+
                $this->mergeMwGlobalArrayValue( 'wgHooks', [
                        'SessionCheckInfo' => [],
                ] );
-               $this->assertNotNull( $manager->getSessionById( $session->getId(), true ), 'sanity check' );
+               $this->assertNotNull( $manager->getSessionById( $id, true ), 'sanity check' );
        }
 
        public static function provideHandlers() {
@@ -322,9 +325,9 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
         * @expectedExceptionMessage Attempt to use PHP session management
         */
        public function testDisabled( $method, $args ) {
-               $rProp = new \ReflectionProperty( 'MediaWiki\\Session\\PHPSessionHandler', 'instance' );
+               $rProp = new \ReflectionProperty( PHPSessionHandler::class, 'instance' );
                $rProp->setAccessible( true );
-               $handler = $this->getMockBuilder( 'MediaWiki\\Session\\PHPSessionHandler' )
+               $handler = $this->getMockBuilder( PHPSessionHandler::class )
                        ->setMethods( null )
                        ->disableOriginalConstructor()
                        ->getMock();
@@ -351,7 +354,7 @@ class PHPSessionHandlerTest extends MediaWikiTestCase {
         * @expectedExceptionMessageRegExp /: Wrong instance called!$/
         */
        public function testWrongInstance( $method, $args ) {
-               $handler = $this->getMockBuilder( 'MediaWiki\\Session\\PHPSessionHandler' )
+               $handler = $this->getMockBuilder( PHPSessionHandler::class )
                        ->setMethods( null )
                        ->disableOriginalConstructor()
                        ->getMock();
index 61be8e0..0b5f4c2 100644 (file)
@@ -23,8 +23,9 @@ class SessionBackendTest extends MediaWikiTestCase {
        /**
         * Returns a non-persistent backend that thinks it has at least one session active
         * @param User|null $user
+        * @param string $id
         */
-       protected function getBackend( User $user = null ) {
+       protected function getBackend( User $user = null, $id = null ) {
                if ( !$this->config ) {
                        $this->config = new \HashConfig();
                        $this->manager = null;
@@ -52,7 +53,7 @@ class SessionBackendTest extends MediaWikiTestCase {
 
                $info = new SessionInfo( SessionInfo::MIN_PRIORITY, [
                        'provider' => $this->provider,
-                       'id' => self::SESSIONID,
+                       'id' => $id ?: self::SESSIONID,
                        'persisted' => true,
                        'userInfo' => UserInfo::newFromUser( $user ?: new User, true ),
                        'idIsSafe' => true,
@@ -67,8 +68,8 @@ class SessionBackendTest extends MediaWikiTestCase {
                $priv->usePhpSessionHandling = false;
 
                $manager = \TestingAccessWrapper::newFromObject( $this->manager );
-               $manager->allSessionBackends = [ $backend->getId() => $backend ];
-               $manager->allSessionIds = [ $backend->getId() => $id ];
+               $manager->allSessionBackends = [ $backend->getId() => $backend ] + $manager->allSessionBackends;
+               $manager->allSessionIds = [ $backend->getId() => $id ] + $manager->allSessionIds;
                $manager->sessionProviders = [ (string)$this->provider => $this->provider ];
 
                return $backend;
@@ -183,8 +184,8 @@ class SessionBackendTest extends MediaWikiTestCase {
                $request2 = new \FauxRequest();
                $session2 = $backend->getSession( $request2 );
 
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session1 );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session2 );
+               $this->assertInstanceOf( Session::class, $session1 );
+               $this->assertInstanceOf( Session::class, $session2 );
                $this->assertSame( 2, count( $priv->requests ) );
 
                $index = \TestingAccessWrapper::newFromObject( $session1 )->index;
@@ -813,12 +814,52 @@ class SessionBackendTest extends MediaWikiTestCase {
                $metadata['???'] = '!!!';
        }
 
+       public function testTakeOverGlobalSession() {
+               if ( !PHPSessionHandler::isInstalled() ) {
+                       PHPSessionHandler::install( SessionManager::singleton() );
+               }
+               if ( !PHPSessionHandler::isEnabled() ) {
+                       $rProp = new \ReflectionProperty( PHPSessionHandler::class, 'instance' );
+                       $rProp->setAccessible( true );
+                       $handler = \TestingAccessWrapper::newFromObject( $rProp->getValue() );
+                       $resetHandler = new \ScopedCallback( function () use ( $handler ) {
+                               session_write_close();
+                               $handler->enable = false;
+                       } );
+                       $handler->enable = true;
+               }
+
+               $backend = $this->getBackend( User::newFromName( 'UTSysop' ) );
+               \TestingAccessWrapper::newFromObject( $backend )->usePhpSessionHandling = true;
+
+               $resetSingleton = TestUtils::setSessionManagerSingleton( $this->manager );
+
+               $manager = \TestingAccessWrapper::newFromObject( $this->manager );
+               $request = \RequestContext::getMain()->getRequest();
+               $manager->globalSession = $backend->getSession( $request );
+               $manager->globalSessionRequest = $request;
+
+               session_id( '' );
+               \TestingAccessWrapper::newFromObject( $backend )->checkPHPSession();
+               $this->assertSame( $backend->getId(), session_id() );
+               session_write_close();
+
+               $backend2 = $this->getBackend(
+                       User::newFromName( 'UTSysop' ), 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
+               );
+               \TestingAccessWrapper::newFromObject( $backend2 )->usePhpSessionHandling = true;
+
+               session_id( '' );
+               \TestingAccessWrapper::newFromObject( $backend2 )->checkPHPSession();
+               $this->assertSame( '', session_id() );
+       }
+
        public function testResetIdOfGlobalSession() {
                if ( !PHPSessionHandler::isInstalled() ) {
                        PHPSessionHandler::install( SessionManager::singleton() );
                }
                if ( !PHPSessionHandler::isEnabled() ) {
-                       $rProp = new \ReflectionProperty( 'MediaWiki\\Session\\PHPSessionHandler', 'instance' );
+                       $rProp = new \ReflectionProperty( PHPSessionHandler::class, 'instance' );
                        $rProp->setAccessible( true );
                        $handler = \TestingAccessWrapper::newFromObject( $rProp->getValue() );
                        $resetHandler = new \ScopedCallback( function () use ( $handler ) {
@@ -831,7 +872,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                $backend = $this->getBackend( User::newFromName( 'UTSysop' ) );
                \TestingAccessWrapper::newFromObject( $backend )->usePhpSessionHandling = true;
 
-               TestUtils::setSessionManagerSingleton( $this->manager );
+               $resetSingleton = TestUtils::setSessionManagerSingleton( $this->manager );
 
                $manager = \TestingAccessWrapper::newFromObject( $this->manager );
                $request = \RequestContext::getMain()->getRequest();
@@ -840,15 +881,12 @@ class SessionBackendTest extends MediaWikiTestCase {
 
                session_id( self::SESSIONID );
                \MediaWiki\quietCall( 'session_start' );
+               $_SESSION['foo'] = __METHOD__;
                $backend->resetId();
                $this->assertNotEquals( self::SESSIONID, $backend->getId() );
                $this->assertSame( $backend->getId(), session_id() );
-               session_write_close();
-
-               session_id( '' );
-               $this->assertNotSame( $backend->getId(), session_id(), 'sanity check' );
-               $backend->persist();
-               $this->assertSame( $backend->getId(), session_id() );
+               $this->assertArrayHasKey( 'foo', $_SESSION );
+               $this->assertSame( __METHOD__, $_SESSION['foo'] );
                session_write_close();
        }
 
@@ -857,7 +895,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                        PHPSessionHandler::install( SessionManager::singleton() );
                }
                if ( !PHPSessionHandler::isEnabled() ) {
-                       $rProp = new \ReflectionProperty( 'MediaWiki\\Session\\PHPSessionHandler', 'instance' );
+                       $rProp = new \ReflectionProperty( PHPSessionHandler::class, 'instance' );
                        $rProp->setAccessible( true );
                        $handler = \TestingAccessWrapper::newFromObject( $rProp->getValue() );
                        $resetHandler = new \ScopedCallback( function () use ( $handler ) {
@@ -872,7 +910,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                $wrap->usePhpSessionHandling = true;
                $wrap->persist = true;
 
-               TestUtils::setSessionManagerSingleton( $this->manager );
+               $resetSingleton = TestUtils::setSessionManagerSingleton( $this->manager );
 
                $manager = \TestingAccessWrapper::newFromObject( $this->manager );
                $request = \RequestContext::getMain()->getRequest();
index e702125..ff22bfa 100644 (file)
@@ -61,7 +61,7 @@ class SessionInfoTest extends MediaWikiTestCase {
                }
 
                $manager = new SessionManager();
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\SessionProvider' )
+               $provider = $this->getMockBuilder( SessionProvider::class )
                        ->setMethods( [ 'persistsSessionId', 'canChangeUser', '__toString' ] )
                        ->getMockForAbstractClass();
                $provider->setManager( $manager );
@@ -72,7 +72,7 @@ class SessionInfoTest extends MediaWikiTestCase {
                $provider->expects( $this->any() )->method( '__toString' )
                        ->will( $this->returnValue( 'Mock' ) );
 
-               $provider2 = $this->getMockBuilder( 'MediaWiki\\Session\\SessionProvider' )
+               $provider2 = $this->getMockBuilder( SessionProvider::class )
                        ->setMethods( [ 'persistsSessionId', 'canChangeUser', '__toString' ] )
                        ->getMockForAbstractClass();
                $provider2->setManager( $manager );
index a1b9bb4..6218f0a 100644 (file)
@@ -48,7 +48,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                $reset = TestUtils::setSessionManagerSingleton( null );
 
                $singleton = SessionManager::singleton();
-               $this->assertInstanceOf( 'MediaWiki\\Session\\SessionManager', $singleton );
+               $this->assertInstanceOf( SessionManager::class, $singleton );
                $this->assertSame( $singleton, SessionManager::singleton() );
        }
 
@@ -58,7 +58,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                if ( !PHPSessionHandler::isInstalled() ) {
                        PHPSessionHandler::install( SessionManager::singleton() );
                }
-               $rProp = new \ReflectionProperty( 'MediaWiki\\Session\\PHPSessionHandler', 'instance' );
+               $rProp = new \ReflectionProperty( PHPSessionHandler::class, 'instance' );
                $rProp->setAccessible( true );
                $handler = \TestingAccessWrapper::newFromObject( $rProp->getValue() );
                $oldEnable = $handler->enable;
@@ -191,7 +191,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                $request->info1 = null;
                $request->info2 = null;
                $session = $manager->getSessionForRequest( $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $idEmpty, $session->getId() );
                $this->assertFalse( $request->unpersist1 );
                $this->assertFalse( $request->unpersist2 );
@@ -210,7 +210,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ] );
                $session = $manager->getSessionForRequest( $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $id2, $session->getId() );
                $this->assertFalse( $request->unpersist1 );
                $this->assertFalse( $request->unpersist2 );
@@ -228,7 +228,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ] );
                $session = $manager->getSessionForRequest( $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $id1, $session->getId() );
                $this->assertFalse( $request->unpersist1 );
                $this->assertFalse( $request->unpersist2 );
@@ -251,7 +251,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                try {
                        $manager->getSessionForRequest( $request );
                        $this->fail( 'Expcected exception not thrown' );
-               } catch ( \OverFlowException $ex ) {
+               } catch ( \OverflowException $ex ) {
                        $this->assertStringStartsWith(
                                'Multiple sessions for this request tied for top priority: ',
                                $ex->getMessage()
@@ -299,7 +299,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ] );
                $session = $manager->getSessionForRequest( $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $id2, $session->getId() );
                $this->logger->setCollect( false );
                $this->assertTrue( $request->unpersist1 );
@@ -321,7 +321,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ] );
                $session = $manager->getSessionForRequest( $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $id1, $session->getId() );
                $this->logger->setCollect( false );
                $this->assertFalse( $request->unpersist1 );
@@ -338,7 +338,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                ] );
                $request->info2 = null;
                $session = $manager->getSessionForRequest( $request );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $id1, $session->getId() );
                $this->assertTrue( $request->unpersist1 ); // The saving of the session does it
                $this->assertFalse( $request->unpersist2 );
@@ -358,7 +358,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                // Unknown session ID
                $id = $manager->generateSessionId();
                $session = $manager->getSessionById( $id, true );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $id, $session->getId() );
 
                $id = $manager->generateSessionId();
@@ -379,8 +379,42 @@ class SessionManagerTest extends MediaWikiTestCase {
                // Known session ID
                $this->store->setSession( $id, [] );
                $session = $manager->getSessionById( $id, false );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $id, $session->getId() );
+
+               // Store isn't checked if the session is already loaded
+               $this->store->setSession( $id, [ 'metadata' => [
+                       'userId' => User::idFromName( 'UTSysop' ),
+                       'userToken' => 'bad',
+               ] ] );
+               $session2 = $manager->getSessionById( $id, false );
+               $this->assertInstanceOf( Session::class, $session2 );
+               $this->assertSame( $id, $session2->getId() );
+               unset( $session, $session2 );
+               $this->logger->setCollect( true );
+               $this->assertNull( $manager->getSessionById( $id, true ) );
+               $this->logger->setCollect( false );
+
+               // Failure to create an empty session
+               $manager = $this->getManager();
+               $provider = $this->getMockBuilder( 'DummySessionProvider' )
+                       ->setMethods( [ 'provideSessionInfo', 'newSessionInfo', '__toString' ] )
+                       ->getMock();
+               $provider->expects( $this->any() )->method( 'provideSessionInfo' )
+                       ->will( $this->returnValue( null ) );
+               $provider->expects( $this->any() )->method( 'newSessionInfo' )
+                       ->will( $this->returnValue( null ) );
+               $provider->expects( $this->any() )->method( '__toString' )
+                       ->will( $this->returnValue( 'MockProvider' ) );
+               $this->config->set( 'SessionProviders', [
+                       $this->objectCacheDef( $provider ),
+               ] );
+               $this->logger->setCollect( true );
+               $this->assertNull( $manager->getSessionById( $id, true ) );
+               $this->logger->setCollect( false );
+               $this->assertSame( [
+                       [ LogLevel::ERROR, 'Failed to create empty session: {exception}' ]
+               ], $this->logger->getBuffer() );
        }
 
        public function testGetEmptySession() {
@@ -450,7 +484,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                ] );
                $info2 = null;
                $session = $manager->getEmptySession();
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( 'empty---------------------------', $session->getId() );
 
                // Info, explicitly
@@ -463,7 +497,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                ] );
                $info2 = null;
                $session = $pmanager->getEmptySessionInternal( null, $expectId );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( $expectId, $session->getId() );
 
                // Wrong ID
@@ -538,7 +572,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ] );
                $session = $manager->getEmptySession();
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( 'empty1--------------------------', $session->getId() );
 
                $expectId = null;
@@ -555,7 +589,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                        'idIsSafe' => true,
                ] );
                $session = $manager->getEmptySession();
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( Session::class, $session );
                $this->assertSame( 'empty2--------------------------', $session->getId() );
 
                // Tied priorities throw an exception
@@ -809,7 +843,7 @@ class SessionManagerTest extends MediaWikiTestCase {
 
                \ObjectCache::$instances[__METHOD__] = new TestBagOStuff();
                $this->setMwGlobals( [ 'wgMainCacheType' => __METHOD__ ] );
-               $this->setMWGlobals( [
+               $this->setMwGlobals( [
                        'wgAuth' => new AuthPlugin,
                ] );
 
@@ -1143,7 +1177,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                        'provider' => 'Mock',
                ];
 
-               $builder = $this->getMockBuilder( 'MediaWiki\\Session\\SessionProvider' )
+               $builder = $this->getMockBuilder( SessionProvider::class )
                        ->setMethods( [ '__toString', 'mergeMetadata', 'refreshSessionInfo' ] );
 
                $provider = $builder->getMockForAbstractClass();
@@ -1258,7 +1292,7 @@ class SessionManagerTest extends MediaWikiTestCase {
                ] );
                $this->assertFalse( $info->isIdSafe(), 'sanity check' );
                $this->assertTrue( $loadSessionInfoFromStore( $info ) );
-               $this->assertInstanceOf( 'MediaWiki\\Session\\UserInfo', $info->getUserInfo() );
+               $this->assertInstanceOf( UserInfo::class, $info->getUserInfo() );
                $this->assertTrue( $info->getUserInfo()->isVerified() );
                $this->assertTrue( $info->getUserInfo()->isAnon() );
                $this->assertFalse( $info->isIdSafe() );
index e92eb09..18b1efd 100644 (file)
@@ -16,7 +16,7 @@ class SessionProviderTest extends MediaWikiTestCase {
                $logger = new \TestLogger();
                $config = new \HashConfig();
 
-               $provider = $this->getMockForAbstractClass( 'MediaWiki\\Session\\SessionProvider' );
+               $provider = $this->getMockForAbstractClass( SessionProvider::class );
                $priv = \TestingAccessWrapper::newFromObject( $provider );
 
                $provider->setConfig( $config );
@@ -53,7 +53,7 @@ class SessionProviderTest extends MediaWikiTestCase {
        public function testNewSessionInfo( $persistId, $persistUser, $ok ) {
                $manager = new SessionManager();
 
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\SessionProvider' )
+               $provider = $this->getMockBuilder( SessionProvider::class )
                        ->setMethods( [ 'canChangeUser', 'persistsSessionId' ] )
                        ->getMockForAbstractClass();
                $provider->expects( $this->any() )->method( 'persistsSessionId' )
@@ -80,7 +80,7 @@ class SessionProviderTest extends MediaWikiTestCase {
        }
 
        public function testMergeMetadata() {
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\SessionProvider' )
+               $provider = $this->getMockBuilder( SessionProvider::class )
                        ->getMockForAbstractClass();
 
                try {
@@ -112,14 +112,14 @@ class SessionProviderTest extends MediaWikiTestCase {
        }
 
        public function testImmutableSessions() {
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\SessionProvider' )
+               $provider = $this->getMockBuilder( SessionProvider::class )
                        ->setMethods( [ 'canChangeUser', 'persistsSessionId' ] )
                        ->getMockForAbstractClass();
                $provider->expects( $this->any() )->method( 'canChangeUser' )
                        ->will( $this->returnValue( true ) );
                $provider->preventSessionsForUser( 'Foo' );
 
-               $provider = $this->getMockBuilder( 'MediaWiki\\Session\\SessionProvider' )
+               $provider = $this->getMockBuilder( SessionProvider::class )
                        ->setMethods( [ 'canChangeUser', 'persistsSessionId' ] )
                        ->getMockForAbstractClass();
                $provider->expects( $this->any() )->method( 'canChangeUser' )
@@ -142,7 +142,7 @@ class SessionProviderTest extends MediaWikiTestCase {
                        'SecretKey' => 'Shhh!',
                ] );
 
-               $provider = $this->getMockForAbstractClass( 'MediaWiki\\Session\\SessionProvider',
+               $provider = $this->getMockForAbstractClass( SessionProvider::class,
                        [], 'MockSessionProvider' );
                $provider->setConfig( $config );
                $priv = \TestingAccessWrapper::newFromObject( $provider );
@@ -172,7 +172,7 @@ class SessionProviderTest extends MediaWikiTestCase {
        }
 
        public function testDescribe() {
-               $provider = $this->getMockForAbstractClass( 'MediaWiki\\Session\\SessionProvider',
+               $provider = $this->getMockForAbstractClass( SessionProvider::class,
                        [], 'MockSessionProvider' );
 
                $this->assertSame(
@@ -182,7 +182,7 @@ class SessionProviderTest extends MediaWikiTestCase {
        }
 
        public function testGetAllowedUserRights() {
-               $provider = $this->getMockForAbstractClass( 'MediaWiki\\Session\\SessionProvider' );
+               $provider = $this->getMockForAbstractClass( SessionProvider::class );
                $backend = TestUtils::getDummySessionBackend();
 
                try {
index a4727c4..e87f41d 100644 (file)
@@ -37,7 +37,7 @@ class SessionTest extends MediaWikiTestCase {
         * @param bool $ret Whether the method returns a value
         */
        public function testMethods( $m, $args, $index, $ret ) {
-               $mock = $this->getMock( 'MediaWiki\\Session\\DummySessionBackend',
+               $mock = $this->getMock( DummySessionBackend::class,
                        [ $m, 'deregisterSession' ] );
                $mock->expects( $this->once() )->method( 'deregisterSession' )
                        ->with( $this->identicalTo( 42 ) );
@@ -224,7 +224,7 @@ class SessionTest extends MediaWikiTestCase {
                $priv = \TestingAccessWrapper::newFromObject( $session );
 
                $backend = $this->getMock(
-                       'MediaWiki\\Session\\DummySessionBackend', [ 'canSetUser', 'setUser', 'save' ]
+                       DummySessionBackend::class, [ 'canSetUser', 'setUser', 'save' ]
                );
                $backend->expects( $this->once() )->method( 'canSetUser' )
                        ->will( $this->returnValue( true ) );
@@ -239,7 +239,7 @@ class SessionTest extends MediaWikiTestCase {
                $this->assertTrue( $backend->dirty );
 
                $backend = $this->getMock(
-                       'MediaWiki\\Session\\DummySessionBackend', [ 'canSetUser', 'setUser', 'save' ]
+                       DummySessionBackend::class, [ 'canSetUser', 'setUser', 'save' ]
                );
                $backend->data = [];
                $backend->expects( $this->once() )->method( 'canSetUser' )
@@ -254,7 +254,7 @@ class SessionTest extends MediaWikiTestCase {
                $this->assertFalse( $backend->dirty );
 
                $backend = $this->getMock(
-                       'MediaWiki\\Session\\DummySessionBackend', [ 'canSetUser', 'setUser', 'save' ]
+                       DummySessionBackend::class, [ 'canSetUser', 'setUser', 'save' ]
                );
                $backend->expects( $this->once() )->method( 'canSetUser' )
                        ->will( $this->returnValue( false ) );
@@ -267,7 +267,7 @@ class SessionTest extends MediaWikiTestCase {
        }
 
        public function testTokens() {
-               $rc = new \ReflectionClass( 'MediaWiki\\Session\\Session' );
+               $rc = new \ReflectionClass( Session::class );
                if ( !method_exists( $rc, 'newInstanceWithoutConstructor' ) ) {
                        $this->markTestSkipped(
                                'ReflectionClass::newInstanceWithoutConstructor isn\'t available'
index 36175af..f1dc9e9 100644 (file)
@@ -18,15 +18,15 @@ class TestUtils {
                session_write_close();
 
                $rInstance = new \ReflectionProperty(
-                       'MediaWiki\\Session\\SessionManager', 'instance'
+                       SessionManager::class, 'instance'
                );
                $rInstance->setAccessible( true );
                $rGlobalSession = new \ReflectionProperty(
-                       'MediaWiki\\Session\\SessionManager', 'globalSession'
+                       SessionManager::class, 'globalSession'
                );
                $rGlobalSession->setAccessible( true );
                $rGlobalSessionRequest = new \ReflectionProperty(
-                       'MediaWiki\\Session\\SessionManager', 'globalSessionRequest'
+                       SessionManager::class, 'globalSessionRequest'
                );
                $rGlobalSessionRequest->setAccessible( true );
 
@@ -62,7 +62,7 @@ class TestUtils {
         *  fields necessary.
         */
        public static function getDummySessionBackend() {
-               $rc = new \ReflectionClass( 'MediaWiki\\Session\\SessionBackend' );
+               $rc = new \ReflectionClass( SessionBackend::class );
                if ( !method_exists( $rc, 'newInstanceWithoutConstructor' ) ) {
                        \PHPUnit_Framework_Assert::markTestSkipped(
                                'ReflectionClass::newInstanceWithoutConstructor isn\'t available'
@@ -83,7 +83,7 @@ class TestUtils {
         * @return Session
         */
        public static function getDummySession( $backend = null, $index = -1, $logger = null ) {
-               $rc = new \ReflectionClass( 'MediaWiki\\Session\\Session' );
+               $rc = new \ReflectionClass( Session::class );
                if ( !method_exists( $rc, 'newInstanceWithoutConstructor' ) ) {
                        \PHPUnit_Framework_Assert::markTestSkipped(
                                'ReflectionClass::newInstanceWithoutConstructor isn\'t available'
index 47b70af..ca001f3 100644 (file)
@@ -11,7 +11,7 @@ use MediaWikiTestCase;
 class TokenTest extends MediaWikiTestCase {
 
        public function testBasics() {
-               $token = $this->getMockBuilder( 'MediaWiki\\Session\\Token' )
+               $token = $this->getMockBuilder( Token::class )
                        ->setMethods( [ 'toStringAtTimestamp' ] )
                        ->setConstructorArgs( [ 'sekret', 'salty', true ] )
                        ->getMock();
index 4f4275d..32dd7f2 100644 (file)
  */
 class DBSiteStoreTest extends MediaWikiTestCase {
 
+       /**
+        * @return DBSiteStore
+        */
+       private function newDBSiteStore() {
+               // NOTE: Use the real DB load balancer for now. Eventually, the test framework should
+               // provide a LoadBalancer that is safe to use in unit tests.
+               return new DBSiteStore( wfGetLB() );
+       }
+
        /**
         * @covers DBSiteStore::getSites
         */
@@ -38,7 +47,7 @@ class DBSiteStoreTest extends MediaWikiTestCase {
                $expectedSites = TestSites::getSites();
                TestSites::insertIntoDb();
 
-               $store = new DBSiteStore();
+               $store = $this->newDBSiteStore();
 
                $sites = $store->getSites();
 
@@ -62,7 +71,7 @@ class DBSiteStoreTest extends MediaWikiTestCase {
         * @covers DBSiteStore::saveSites
         */
        public function testSaveSites() {
-               $store = new DBSiteStore();
+               $store = $this->newDBSiteStore();
 
                $sites = [];
 
@@ -95,8 +104,8 @@ class DBSiteStoreTest extends MediaWikiTestCase {
         * @covers DBSiteStore::reset
         */
        public function testReset() {
-               $store1 = new DBSiteStore();
-               $store2 = new DBSiteStore();
+               $store1 = $this->newDBSiteStore();
+               $store2 = $this->newDBSiteStore();
 
                // initialize internal cache
                $this->assertGreaterThan( 0, $store1->getSites()->count() );
@@ -121,7 +130,7 @@ class DBSiteStoreTest extends MediaWikiTestCase {
         * @covers DBSiteStore::clear
         */
        public function testClear() {
-               $store = new DBSiteStore();
+               $store = $this->newDBSiteStore();
                $this->assertTrue( $store->clear() );
 
                $site = $store->getSite( 'enwiki' );
@@ -135,7 +144,7 @@ class DBSiteStoreTest extends MediaWikiTestCase {
         * @covers DBSiteStore::getSites
         */
        public function testGetSitesDefaultOrder() {
-               $store = new DBSiteStore();
+               $store = $this->newDBSiteStore();
                $siteB = new Site();
                $siteB->setGlobalId( 'B' );
                $siteA = new Site();
diff --git a/tests/phpunit/includes/site/SiteSQLStoreTest.php b/tests/phpunit/includes/site/SiteSQLStoreTest.php
deleted file mode 100644 (file)
index 6908800..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @since 1.25
- *
- * @ingroup Site
- * @ingroup Test
- *
- * @group Site
- * @group Database
- *
- * @author Katie Filbert < aude.wiki@gmail.com >
- */
-class SiteSQLStoreTest extends MediaWikiTestCase {
-
-       /**
-        * @covers SiteSQLStore::newInstance
-        */
-       public function testNewInstance() {
-               $siteStore = SiteSQLStore::newInstance();
-               $this->assertInstanceOf( 'SiteSQLStore', $siteStore );
-       }
-
-}
index d7865d4..6597906 100644 (file)
@@ -107,7 +107,7 @@ class TestSites {
         * @since 0.1
         */
        public static function insertIntoDb() {
-               $sitesTable = new DBSiteStore();
+               $sitesTable = \MediaWiki\MediaWikiServices::getInstance()->getSiteStore();
                $sitesTable->clear();
                $sitesTable->saveSites( TestSites::getSites() );
        }
index 534cf9b..3d407fb 100644 (file)
@@ -55,19 +55,17 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
                $specialPageTestHelper = new SpecialPageTestHelper();
 
                return [
-                       'class name' => [ 'SpecialAllPages', false ],
+                       'class name' => [ 'SpecialAllPages' ],
                        'closure' => [ function () {
                                return new SpecialAllPages();
-                       }, false ],
-                       'function' => [ [ $this, 'newSpecialAllPages' ], false ],
-                       'callback string' => [ 'SpecialPageTestHelper::newSpecialAllPages', false ],
+                       } ],
+                       'function' => [ [ $this, 'newSpecialAllPages' ] ],
+                       'callback string' => [ 'SpecialPageTestHelper::newSpecialAllPages' ],
                        'callback with object' => [
-                               [ $specialPageTestHelper, 'newSpecialAllPages' ],
-                               false
+                               [ $specialPageTestHelper, 'newSpecialAllPages' ]
                        ],
                        'callback array' => [
-                               [ 'SpecialPageTestHelper', 'newSpecialAllPages' ],
-                               false
+                               [ 'SpecialPageTestHelper', 'newSpecialAllPages' ]
                        ]
                ];
        }
@@ -76,7 +74,7 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
         * @covers SpecialPageFactory::getPage
         * @dataProvider specialPageProvider
         */
-       public function testGetPage( $spec, $shouldReuseInstance ) {
+       public function testGetPage( $spec ) {
                $this->mergeMwGlobalArrayValue( 'wgSpecialPages', [ 'testdummy' => $spec ] );
                SpecialPageFactory::resetList();
 
@@ -84,7 +82,7 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
                $this->assertInstanceOf( 'SpecialPage', $page );
 
                $page2 = SpecialPageFactory::getPage( 'testdummy' );
-               $this->assertEquals( $shouldReuseInstance, $page2 === $page, "Should re-use instance:" );
+               $this->assertEquals( true, $page2 === $page, "Should re-use instance:" );
        }
 
        /**
diff --git a/tests/phpunit/includes/specials/SpecialEditWatchlistTest.php b/tests/phpunit/includes/specials/SpecialEditWatchlistTest.php
new file mode 100644 (file)
index 0000000..cd84d79
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @author Addshore
+ *
+ * @group Database
+ *
+ * @covers SpecialEditWatchlist
+ */
+class SpecialEditWatchlistTest extends SpecialPageTestBase {
+
+       /**
+        * Returns a new instance of the special page under test.
+        *
+        * @return SpecialPage
+        */
+       protected function newSpecialPage() {
+               return new SpecialEditWatchlist();
+       }
+
+       public function testNotLoggedIn_throwsException() {
+               $this->setExpectedException( 'UserNotLoggedIn' );
+               $this->executeSpecialPage();
+       }
+
+       public function testRootPage_displaysExplanationMessage() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( '', null, 'qqx', $user->getUser() );
+               $this->assertContains( '(watchlistedit-normal-explain)', $html );
+       }
+
+       public function testClearPage_hasClearButtonForm() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( 'clear', null, 'qqx', $user->getUser() );
+               $this->assertRegExp(
+                       '/<form action=".*?Special:EditWatchlist\/clear" method="post" class="visualClear">/',
+                       $html
+               );
+       }
+
+       public function testEditRawPage_hasTitlesBox() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( 'raw', null, 'qqx', $user->getUser() );
+               $this->assertContains(
+                       '<textarea id="mw-input-wpTitles"',
+                       $html
+               );
+       }
+
+}
index 548b75b..89fd1b0 100644 (file)
@@ -5,7 +5,7 @@
  * @covers SpecialMyLanguage
  */
 class SpecialMyLanguageTest extends MediaWikiTestCase {
-       public function addDBData() {
+       public function addDBDataOnce() {
                $titles = [
                        'Page/Another',
                        'Page/Another/ru',
diff --git a/tests/phpunit/includes/specials/SpecialPageExecutor.php b/tests/phpunit/includes/specials/SpecialPageExecutor.php
new file mode 100644 (file)
index 0000000..2f7b767
--- /dev/null
@@ -0,0 +1,129 @@
+<?php
+
+/**
+ * @author Addshore
+ *
+ * @since 1.27
+ */
+class SpecialPageExecutor {
+
+       /**
+        * @param SpecialPage $page The special page to execute
+        * @param string $subPage The subpage parameter to call the page with
+        * @param WebRequest|null $request Web request that may contain URL parameters, etc
+        * @param Language|string|null $language The language which should be used in the context
+        * @param User|null $user The user which should be used in the context of this special page
+        *
+        * @throws Exception
+        * @return array( string, WebResponse ) A two-elements array containing the HTML output
+        * generated by the special page as well as the response object.
+        */
+       public function executeSpecialPage(
+               SpecialPage $page,
+               $subPage = '',
+               WebRequest $request = null,
+               $language = null,
+               User $user = null
+       ) {
+               $context = $this->newContext( $request, $language, $user );
+
+               $output = new OutputPage( $context );
+               $context->setOutput( $output );
+
+               $page->setContext( $context );
+               $output->setTitle( $page->getPageTitle() );
+
+               $html = $this->getHTMLFromSpecialPage( $page, $subPage );
+               $response = $context->getRequest()->response();
+
+               if ( $response instanceof FauxResponse ) {
+                       $code = $response->getStatusCode();
+
+                       if ( $code > 0 ) {
+                               $response->header( 'Status: ' . $code . ' ' . HttpStatus::getMessage( $code ) );
+                       }
+               }
+
+               return [ $html, $response ];
+       }
+
+       /**
+        * @param WebRequest|null $request
+        * @param Language|string|null $language
+        * @param User|null $user
+        *
+        * @return DerivativeContext
+        */
+       private function newContext(
+               WebRequest $request = null,
+               $language = null,
+               User $user = null
+       ) {
+               $context = new DerivativeContext( RequestContext::getMain() );
+
+               $context->setRequest( $request ?: new FauxRequest() );
+
+               if ( $language !== null ) {
+                       $context->setLanguage( $language );
+               }
+
+               if ( $user !== null ) {
+                       $context->setUser( $user );
+               }
+
+               $this->setEditTokenFromUser( $context );
+
+               return $context;
+       }
+
+       /**
+        * If we are trying to edit and no token is set, supply one.
+        *
+        * @param DerivativeContext $context
+        */
+       private function setEditTokenFromUser( DerivativeContext $context ) {
+               $request = $context->getRequest();
+
+               // Edits via GET are a security issue and should not succeed. On the other hand, not all
+               // POST requests are edits, but should ignore unused parameters.
+               if ( !$request->getCheck( 'wpEditToken' ) && $request->wasPosted() ) {
+                       $request->setVal( 'wpEditToken', $context->getUser()->getEditToken() );
+               }
+       }
+
+       /**
+        * @param SpecialPage $page
+        * @param string $subPage
+        *
+        * @throws Exception
+        * @return string HTML
+        */
+       private function getHTMLFromSpecialPage( SpecialPage $page, $subPage ) {
+               ob_start();
+
+               try {
+                       $page->execute( $subPage );
+
+                       $output = $page->getOutput();
+
+                       if ( $output->getRedirect() !== '' ) {
+                               $output->output();
+                               $html = ob_get_contents();
+                       } elseif ( $output->isDisabled() ) {
+                               $html = ob_get_contents();
+                       } else {
+                               $html = $output->getHTML();
+                       }
+               } catch ( Exception $ex ) {
+                       ob_end_clean();
+
+                       // Re-throw exception after "finally" handling because PHP 5.3 doesn't have "finally".
+                       throw $ex;
+               }
+
+               ob_end_clean();
+
+               return $html;
+       }
+
+}
index 48baa8e..2f091d5 100644 (file)
@@ -60,106 +60,13 @@ abstract class SpecialPageTestBase extends MediaWikiTestCase {
                $language = null,
                User $user = null
        ) {
-               $context = $this->newContext( $request, $language, $user );
-
-               $output = new OutputPage( $context );
-               $context->setOutput( $output );
-
-               $page = $this->newSpecialPage();
-               $page->setContext( $context );
-               $output->setTitle( $page->getPageTitle() );
-
-               $html = $this->getHTMLFromSpecialPage( $page, $subPage );
-               $response = $context->getRequest()->response();
-
-               if ( $response instanceof FauxResponse ) {
-                       $code = $response->getStatusCode();
-
-                       if ( $code > 0 ) {
-                               $response->header( 'Status: ' . $code . ' ' . HttpStatus::getMessage( $code ) );
-                       }
-               }
-
-               return [ $html, $response ];
-       }
-
-       /**
-        * @param WebRequest|null $request
-        * @param Language|string|null $language
-        * @param User|null $user
-        *
-        * @return DerivativeContext
-        */
-       private function newContext(
-               WebRequest $request = null,
-               $language = null,
-               User $user = null
-       ) {
-               $context = new DerivativeContext( RequestContext::getMain() );
-
-               $context->setRequest( $request ?: new FauxRequest() );
-
-               if ( $language !== null ) {
-                       $context->setLanguage( $language );
-               }
-
-               if ( $user !== null ) {
-                       $context->setUser( $user );
-               }
-
-               $this->setEditTokenFromUser( $context );
-
-               return $context;
-       }
-
-       /**
-        * If we are trying to edit and no token is set, supply one.
-        *
-        * @param DerivativeContext $context
-        */
-       private function setEditTokenFromUser( DerivativeContext $context ) {
-               $request = $context->getRequest();
-
-               // Edits via GET are a security issue and should not succeed. On the other hand, not all
-               // POST requests are edits, but should ignore unused parameters.
-               if ( !$request->getCheck( 'wpEditToken' ) && $request->wasPosted() ) {
-                       $request->setVal( 'wpEditToken', $context->getUser()->getEditToken() );
-               }
-       }
-
-       /**
-        * @param SpecialPage $page
-        * @param string $subPage
-        *
-        * @throws Exception
-        * @return string HTML
-        */
-       private function getHTMLFromSpecialPage( SpecialPage $page, $subPage ) {
-               ob_start();
-
-               try {
-                       $page->execute( $subPage );
-
-                       $output = $page->getOutput();
-
-                       if ( $output->getRedirect() !== '' ) {
-                               $output->output();
-                               $html = ob_get_contents();
-                       } elseif ( $output->isDisabled() ) {
-                               $html = ob_get_contents();
-                       } else {
-                               $html = $output->getHTML();
-                       }
-               } catch ( Exception $ex ) {
-                       ob_end_clean();
-
-                       // Re-throw exception after "finally" handling because PHP 5.3 doesn't have "finally".
-                       throw $ex;
-               }
-
-               ob_end_clean();
-
-               return $html;
+               return ( new SpecialPageExecutor() )->executeSpecialPage(
+                       $this->newSpecialPage(),
+                       $subPage,
+                       $request,
+                       $language,
+                       $user
+               );
        }
 
 }
diff --git a/tests/phpunit/includes/specials/SpecialWatchlistTest.php b/tests/phpunit/includes/specials/SpecialWatchlistTest.php
new file mode 100644 (file)
index 0000000..6e702b6
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @author Addshore
+ *
+ * @group Database
+ *
+ * @covers SpecialWatchlist
+ */
+class SpecialWatchlistTest extends SpecialPageTestBase {
+
+       /**
+        * Returns a new instance of the special page under test.
+        *
+        * @return SpecialPage
+        */
+       protected function newSpecialPage() {
+               return new SpecialWatchlist();
+       }
+
+       public function testNotLoggedIn_throwsException() {
+               $this->setExpectedException( 'UserNotLoggedIn' );
+               $this->executeSpecialPage();
+       }
+
+       public function testUserWithNoWatchedItems_displaysNoWatchlistMessage() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( '', null, 'qqx', $user->getUser() );
+               $this->assertContains( '(nowatchlist)', $html );
+       }
+
+}
index a274b84..ee74957 100644 (file)
@@ -136,259 +136,259 @@ class UploadBaseTest extends MediaWikiTestCase {
 
        public static function provideCheckSvgScriptCallback() {
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
+               return [
                        // html5sec SVG vectors
-                       array(
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>',
                                true,
                                true,
                                'Script tag in svg (http://html5sec.org/#47)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"><g onload="javascript:alert(1)"></g></svg>',
                                true,
                                true,
                                'SVG with onload property (http://html5sec.org/#11)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg onload="javascript:alert(1)" xmlns="http://www.w3.org/2000/svg"></svg>',
                                true,
                                true,
                                'SVG with onload property (http://html5sec.org/#65)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="javascript:alert(1)"><rect width="1000" height="1000" fill="white"/></a> </svg>',
                                true,
                                true,
                                'SVG with javascript xlink (http://html5sec.org/#87)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><use xlink:href="data:application/xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KPGRlZnM+CjxjaXJjbGUgaWQ9InRlc3QiIHI9IjUwIiBjeD0iMTAwIiBjeT0iMTAwIiBzdHlsZT0iZmlsbDogI0YwMCI+CjxzZXQgYXR0cmlidXRlTmFtZT0iZmlsbCIgYXR0cmlidXRlVHlwZT0iQ1NTIiBvbmJlZ2luPSdhbGVydChkb2N1bWVudC5jb29raWUpJwpvbmVuZD0nYWxlcnQoIm9uZW5kIiknIHRvPSIjMDBGIiBiZWdpbj0iMXMiIGR1cj0iNXMiIC8+CjwvY2lyY2xlPgo8L2RlZnM+Cjx1c2UgeGxpbms6aHJlZj0iI3Rlc3QiLz4KPC9zdmc+#test"/> </svg>',
                                true,
                                true,
                                'SVG with Opera image xlink (http://html5sec.org/#88 - c)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  <animation xlink:href="javascript:alert(1)"/> </svg>',
                                true,
                                true,
                                'SVG with Opera animation xlink (http://html5sec.org/#88 - a)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  <animation xlink:href="data:text/xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' onload=\'alert(1)\'%3E%3C/svg%3E"/> </svg>',
                                true,
                                true,
                                'SVG with Opera animation xlink (http://html5sec.org/#88 - b)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  <image xlink:href="data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' onload=\'alert(1)\'%3E%3C/svg%3E"/> </svg>',
                                true,
                                true,
                                'SVG with Opera image xlink (http://html5sec.org/#88 - c)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  <foreignObject xlink:href="javascript:alert(1)"/> </svg>',
                                true,
                                true,
                                'SVG with Opera foreignObject xlink (http://html5sec.org/#88 - d)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  <foreignObject xlink:href="data:text/xml,%3Cscript xmlns=\'http://www.w3.org/1999/xhtml\'%3Ealert(1)%3C/script%3E"/> </svg>',
                                true,
                                true,
                                'SVG with Opera foreignObject xlink (http://html5sec.org/#88 - e)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <set attributeName="onmouseover" to="alert(1)"/> </svg>',
                                true,
                                true,
                                'SVG with event handler set (http://html5sec.org/#89 - a)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <animate attributeName="onunload" to="alert(1)"/> </svg>',
                                true,
                                true,
                                'SVG with event handler animate (http://html5sec.org/#89 - a)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <handler xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load">alert(1)</handler> </svg>',
                                true,
                                true,
                                'SVG with element handler (http://html5sec.org/#94)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <feImage> <set attributeName="xlink:href" to="data:image/svg+xml;charset=utf-8;base64, PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxzY3JpcHQ%2BYWxlcnQoMSk8L3NjcmlwdD48L3N2Zz4NCg%3D%3D"/> </feImage> </svg>',
                                true,
                                true,
                                'SVG with href to data: url (http://html5sec.org/#95)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" id="foo"> <x xmlns="http://www.w3.org/2001/xml-events" event="load" observer="foo" handler="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Chandler%20xml%3Aid%3D%22bar%22%20type%3D%22application%2Fecmascript%22%3E alert(1) %3C%2Fhandler%3E%0A%3C%2Fsvg%3E%0A#bar"/> </svg>',
                                true,
                                true,
                                'SVG with Tiny handler (http://html5sec.org/#104)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <a id="x"><rect fill="white" width="1000" height="1000"/></a> <rect fill="white" style="clip-path:url(test3.svg#a);fill:url(#b);filter:url(#c);marker:url(#d);mask:url(#e);stroke:url(#f);"/> </svg>',
                                true,
                                true,
                                'SVG with new CSS styles properties (http://html5sec.org/#109)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <a id="x"><rect fill="white" width="1000" height="1000"/></a> <rect clip-path="url(test3.svg#a)" /> </svg>',
                                true,
                                true,
                                'SVG with new CSS styles properties as attributes'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <a id="x"> <rect fill="white" width="1000" height="1000"/> </a> <rect fill="url(http://html5sec.org/test3.svg#a)" /> </svg>',
                                true,
                                true,
                                'SVG with new CSS styles properties as attributes (2)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <path d="M0,0" style="marker-start:url(test4.svg#a)"/> </svg>',
                                true,
                                true,
                                'SVG with path marker-start (http://html5sec.org/#110)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<?xml version="1.0"?> <?xml-stylesheet type="text/xml" href="#stylesheet"?> <!DOCTYPE doc [ <!ATTLIST xsl:stylesheet id ID #REQUIRED>]> <svg xmlns="http://www.w3.org/2000/svg"> <xsl:stylesheet id="stylesheet" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert(1)"></iframe> </xsl:template> </xsl:stylesheet> <circle fill="red" r="40"></circle> </svg>',
                                true,
                                true,
                                'SVG with embedded stylesheet (http://html5sec.org/#125)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" id="x"> <listener event="load" handler="#y" xmlns="http://www.w3.org/2001/xml-events" observer="x"/> <handler id="y">alert(1)</handler> </svg>',
                                true,
                                true,
                                'SVG with handler attribute (http://html5sec.org/#127)'
-                       ),
-                       array(
+                       ],
+                       [
                                // Haven't found a browser that accepts this particular example, but we
                                // don't want to allow embeded svgs, ever
                                '<svg> <image style=\'filter:url("data:image/svg+xml;charset=utf-8;base64, PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxzY3JpcHQ/YWxlcnQoMSk8L3NjcmlwdD48L3N2Zz4NCg==")\' /> </svg>',
                                true,
                                true,
                                'SVG with image filter via style (http://html5sec.org/#129)'
-                       ),
-                       array(
+                       ],
+                       [
                                // This doesn't seem possible without embedding the svg, but just in case
                                '<svg> <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="?"> <circle r="400"></circle> <animate attributeName="xlink:href" begin="0" from="javascript:alert(1)" to="" /> </a></svg>',
                                true,
                                true,
                                'SVG with animate from (http://html5sec.org/#137)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <a><text y="1em">Click me</text> <animate attributeName="xlink:href" values="javascript:alert(\'Bang!\')" begin="0s" dur="0.1s" fill="freeze" /> </a></svg>',
                                true,
                                true,
                                'SVG with animate xlink:href (http://html5sec.org/#137)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:y="http://www.w3.org/1999/xlink"> <a y:href="#"> <text y="1em">Click me</text> <animate attributeName="y:href" values="javascript:alert(\'Bang!\')" begin="0s" dur="0.1s" fill="freeze" /> </a> </svg>',
                                true,
                                true,
                                'SVG with animate y:href (http://html5sec.org/#137)'
-                       ),
+                       ],
 
                        // Other hostile SVG's
-                       array(
+                       [
                                '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink"> <image xlink:href="https://upload.wikimedia.org/wikipedia/commons/3/34/Bahnstrecke_Zeitz-Camburg_1930.png" /> </svg>',
                                true,
                                true,
                                'SVG with non-local image href (bug 65839)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<?xml version="1.0" ?> <?xml-stylesheet type="text/xsl" href="/w/index.php?title=User:Jeeves/test.xsl&amp;action=raw&amp;format=xml" ?> <svg> <height>50</height> <width>100</width> </svg>',
                                true,
                                true,
                                'SVG with remote stylesheet (bug 57550)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewbox="-1 -1 15 15"> <rect y="0" height="13" width="12" stroke="#179" rx="1" fill="#2ac"/> <text x="1.5" y="11" font-family="courier" stroke="white" font-size="16"><![CDATA[B]]></text> <iframe xmlns="http://www.w3.org/1999/xhtml" srcdoc="&#x3C;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x45;&#x44;&#x20;&#x3D;&#x3E;&#x20;&#x44;&#x6F;&#x6D;&#x61;&#x69;&#x6E;&#x28;&#x27;&#x2B;&#x74;&#x6F;&#x70;&#x2E;&#x64;&#x6F;&#x63;&#x75;&#x6D;&#x65;&#x6E;&#x74;&#x2E;&#x64;&#x6F;&#x6D;&#x61;&#x69;&#x6E;&#x2B;&#x27;&#x29;&#x27;&#x29;&#x3B;&#x3C;&#x2F;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;"></iframe> </svg>',
                                true,
                                true,
                                'SVG with rembeded iframe (bug 60771)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewBox="6 3 177 153" xmlns:xlink="http://www.w3.org/1999/xlink"> <style>@import url("https://fonts.googleapis.com/css?family=Bitter:700&amp;text=WebPlatform.org");</style> <g transform="translate(-.5,-.5)"> <text fill="#474747" x="95" y="150" text-anchor="middle" font-family="Bitter" font-size="20" font-weight="bold">WebPlatform.org</text> </g> </svg>',
                                true,
                                true,
                                'SVG with @import in style element (bug 69008)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewBox="6 3 177 153" xmlns:xlink="http://www.w3.org/1999/xlink"> <style>@import url("https://fonts.googleapis.com/css?family=Bitter:700&amp;text=WebPlatform.org");<foo/></style> <g transform="translate(-.5,-.5)"> <text fill="#474747" x="95" y="150" text-anchor="middle" font-family="Bitter" font-size="20" font-weight="bold">WebPlatform.org</text> </g> </svg>',
                                true,
                                true,
                                'SVG with @import in style element and child element (bug 69008#c11)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewBox="6 3 177 153" xmlns:xlink="http://www.w3.org/1999/xlink"> <style>@imporT "https://fonts.googleapis.com/css?family=Bitter:700&amp;text=WebPlatform.org";</style> <g transform="translate(-.5,-.5)"> <text fill="#474747" x="95" y="150" text-anchor="middle" font-family="Bitter" font-size="20" font-weight="bold">WebPlatform.org</text> </g> </svg>',
                                true,
                                true,
                                'SVG with case-insensitive @import in style element (bug T85349)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <rect width="100" height="100" style="background-image:url(https://www.google.com/images/srpr/logo11w.png)"/> </svg>',
                                true,
                                true,
                                'SVG with remote background image (bug 69008)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <rect width="100" height="100" style="background-image:\55rl(https://www.google.com/images/srpr/logo11w.png)"/> </svg>',
                                true,
                                true,
                                'SVG with remote background image, encoded (bug 69008)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <style> #a { background-image:\55rl(\'https://www.google.com/images/srpr/logo11w.png\'); } </style> <rect width="100" height="100" id="a"/> </svg>',
                                true,
                                true,
                                'SVG with remote background image, in style element (bug 69008)'
-                       ),
-                       array(
+                       ],
+                       [
                                // This currently doesn't seem to work in any browsers, but in case
                                // http://www.w3.org/TR/css3-images/ is implemented for SVG files
                                '<svg xmlns="http://www.w3.org/2000/svg"> <rect width="100" height="100" style="background-image:image(\'sprites.svg#xywh=40,0,20,20\')"/> </svg>',
                                true,
                                true,
                                'SVG with remote background image using image() (bug 69008)'
-                       ),
-                       array(
+                       ],
+                       [
                                // As reported by Cure53
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <a xlink:href="data:text/html;charset=utf-8;base64, PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ%2BDQo%3D"> <circle r="400" fill="red"></circle> </a> </svg>',
                                true,
                                true,
                                'SVG with data:text/html link target (firefox only)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ <!ENTITY lol "lol"> <!ENTITY lol2 "&#x3C;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x45;&#x44;&#x20;&#x3D;&#x3E;&#x20;&#x27;&#x2B;&#x64;&#x6F;&#x63;&#x75;&#x6D;&#x65;&#x6E;&#x74;&#x2E;&#x64;&#x6F;&#x6D;&#x61;&#x69;&#x6E;&#x29;&#x3B;&#x3C;&#x2F;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;"> ]> <svg xmlns="http://www.w3.org/2000/svg" width="68" height="68" viewBox="-34 -34 68 68" version="1.1"> <circle cx="0" cy="0" r="24" fill="#c8c8c8"/> <text x="0" y="0" fill="black">&lol2;</text> </svg>',
                                true,
                                true,
                                'SVG with encoded script tag in internal entity (reported by Beyond Security)'
-                       ),
-                       array(
+                       ],
+                       [
                                '<?xml version="1.0"?> <!DOCTYPE svg [ <!ENTITY foo SYSTEM "file:///etc/passwd"> ]> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <desc>&foo;</desc> <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,2)" /> </svg>',
                                false,
                                false,
                                'SVG with external entity'
-                       ),
+                       ],
 
                        // Test good, but strange files that we want to allow
-                       array(
+                       [
                                '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g> <a xlink:href="http://en.wikipedia.org/wiki/Main_Page"> <path transform="translate(0,496)" id="path6706" d="m 112.09375,107.6875 -5.0625,3.625 -4.3125,5.03125 -0.46875,0.5 -4.09375,3.34375 -9.125,5.28125 -8.625,-3.375 z" style="fill:#cccccc;fill-opacity:1;stroke:#6e6e6e;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:inline" /> </a> </g> </svg>',
                                true,
                                false,
                                'SVG with <a> link to a remote site'
-                       ),
-                       array(
+                       ],
+                       [
                                '<svg> <defs> <filter id="filter6226" x="-0.93243687" width="2.8648737" y="-0.24250539" height="1.4850108"> <feGaussianBlur stdDeviation="3.2344681" id="feGaussianBlur6228" /> </filter> <clipPath id="clipPath2436"> <path d="M 0,0 L 0,0 L 0,0 L 0,0 z" id="path2438" /> </clipPath> </defs> <g clip-path="url(#clipPath2436)" id="g2460"> <text id="text2466"> <tspan>12345</tspan> </text> </g> <path style="fill:#346733;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;filter:url(\'#filter6226\');fill-opacity:1;opacity:0.79807692" d="M 236.82371,332.63732 C 236.92217,332.63732 z" id="path5618" /> </svg>',
                                true,
                                false,
                                'SVG with local urls, including filter: in style'
-                       ),
-               );
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 }
index d3a5791..27ce287 100644 (file)
@@ -234,7 +234,7 @@ class BotPasswordTest extends MediaWikiTestCase {
                ] );
                $reset = MediaWiki\Session\TestUtils::setSessionManagerSingleton( $manager );
                $this->assertNull(
-                       $manager->getProvider( 'MediaWiki\\Session\\BotPasswordSessionProvider' ),
+                       $manager->getProvider( MediaWiki\Session\BotPasswordSessionProvider::class ),
                        'sanity check'
                );
                $status = BotPassword::login( 'UTSysop@BotPassword', 'foobaz', new FauxRequest );
@@ -245,8 +245,8 @@ class BotPasswordTest extends MediaWikiTestCase {
                $mainConfig = RequestContext::getMain()->getConfig();
                $config = new HashConfig( [
                        'SessionProviders' => $mainConfig->get( 'SessionProviders' ) + [
-                               'MediaWiki\\Session\\BotPasswordSessionProvider' => [
-                                       'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider',
+                               MediaWiki\Session\BotPasswordSessionProvider::class => [
+                                       'class' => MediaWiki\Session\BotPasswordSessionProvider::class,
                                        'args' => [ [ 'priority' => 40 ] ],
                                ]
                        ],
@@ -287,7 +287,7 @@ class BotPasswordTest extends MediaWikiTestCase {
                // Success!
                $request = new FauxRequest;
                $this->assertNotInstanceOf(
-                       'MediaWiki\\Session\\BotPasswordSessionProvider',
+                       MediaWiki\Session\BotPasswordSessionProvider::class,
                        $request->getSession()->getProvider(),
                        'sanity check'
                );
@@ -295,9 +295,9 @@ class BotPasswordTest extends MediaWikiTestCase {
                $this->assertInstanceOf( 'Status', $status );
                $this->assertTrue( $status->isGood() );
                $session = $status->getValue();
-               $this->assertInstanceOf( 'MediaWiki\\Session\\Session', $session );
+               $this->assertInstanceOf( MediaWiki\Session\Session::class, $session );
                $this->assertInstanceOf(
-                       'MediaWiki\\Session\\BotPasswordSessionProvider', $session->getProvider()
+                       MediaWiki\Session\BotPasswordSessionProvider::class, $session->getProvider()
                );
                $this->assertSame( $session->getId(), $request->getSession()->getId() );
 
index e2b138b..c86fb6c 100644 (file)
@@ -104,11 +104,11 @@ class LocalIdLookupTest extends MediaWikiTestCase {
                $this->assertTrue( $lookup->isAttached( $user1 ) );
                $this->assertFalse( $lookup->isAttached( $user2 ) );
 
-               $wiki = wfWikiId();
+               $wiki = wfWikiID();
                $this->assertTrue( $lookup->isAttached( $user1, $wiki ) );
                $this->assertFalse( $lookup->isAttached( $user2, $wiki ) );
 
-               $wiki = 'not-' . wfWikiId();
+               $wiki = 'not-' . wfWikiID();
                $this->assertFalse( $lookup->isAttached( $user1, $wiki ) );
                $this->assertFalse( $lookup->isAttached( $user2, $wiki ) );
        }
index 17442b8..fafd4fa 100644 (file)
@@ -42,53 +42,58 @@ class MWCryptHKDFTest extends MediaWikiTestCase {
        public static function providerRfc5869() {
 
                // @codingStandardsIgnoreStart Generic.Files.LineLength
-               return array(
+               return [
                        // A.1
-                       array( 'sha256',
+                       [
+                               'sha256',
                                '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', // ikm
                                '000102030405060708090a0b0c', // salt
                                'f0f1f2f3f4f5f6f7f8f9', // context
                                42, // bytes
                                '077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5', // prk
                                '3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865' // okm
-                       ),
+                       ],
                        // A.2
-                       array( 'sha256',
+                       [
+                               'sha256',
                                '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f',
                                '606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf',
                                'b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff',
                                82,
                                '06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244',
                                'b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87'
-                       ),
+                       ],
                        // A.3
-                       array( 'sha256',
+                       [
+                               'sha256',
                                '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', // ikm
                                '', // salt
                                '', // context
                                42, // bytes
                                '19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04', // prk
                                '8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8' // okm
-                       ),
+                       ],
                        // A.4
-                       array( 'sha1',
+                       [
+                               'sha1',
                                '0b0b0b0b0b0b0b0b0b0b0b', // ikm
                                '000102030405060708090a0b0c', // salt
                                'f0f1f2f3f4f5f6f7f8f9', // context
                                42, // bytes
                                '9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243', // prk
                                '085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896' // okm
-                       ),
+                       ],
                        // A.5
-                       array( 'sha1',
+                       [
+                               'sha1',
                                '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f', // ikm
                                '606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf', // salt
                                'b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff', // context
                                82, // bytes
                                '8adae09a2a307059478d309b26c4115a224cfaf6', // prk
                                '0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4' // okm
-                       ),
-               );
+                       ],
+               ];
                // @codingStandardsIgnoreEnd
        }
 }
index 6d7325d..d746ea1 100644 (file)
@@ -9,6 +9,9 @@ class UIDGeneratorTest extends PHPUnit_Framework_TestCase {
        }
 
        /**
+        * Flaky test (T131549).
+        *
+        * @group Broken
         * @dataProvider provider_testTimestampedUID
         * @covers UIDGenerator::newTimestampedUID128
         * @covers UIDGenerator::newTimestampedUID88
index 20f4c4f..0cf2d0f 100644 (file)
@@ -281,7 +281,7 @@ class LanguageTest extends LanguageClassesTestCase {
                // Actual HTML...
                $this->assertEquals(
                        $expected,
-                       $this->getLang()->truncateHTML( $input, $len, $ellipsis )
+                       $this->getLang()->truncateHtml( $input, $len, $ellipsis )
                );
        }
 
@@ -1310,19 +1310,19 @@ class LanguageTest extends LanguageClassesTestCase {
 
        public static function provideCheckTitleEncodingData() {
                // @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
-               return array(
-                       array( "" ),
-                       array( "United States of America" ), // 7bit ASCII
-                       array( rawurldecode( "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e" ) ),
-                       array(
+               return [
+                       [ "" ],
+                       [ "United States of America" ], // 7bit ASCII
+                       [ rawurldecode( "S%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e" ) ],
+                       [
                                rawurldecode(
                                        "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn"
                                )
-                       ),
+                       ],
                        // The following two data sets come from bug 36839. They fail if checkTitleEncoding uses a regexp to test for
                        // valid UTF-8 encoding and the pcre.recursion_limit is low (like, say, 1024). They succeed if checkTitleEncoding
                        // uses mb_check_encoding for its test.
-                       array(
+                       [
                                rawurldecode(
                                        "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn%7C"
                                                . "Catherine%20Willows%7CDavid%20Hodges%7CDavid%20Phillips%7CGil%20Grissom%7CGreg%20Sanders%7CHodges%7C"
@@ -1339,8 +1339,8 @@ class LanguageTest extends LanguageClassesTestCase {
                                                . "Sara%20Sidle%7CSofia%20Curtis%7CS%C3%A9rie%20t%C3%A9l%C3%A9vis%C3%A9e%7CWallace%20Langham%7C"
                                                . "Warrick%20Brown%7CWendy%20Simms%7C%C3%89tats-Unis"
                                ),
-                       ),
-                       array(
+                       ],
+                       [
                                rawurldecode(
                                        "Mod%C3%A8le%3AArrondissements%20homonymes%7CMod%C3%A8le%3ABandeau%20standard%20pour%20page%20d'homonymie%7C"
                                                . "Mod%C3%A8le%3ABatailles%20homonymes%7CMod%C3%A8le%3ACantons%20homonymes%7C"
@@ -1358,8 +1358,8 @@ class LanguageTest extends LanguageClassesTestCase {
                                                . "Mod%C3%A8le%3ATitres%20homonymes%7CMod%C3%A8le%3AToponymie%7CMod%C3%A8le%3AUnit%C3%A9s%20homonymes%7C"
                                                . "Mod%C3%A8le%3AVilles%20homonymes%7CMod%C3%A8le%3A%C3%89difices%20religieux%20homonymes"
                                )
-                       )
-               );
+                       ]
+               ];
                // @codingStandardsIgnoreEnd
        }
 
index e015216..d7e72bb 100644 (file)
@@ -114,7 +114,7 @@ class TextPassDumperDatabaseTest extends DumpTestCase {
                $dumper = new TextPassDumper( [ "--stub=file:" . $nameStub,
                        "--output=file:" . $nameFull ] );
                $dumper->reporting = false;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // Performing the dump
                $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT );
@@ -183,7 +183,7 @@ class TextPassDumperDatabaseTest extends DumpTestCase {
 
                $dumper->prefetch = $prefetchMock;
                $dumper->reporting = false;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // Performing the dump
                $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT );
@@ -274,7 +274,7 @@ class TextPassDumperDatabaseTest extends DumpTestCase {
                                "--maxtime=1" /*This is in minutes. Fixup is below*/,
                                "--buffersize=32768", // The default of 32 iterations fill up 32KB about twice
                                "--checkpointfile=checkpoint-%s-%s.xml.gz" ] );
-                       $dumper->setDb( $this->db );
+                       $dumper->setDB( $this->db );
                        $dumper->maxTimeAllowed = $checkpointAfter; // Patching maxTime from 1 minute
                        $dumper->stderr = $stderr;
 
index 0b2f7fb..0019a3f 100644 (file)
@@ -146,7 +146,7 @@ class BackupDumperLoggerTest extends DumpTestCase {
                $dumper->startId = $this->logId1;
                $dumper->endId = $this->logId3 + 1;
                $dumper->reporting = false;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // Performing the dump
                $dumper->dump( WikiExporter::LOGS, WikiExporter::TEXT );
@@ -185,7 +185,7 @@ class BackupDumperLoggerTest extends DumpTestCase {
                        '--reporting=2' ] );
                $dumper->startId = $this->logId1;
                $dumper->endId = $this->logId3 + 1;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // xmldumps-backup demands reporting, although this is currently not
                // implemented in BackupDumper, when dumping logging data. We
index 5cd8336..2262cc0 100644 (file)
@@ -104,7 +104,7 @@ class BackupDumperPageTest extends DumpTestCase {
                $dumper->loadWithArgv( [ '--full', '--quiet', '--output', 'file:' . $fname ] );
                $dumper->startId = $this->pageId1;
                $dumper->endId = $this->pageId4 + 1;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // Performing the dump
                $dumper->execute();
@@ -160,7 +160,7 @@ class BackupDumperPageTest extends DumpTestCase {
                $dumper->loadWithArgv( [ '--full', '--quiet', '--output', 'file:' . $fname, '--stub' ] );
                $dumper->startId = $this->pageId1;
                $dumper->endId = $this->pageId4 + 1;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // Performing the dump
                $dumper->execute();
@@ -210,7 +210,7 @@ class BackupDumperPageTest extends DumpTestCase {
                $dumper->startId = $this->pageId1;
                $dumper->endId = $this->pageId4 + 1;
                $dumper->reporting = false;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // Performing the dump
                $dumper->dump( WikiExporter::CURRENT, WikiExporter::STUB );
@@ -256,7 +256,7 @@ class BackupDumperPageTest extends DumpTestCase {
                $dumper->startId = $this->pageId1;
                $dumper->endId = $this->pageId4 + 1;
                $dumper->reporting = false;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // Performing the dump
                $dumper->dump( WikiExporter::CURRENT, WikiExporter::STUB );
@@ -318,7 +318,7 @@ class BackupDumperPageTest extends DumpTestCase {
                        "--reporting=1000" ] );
                $dumper->startId = $this->pageId1;
                $dumper->endId = $this->pageId4 + 1;
-               $dumper->setDb( $this->db );
+               $dumper->setDB( $this->db );
 
                // xmldumps-backup uses reporting. We will not check the exact reported
                // message, as they are dependent on the processing power of the used
index 86fc295..77690cd 100755 (executable)
@@ -10,6 +10,8 @@
 // through this entry point or not.
 define( 'MW_PHPUNIT_TEST', true );
 
+$wgPhpUnitClass = 'PHPUnit_TextUI_Command';
+
 // Start up MediaWiki in command-line mode
 require_once dirname( dirname( __DIR__ ) ) . "/maintenance/Maintenance.php";
 
@@ -30,11 +32,10 @@ class PHPUnitMaintClass extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->addOption(
-                       'with-phpunitdir',
-                       'Directory to include PHPUnit from, for example when using a git '
-                               . 'fetchout from upstream. Path will be prepended to PHP `include_path`.',
-                       false, # not required
-                       true # need arg
+                       'with-phpunitclass',
+                       'Class name of the PHPUnit entry point to use',
+                       false,
+                       true
                );
                $this->addOption(
                        'debug-tests',
@@ -115,7 +116,7 @@ class PHPUnitMaintClass extends Maintenance {
                // cookies to show up in a FauxRequest somewhere.
                $wgSessionProviders = [
                        [
-                               'class' => 'MediaWiki\\Session\\CookieSessionProvider',
+                               'class' => MediaWiki\Session\CookieSessionProvider::class,
                                'args' => [ [
                                        'priority' => 30,
                                        'callUserSetCookiesHook' => true,
@@ -158,38 +159,18 @@ class PHPUnitMaintClass extends Maintenance {
                                [ '--configuration', $IP . '/tests/phpunit/suite.xml' ] );
                }
 
-               # --with-phpunitdir let us override the default PHPUnit version
-               # Can use with either or phpunit.phar in the directory or the
-               # full PHPUnit code base.
-               if ( $this->hasOption( 'with-phpunitdir' ) ) {
-                       $phpunitDir = $this->getOption( 'with-phpunitdir' );
-
-                       # prepends provided PHPUnit directory or phar
-                       $this->output( "Will attempt loading PHPUnit from `$phpunitDir`\n" );
-                       set_include_path( $phpunitDir . PATH_SEPARATOR . get_include_path() );
+               if ( $this->hasOption( 'with-phpunitclass' ) ) {
+                       global $wgPhpUnitClass;
+                       $wgPhpUnitClass = $this->getOption( 'with-phpunitclass' );
 
                        # Cleanup $args array so the option and its value do not
                        # pollute PHPUnit
-                       $key = array_search( '--with-phpunitdir', $_SERVER['argv'] );
+                       $key = array_search( '--with-phpunitclass', $_SERVER['argv'] );
                        unset( $_SERVER['argv'][$key] ); // the option
                        unset( $_SERVER['argv'][$key + 1] ); // its value
                        $_SERVER['argv'] = array_values( $_SERVER['argv'] );
                }
 
-               # Makes MediaWiki PHPUnit directory includable so the PHPUnit will
-               # be able to resolve relative files inclusion such as suites/*
-               # PHPUnit uses stream_resolve_include_path() internally
-               # See bug 32022
-               $key = array_search( '--include-path', $_SERVER['argv'] );
-               if ( $key === false ) {
-                       array_splice( $_SERVER['argv'], 1, 0,
-                               __DIR__
-                               . PATH_SEPARATOR
-                               . get_include_path()
-                       );
-                       array_splice( $_SERVER['argv'], 1, 0, '--include-path' );
-               }
-
                $key = array_search( '--debug-tests', $_SERVER['argv'] );
                if ( $key !== false && array_search( '--printer', $_SERVER['argv'] ) === false ) {
                        unset( $_SERVER['argv'][$key] );
@@ -241,43 +222,14 @@ class PHPUnitMaintClass extends Maintenance {
 $maintClass = 'PHPUnitMaintClass';
 require RUN_MAINTENANCE_IF_MAIN;
 
-$ok = false;
-
-if ( class_exists( 'PHPUnit_TextUI_Command' ) ) {
-       echo "PHPUnit already present\n";
-       $ok = true;
-} else {
-       foreach ( [
-                               stream_resolve_include_path( 'phpunit.phar' ),
-                               stream_resolve_include_path( 'phpunit-old.phar' ),
-                               'PHPUnit/Runner/Version.php',
-                               'PHPUnit/Autoload.php'
-                       ] as $includePath ) {
-
-               if ( $includePath === false ) {
-                       // stream_resolve_include_path can return false
-                       continue;
-               }
-
-               \MediaWiki\suppressWarnings();
-               include_once $includePath;
-               \MediaWiki\restoreWarnings();
-               if ( class_exists( 'PHPUnit_TextUI_Command' ) ) {
-                       $ok = true;
-                       echo "Using PHPUnit from $includePath\n";
-                       break;
-               }
-       }
-}
-
-if ( !$ok ) {
-       echo "Couldn't find a usable PHPUnit.\n";
+if ( !class_exists( 'PHPUnit_Framework_TestCase' ) ) {
+       echo "PHPUnit not found. Please install it and other dev dependencies by
+running `composer install` in MediaWiki root directory.\n";
        exit( 1 );
 }
-
-$puVersion = PHPUnit_Runner_Version::id();
-if ( $puVersion !== '@package_version@' && version_compare( $puVersion, '3.7.0', '<' ) ) {
-       echo "PHPUnit 3.7.0 or later required; you have {$puVersion}.\n";
+if ( !class_exists( $wgPhpUnitClass ) ) {
+       echo "PHPUnit entry point '" . $wgPhpUnitClass . "' not found. Please make sure you installed
+the containing component and check the spelling of the class name.\n";
        exit( 1 );
 }
 
@@ -285,4 +237,4 @@ echo defined( 'HHVM_VERSION' ) ?
        'Using HHVM ' . HHVM_VERSION . ' (' . PHP_VERSION . ")\n" :
        'Using PHP ' . PHP_VERSION . "\n";
 
-PHPUnit_TextUI_Command::main();
+$wgPhpUnitClass::main();
index 81e2c65..aaa1feb 100644 (file)
@@ -78,7 +78,7 @@ class SideBarTest extends MediaWikiLangTestCase {
         * @covers SkinTemplate::addToSidebarPlain
         */
        public function testExpandMessages() {
-               $this->assertSidebar(
+               $this->assertSideBar(
                        [ 'Title' => [
                                [
                                        'text' => 'Help',
@@ -102,7 +102,7 @@ class SideBarTest extends MediaWikiLangTestCase {
                        'wgNoFollowDomainExceptions' => [],
                        'wgNoFollowNsExceptions' => [],
                ] );
-               $this->assertSidebar(
+               $this->assertSideBar(
                        [ 'Title' => [
                                # ** http://www.mediawiki.org/| Home
                                [
@@ -128,7 +128,7 @@ class SideBarTest extends MediaWikiLangTestCase {
         * @covers SkinTemplate::addToSidebarPlain
         */
        public function testTrickyPipe() {
-               $this->assertSidebar(
+               $this->assertSideBar(
                        [ 'Title' => [
                                # The first 2 are skipped
                                # Doesn't really test the url properly
@@ -163,7 +163,7 @@ class SideBarTest extends MediaWikiLangTestCase {
 ** http://www.mediawiki.org/| Home';
 
                $bar = [];
-               $this->skin->addToSideBarPlain( $bar, $text );
+               $this->skin->addToSidebarPlain( $bar, $text );
 
                return $bar['Title'][0];
        }
index 542420a..2049e38 100644 (file)
@@ -65,7 +65,7 @@ class ApiDocumentationTest extends MediaWikiTestCase {
                        RequestContext::getMain()->getConfig(),
                ] ) );
                foreach ( $globals as $k => $v ) {
-                       $this->setMWGlobals( "wg$k", $v );
+                       $this->setMwGlobals( "wg$k", $v );
                }
 
                // Fetch module.
diff --git a/tests/phpunit/structure/ExtensionJsonValidationTest.php b/tests/phpunit/structure/ExtensionJsonValidationTest.php
new file mode 100644 (file)
index 0000000..275c0d1
--- /dev/null
@@ -0,0 +1,93 @@
+<?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
+ */
+
+/**
+ * Validates all loaded extensions and skins using the ExtensionRegistry
+ * against the extension.json schema in the docs/ folder.
+ */
+class ExtensionJsonValidationTest extends PHPUnit_Framework_TestCase {
+
+       public function setUp() {
+               parent::setUp();
+               if ( !class_exists( 'JsonSchema\Uri\UriRetriever' ) ) {
+                       $this->markTestSkipped(
+                               'The JsonSchema library cannot be found,' .
+                               ' please install it through composer to run extension.json validation tests.'
+                       );
+               }
+
+               if ( !ExtensionRegistry::getInstance()->getAllThings() ) {
+                       $this->markTestSkipped(
+                               'There are no extensions or skins loaded via the ExtensionRegistry'
+                       );
+               }
+       }
+
+       public static function providePassesValidation() {
+               $values = [];
+               foreach ( ExtensionRegistry::getInstance()->getAllThings() as $thing ) {
+                       $values[] = [ $thing['path'] ];
+               }
+
+               return $values;
+       }
+
+       /**
+        * @dataProvider providePassesValidation
+        * @param string $path Path to thing's json file
+        */
+       public function testPassesValidation( $path ) {
+               $data = json_decode( file_get_contents( $path ) );
+               $this->assertInstanceOf( 'stdClass', $data, "$path is not valid JSON" );
+
+               $this->assertObjectHasAttribute( 'manifest_version', $data,
+                       "$path does not have manifest_version set." );
+               $version = $data->manifest_version;
+               if ( $version !== ExtensionRegistry::MANIFEST_VERSION ) {
+                       $schemaPath = __DIR__ . "/../../../docs/extension.schema.v$version.json";
+               } else {
+                       $schemaPath = __DIR__ . '/../../../docs/extension.schema.json';
+               }
+
+               // Not too old
+               $this->assertTrue(
+                       $version >= ExtensionRegistry::OLDEST_MANIFEST_VERSION,
+                       "$path is using a non-supported schema version"
+               );
+               // Not too new
+               $this->assertTrue(
+                       $version <= ExtensionRegistry::MANIFEST_VERSION,
+                       "$path is using a non-supported schema version"
+               );
+               $retriever = new JsonSchema\Uri\UriRetriever();
+               $schema = $retriever->retrieve( 'file://' . $schemaPath );
+
+               $validator = new JsonSchema\Validator();
+               $validator->check( $data, $schema );
+               if ( $validator->isValid() ) {
+                       // All good.
+                       $this->assertTrue( true );
+               } else {
+                       $out = "$path did pass validation.\n";
+                       foreach ( $validator->getErrors() as $error ) {
+                               $out .= "[{$error['property']}] {$error['message']}\n";
+                       }
+                       $this->assertTrue( false, $out );
+               }
+       }
+}
index 723328e..0e23fdd 100644 (file)
@@ -8,16 +8,14 @@
 class ExtensionsTestSuite extends PHPUnit_Framework_TestSuite {
        public function __construct() {
                parent::__construct();
-               $paths = array();
+               $paths = [];
                // Extensions can return a list of files or directories
-               Hooks::run( 'UnitTestsList', array( &$paths ) );
+               Hooks::run( 'UnitTestsList', [ &$paths ] );
                foreach ( $paths as $path ) {
                        if ( is_dir( $path ) ) {
                                // If the path is a directory, search for test cases.
                                // @since 1.24
-                               $suffixes = array(
-                                       'Test.php',
-                               );
+                               $suffixes = [ 'Test.php' ];
                                $fileIterator = new File_Iterator_Facade();
                                $matchingFiles = $fileIterator->getFilesAsArray( $path, $suffixes );
                                $this->addTestFiles( $matchingFiles );
@@ -26,7 +24,7 @@ class ExtensionsTestSuite extends PHPUnit_Framework_TestSuite {
                                $this->addTestFile( $path );
                        }
                }
-               if ( !count( $paths ) ) {
+               if ( !$paths ) {
                        $this->addTest( new DummyExtensionsTest( 'testNothing' ) );
                }
        }
index e3c5118..8366369 100644 (file)
@@ -37,7 +37,7 @@ class UploadFromUrlTestSuite extends PHPUnit_Framework_TestSuite {
                        'transformVia404' => false,
                        'backend' => new FSFileBackend( [
                                'name' => 'local-backend',
-                               'wikiId' => wfWikiId(),
+                               'wikiId' => wfWikiID(),
                                'containerPaths' => [
                                        'local-public' => "{$tmpDir}/test-repo/public",
                                        'local-thumb' => "{$tmpDir}/test-repo/thumb",
index 310268f..b7161b1 100644 (file)
@@ -8,14 +8,7 @@ return [
 
        'test.sinonjs' => [
                'scripts' => [
-                       'resources/lib/sinonjs/sinon-1.15.4.js',
-                       // We want tests to work in IE, but can't include this as it
-                       // will break the placeholders in Sinon because the hack it uses
-                       // to hijack IE globals relies on running in the global scope
-                       // and in ResourceLoader this won't be running in the global scope.
-                       // Including it results (among other things) in sandboxed timers
-                       // being broken due to Date inheritance being undefined.
-                       // 'resources/lib/sinonjs/sinon-ie-1.15.4.js',
+                       'resources/lib/sinonjs/sinon-1.17.3.js',
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
index f2865eb..dc0cff4 100644 (file)
@@ -6,12 +6,20 @@
        } ) );
 
        QUnit.test( 'Hello world', function ( assert ) {
-               QUnit.expect( 1 );
+               QUnit.expect( 3 );
 
                var api = new mw.Api();
 
                api.parse( '\'\'\'Hello world\'\'\'' ).done( function ( html ) {
-                       assert.equal( html, '<p><b>Hello world</b></p>' );
+                       assert.equal( html, '<p><b>Hello world</b></p>', 'Parse wikitext by string' );
+               } );
+
+               api.parse( {
+                       toString: function () {
+                               return '\'\'\'Hello world\'\'\'';
+                       }
+               } ).done( function ( html ) {
+                       assert.equal( html, '<p><b>Hello world</b></p>', 'Parse wikitext by toString object' );
                } );
 
                this.server.respondWith( /action=parse.*&text='''Hello\+world'''/, function ( request ) {
                        );
                } );
 
+               api.parse( new mw.Title( 'Earth' ) ).done( function ( html ) {
+                       assert.equal( html, '<p><b>Earth</b> is a planet.</p>', 'Parse page by Title object'  );
+               } );
+
+               this.server.respondWith( /action=parse.*&page=Earth/, function ( request ) {
+                       request.respond( 200, { 'Content-Type': 'application/json' },
+                               '{ "parse": { "text": "<p><b>Earth</b> is a planet.</p>" } }'
+                       );
+               } );
+
                this.server.respond();
        } );
 }( mediaWiki ) );
index 394f3bd..520db42 100644 (file)
@@ -3,11 +3,6 @@
                setup: function () {
                        this.server = this.sandbox.useFakeServer();
                        this.server.respondImmediately = true;
-                       this.clock = this.sandbox.useFakeTimers();
-               },
-               teardown: function () {
-                       // https://github.com/jquery/jquery/issues/2453
-                       this.clock.tick();
                }
        } ) );
 
                return sequence( bodies );
        }
 
-       QUnit.test( 'Basic functionality', function ( assert ) {
-               QUnit.expect( 2 );
+       QUnit.test( 'get()', function ( assert ) {
                var api = new mw.Api();
 
                this.server.respond( [ 200, { 'Content-Type': 'application/json' }, '[]' ] );
 
-               api.get( {} )
-                       .done( function ( data ) {
-                               assert.deepEqual( data, [], 'If request succeeds without errors, resolve deferred' );
-                       } );
+               return api.get( {} ).then( function ( data ) {
+                       assert.deepEqual( data, [], 'If request succeeds without errors, resolve deferred' );
+               } );
+       } );
 
-               api.post( {} )
-                       .done( function ( data ) {
-                               assert.deepEqual( data, [], 'Simple POST request' );
-                       } );
+       QUnit.test( 'post()', function ( assert ) {
+               var api = new mw.Api();
+
+               this.server.respond( [ 200, { 'Content-Type': 'application/json' }, '[]' ] );
+
+               return api.post( {} ).then( function ( data ) {
+                       assert.deepEqual( data, [], 'Simple POST request' );
+               } );
        } );
 
        QUnit.test( 'API error', function ( assert ) {
-               QUnit.expect( 1 );
                var api = new mw.Api();
 
                this.server.respond( [ 200, { 'Content-Type': 'application/json' },
                api.get( { action: 'doesntexist' } )
                        .fail( function ( errorCode ) {
                                assert.equal( errorCode, 'unknown_action', 'API error should reject the deferred' );
-                       } );
+                       } )
+                       .always( assert.async() );
        } );
 
        QUnit.test( 'FormData support', function ( assert ) {
-               QUnit.expect( 2 );
                var api = new mw.Api();
 
                this.server.respond( function ( request ) {
                        request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
                } );
 
-               api.post( { action: 'test' }, { contentType: 'multipart/form-data' } );
+               return api.post( { action: 'test' }, { contentType: 'multipart/form-data' } );
        } );
 
        QUnit.test( 'Converting arrays to pipe-separated', function ( assert ) {
-               QUnit.expect( 1 );
                var api = new mw.Api();
 
                this.server.respond( function ( request ) {
                        request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
                } );
 
-               api.get( { test: [ 'foo', 'bar', 'baz' ] } );
+               return api.get( { test: [ 'foo', 'bar', 'baz' ] } );
        } );
 
        QUnit.test( 'Omitting false booleans', function ( assert ) {
-               QUnit.expect( 2 );
                var api = new mw.Api();
 
                this.server.respond( function ( request ) {
                        request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
                } );
 
-               api.get( { foo: false, bar: true } );
+               return api.get( { foo: false, bar: true } );
        } );
 
        QUnit.test( 'getToken() - cached', function ( assert ) {
-               QUnit.expect( 2 );
-               var api = new mw.Api();
+               var api = new mw.Api(),
+                       test = this;
 
                // Get editToken for local wiki, this should not make
                // a request as it should be retrieved from mw.user.tokens.
-               api.getToken( 'edit' )
-                       .done( function ( token ) {
+               return api.getToken( 'edit' )
+                       .then( function ( token ) {
                                assert.ok( token.length, 'Got a token' );
-                       } )
-                       .fail( function ( err ) {
+                       }, function ( err ) {
                                assert.equal( '', err, 'API error' );
+                       } )
+                       .then( function () {
+                               assert.equal( test.server.requests.length, 0, 'Requests made' );
                        } );
-
-               assert.equal( this.server.requests.length, 0, 'Requests made' );
        } );
 
        QUnit.test( 'getToken() - uncached', function ( assert ) {
-               QUnit.expect( 3 );
-               var api = new mw.Api();
+               var api = new mw.Api(),
+                       firstDone = assert.async(),
+                       secondDone = assert.async();
 
                this.server.respondWith( /type=testuncached/, [ 200, { 'Content-Type': 'application/json' },
                        '{ "query": { "tokens": { "testuncachedtoken": "good" } } }'
                        } )
                        .fail( function ( err ) {
                                assert.equal( err, '', 'API error' );
-                       } );
+                       } )
+                       .always( firstDone );
 
                api.getToken( 'testuncached' )
                        .done( function ( token ) {
                        } )
                        .fail( function ( err ) {
                                assert.equal( err, '', 'API error' );
-                       } );
+                       } )
+                       .always( secondDone );
 
                assert.equal( this.server.requests.length, 1, 'Requests made' );
        } );
 
        QUnit.test( 'getToken() - error', function ( assert ) {
-               QUnit.expect( 2 );
                var api = new mw.Api();
 
                this.server.respondWith( /type=testerror/, sequenceBodies( 200, { 'Content-Type': 'application/json' },
                ) );
 
                // Don't cache error (bug 65268)
-               api.getToken( 'testerror' ).fail( function ( err ) {
-                       assert.equal( err, 'bite-me', 'Expected error' );
-
-                       // Make this request after the first one has finished.
-                       // If we make it simultaneously we still want it to share
-                       // the cache, but as soon as it is fulfilled as error we
-                       // reject it so that the next one tries fresh.
-                       api.getToken( 'testerror' ).done( function ( token ) {
+               return api.getToken( 'testerror' )
+                       .then( null, function ( err ) {
+                               assert.equal( err, 'bite-me', 'Expected error' );
+
+                               return api.getToken( 'testerror' );
+                       } )
+                       .then( function ( token ) {
                                assert.equal( token, 'good', 'The token' );
                        } );
-               } );
        } );
 
        QUnit.test( 'getToken() - deprecated', function ( assert ) {
-               QUnit.expect( 2 );
                // Cache API endpoint from default to avoid cachehit in mw.user.tokens
-               var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
+               var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } ),
+                       test = this;
 
                this.server.respondWith( /type=csrf/, [ 200, { 'Content-Type': 'application/json' },
                        '{ "query": { "tokens": { "csrftoken": "csrfgood" } } }'
                ] );
 
                // Get a token of a type that is in the legacy map.
-               api.getToken( 'email' )
+               return api.getToken( 'email' )
                        .done( function ( token ) {
                                assert.equal( token, 'csrfgood', 'Token' );
                        } )
                        .fail( function ( err ) {
                                assert.equal( err, '', 'API error' );
+                       } )
+                       .always( function () {
+                               assert.equal( test.server.requests.length, 1, 'Requests made' );
                        } );
-
-               assert.equal( this.server.requests.length, 1, 'Requests made' );
        } );
 
        QUnit.test( 'badToken()', function ( assert ) {
-               QUnit.expect( 2 );
                var api = new mw.Api(),
                        test = this;
 
                        ]
                ) );
 
-               api.getToken( 'testbad' )
+               return api.getToken( 'testbad' )
                        .then( function () {
                                api.badToken( 'testbad' );
                                return api.getToken( 'testbad' );
        } );
 
        QUnit.test( 'badToken( legacy )', function ( assert ) {
-               QUnit.expect( 2 );
                var api = new mw.Api( { ajax: { url: '/badTokenLegacy/api.php' } } ),
                        test = this;
 
                        ]
                ) );
 
-               api.getToken( 'options' )
+               return api.getToken( 'options' )
                        .then( function () {
                                api.badToken( 'options' );
                                return api.getToken( 'options' );
        } );
 
        QUnit.test( 'postWithToken( tokenType, params )', function ( assert ) {
-               QUnit.expect( 1 );
                var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
 
                this.server.respondWith( 'GET', /type=testpost/, [ 200, { 'Content-Type': 'application/json' },
                        }
                } );
 
-               api.postWithToken( 'testpost', { action: 'example', key: 'foo' } )
-                       .done( function ( data ) {
+               return api.postWithToken( 'testpost', { action: 'example', key: 'foo' } )
+                       .then( function ( data ) {
                                assert.deepEqual( data, { example: { foo: 'quux' } } );
                        } );
        } );
 
        QUnit.test( 'postWithToken( tokenType, params with assert )', function ( assert ) {
-               QUnit.expect( 2 );
-               var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
+               var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } ),
+                       test = this;
 
                this.server.respondWith( /assert=user/, [ 200, { 'Content-Type': 'application/json' },
                        '{ "error": { "code": "assertuserfailed", "info": "Assertion failed" } }'
                ] );
 
-               api.postWithToken( 'testassertpost', { action: 'example', key: 'foo', assert: 'user' } )
-                       .fail( function ( errorCode ) {
+               return api.postWithToken( 'testassertpost', { action: 'example', key: 'foo', assert: 'user' } )
+                       // Cast error to success and vice versa
+                       .then( function ( ) {
+                               return $.Deferred().reject( 'Unexpected success' );
+                       }, function ( errorCode ) {
                                assert.equal( errorCode, 'assertuserfailed', 'getToken fails assert' );
+                               return $.Deferred().resolve();
+                       } )
+                       .then( function () {
+                               assert.equal( test.server.requests.length, 1, 'Requests made' );
                        } );
-
-               assert.equal( this.server.requests.length, 1, 'Requests made' );
        } );
 
        QUnit.test( 'postWithToken( tokenType, params, ajaxOptions )', function ( assert ) {
-               QUnit.expect( 3 );
-               var api = new mw.Api();
+               var api = new mw.Api(),
+                       test = this;
 
                this.server.respond( [ 200, { 'Content-Type': 'application/json' }, '{ "example": "quux" }' ] );
 
-               api.postWithToken(
-                       'edit',
-                       {
-                               action: 'example'
-                       },
-                       {
-                               headers: {
-                                       'X-Foo': 'Bar'
+               return api.postWithToken( 'edit',
+                               { action: 'example' },
+                               {
+                                       headers: {
+                                               'X-Foo': 'Bar'
+                                       }
                                }
-                       }
-               );
+                       )
+                       .then( function () {
+                               assert.equal( test.server.requests[ 0 ].requestHeaders[ 'X-Foo' ], 'Bar', 'Header sent' );
 
-               api.postWithToken(
-                       'edit',
-                       {
-                               action: 'example'
-                       },
-                       function () {
-                               assert.ok( false, 'This parameter cannot be a callback' );
-                       }
-               )
-               .always( function ( data ) {
-                       assert.equal( data.example, 'quux' );
-               } );
+                               return api.postWithToken( 'edit',
+                                       { action: 'example' },
+                                       function () {
+                                               assert.ok( false, 'This parameter cannot be a callback' );
+                                       }
+                               );
+                       } )
+                       .then( function ( data ) {
+                               assert.equal( data.example, 'quux' );
 
-               assert.equal( this.server.requests.length, 2, 'Request made' );
-               assert.equal( this.server.requests[ 0 ].requestHeaders[ 'X-Foo' ], 'Bar', 'Header sent' );
+                               assert.equal( test.server.requests.length, 2, 'Request made' );
+                       } );
        } );
 
        QUnit.test( 'postWithToken() - badtoken', function ( assert ) {
-               QUnit.expect( 1 );
                var api = new mw.Api();
 
                this.server.respondWith( /type=testbadtoken/, sequenceBodies( 200, { 'Content-Type': 'application/json' },
                // - Request: action=example -> badtoken error
                // - Request: new token -> good
                // - Request: action=example -> success
-               api.postWithToken( 'testbadtoken', { action: 'example', key: 'foo' } )
-                       .done( function ( data ) {
+               return api.postWithToken( 'testbadtoken', { action: 'example', key: 'foo' } )
+                       .then( function ( data ) {
                                assert.deepEqual( data, { example: { foo: 'quux' } } );
                        } );
        } );
 
        QUnit.test( 'postWithToken() - badtoken-cached', function ( assert ) {
-               QUnit.expect( 2 );
                var sequenceA,
                        api = new mw.Api();
 
 
                // - Request: new token -> A
                // - Request: action=example
-               api.postWithToken( 'testonce', { action: 'example', key: 'foo' } )
-                       .done( function ( data ) {
+               return api.postWithToken( 'testonce', { action: 'example', key: 'foo' } )
+                       .then( function ( data ) {
                                assert.deepEqual( data, { example: { value: 'A' } } );
-                       } );
 
-               // - Request: action=example w/ token A -> badtoken error
-               // - Request: new token -> B
-               // - Request: action=example w/ token B -> success
-               api.postWithToken( 'testonce', { action: 'example', key: 'bar' } )
-                       .done( function ( data ) {
+                               // - Request: action=example w/ token A -> badtoken error
+                               // - Request: new token -> B
+                               // - Request: action=example w/ token B -> success
+                               return api.postWithToken( 'testonce', { action: 'example', key: 'bar' } );
+                       } )
+                       .then( function ( data ) {
                                assert.deepEqual( data, { example: { value: 'B' } } );
                        } );
        } );
index 932ba7d..991725b 100644 (file)
 
        QUnit.test( 'getUrl', 4, function ( assert ) {
                var title;
-
-               // Config
-               mw.config.set( 'wgArticlePath', '/wiki/$1' );
+               mw.config.set( {
+                       wgScript: '/w/index.php',
+                       wgArticlePath: '/wiki/$1'
+               } );
 
                title = new mw.Title( 'Foobar' );
                assert.equal( title.getUrl(), '/wiki/Foobar', 'Basic functionality, getUrl uses mw.util.getUrl' );
-               assert.equal( title.getUrl( { action: 'edit' } ), '/wiki/Foobar?action=edit', 'Basic functionality, \'params\' parameter' );
+               assert.equal( title.getUrl( { action: 'edit' } ), '/w/index.php?title=Foobar&action=edit', 'Basic functionality, \'params\' parameter' );
 
                title = new mw.Title( 'John Doe', 3 );
                assert.equal( title.getUrl(), '/wiki/User_talk:John_Doe', 'Escaping in title and namespace for urls' );
 
                title = new mw.Title( 'John Cena#And_His_Name_Is', 3 );
-               assert.equal( title.getUrl( { meme: true } ), '/wiki/User_talk:John_Cena?meme=true#And_His_Name_Is', 'title with fragment and query parameter' );
+               assert.equal( title.getUrl( { meme: true } ), '/w/index.php?title=User_talk:John_Cena&meme=true#And_His_Name_Is', 'title with fragment and query parameter' );
        } );
 
        QUnit.test( 'newFromImg', 44, function ( assert ) {
index 07eddbf..ee948bb 100644 (file)
@@ -81,8 +81,9 @@
                        'jquerymsg-test-version-entrypoints-index-php': '[https://www.mediawiki.org/wiki/Manual:index.php index.php]',
 
                        'external-link-replace': 'Foo [$1 bar]',
-                       'external-link-plural': 'Foo {{PLURAL:$1|is [$2 one]|are [$2 some]|2=[$2 two]|3=three|4=a=b|5=}} things.',
-                       'plural-only-explicit-forms': 'It is a {{PLURAL:$1|1=single|2=double}} room.'
+                       'external-link-plural': 'Foo {{PLURAL:$1|is [$2 one]|are [$2 some]|2=[$2 two]|3=three|4=a=b}} things.',
+                       'plural-only-explicit-forms': 'It is a {{PLURAL:$1|1=single|2=double}} room.',
+                       'plural-empty-explicit-form': 'There is me{{PLURAL:$1|0=| and other people}}.'
                }
        } ) );
 
                next();
        }
 
-       QUnit.test( 'Replace', 16, function ( assert ) {
+       QUnit.test( 'Replace', 15, function ( assert ) {
                mw.messages.set( 'simple', 'Foo $1 baz $2' );
 
                assert.equal( formatParse( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' );
                        'Foo a=b things.',
                        'Only first equal sign is used as delimiter for explicit plural form. Repeated equal signs does not create issue'
                );
-               assert.equal(
-                       formatParse( 'external-link-plural', 5, 'http://example.org' ),
-                       'Foo are <a href="http://example.org">some</a> things.',
-                       'Invalid explicit plural form. Plural fallback to the "other" plural form'
-               );
                assert.equal(
                        formatParse( 'external-link-plural', 6, 'http://example.org' ),
                        'Foo are <a href="http://example.org">some</a> things.',
                );
        } );
 
-       QUnit.test( 'Plural', 6, function ( assert ) {
+       QUnit.test( 'Plural', 9, function ( assert ) {
                assert.equal( formatParse( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' );
                assert.equal( formatParse( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' );
                assert.equal( formatParse( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' );
                assert.equal( formatParse( 'plural-msg-explicit-forms-nested', 6 ), 'Found 6 results', 'Plural message with explicit plural forms' );
                assert.equal( formatParse( 'plural-msg-explicit-forms-nested', 0 ), 'Found no results in Wiki', 'Plural message with explicit plural forms, with nested {{SITENAME}}' );
                assert.equal( formatParse( 'plural-msg-explicit-forms-nested', 1 ), 'Found 1 result', 'Plural message with explicit plural forms with placeholder nested' );
+               assert.equal( formatParse( 'plural-empty-explicit-form', 0 ), 'There is me.' );
+               assert.equal( formatParse( 'plural-empty-explicit-form', 1 ), 'There is me and other people.' );
+               assert.equal( formatParse( 'plural-empty-explicit-form', 2 ), 'There is me and other people.' );
        } );
 
        QUnit.test( 'Gender', 15, function ( assert ) {
index 3772097..7a09964 100644 (file)
 ( function ( mw ) {
        QUnit.module( 'mediawiki.requestIdleCallback', QUnit.newMwEnvironment( {
                setup: function () {
-                       var time = mw.now(),
-                               clock = this.clock = this.sandbox.useFakeTimers();
+                       var clock = this.clock = this.sandbox.useFakeTimers();
 
-                       this.tick = function ( forward ) {
-                               time += forward;
-                               clock.tick( forward );
-                       };
                        this.sandbox.stub( mw, 'now', function () {
-                               return time;
+                               return +new Date();
                        } );
 
-                       // Don't test the native version (if available)
-                       this.mwRIC = mw.requestIdleCallback;
-                       mw.requestIdleCallback = mw.requestIdleCallbackInternal;
-               },
-               teardown: function () {
-                       mw.requestIdleCallback = this.mwRIC;
+                       this.tick = function ( forward ) {
+                               return clock.tick( forward || 1 );
+                       };
+
+                       // Always test the polyfill, not native
+                       this.sandbox.stub( mw, 'requestIdleCallback', mw.requestIdleCallbackInternal );
                }
        } ) );
 
-       // Basic scheduling of callbacks
-       QUnit.test( 'callback', 3, function ( assert ) {
-               var sequence,
-                       tick = this.tick;
+       QUnit.test( 'callback', function ( assert ) {
+               var sequence;
 
                mw.requestIdleCallback( function () {
                        sequence.push( 'x' );
-                       tick( 30 );
                } );
                mw.requestIdleCallback( function () {
-                       tick( 5 );
                        sequence.push( 'y' );
-                       tick( 30 );
                } );
-               // Task Z is not run in the first sequence because the
-               // first two tasks consumed the available 50ms budget.
                mw.requestIdleCallback( function () {
                        sequence.push( 'z' );
-                       tick( 30 );
                } );
 
                sequence = [];
-               tick( 1000 );
-               assert.deepEqual( sequence, [ 'x', 'y' ] );
-
-               sequence = [];
-               tick( 1000 );
-               assert.deepEqual( sequence, [ 'z' ] );
-
-               sequence = [];
-               tick( 1000 );
-               assert.deepEqual( sequence, [] );
+               this.tick();
+               assert.deepEqual( sequence, [ 'x', 'y', 'z' ] );
        } );
 
-       // Schedule new callbacks within a callback that tick
-       // the clock. If the budget is exceeded, the newly scheduled
-       // task is delayed until the next idle period.
-       QUnit.test( 'nest-tick', 3, function ( assert ) {
-               var sequence,
-                       tick = this.tick;
+       QUnit.test( 'nested', function ( assert ) {
+               var sequence;
 
                mw.requestIdleCallback( function () {
                        sequence.push( 'x' );
-                       tick( 30 );
                } );
                // Task Y is a task that schedules another task.
                mw.requestIdleCallback( function () {
                        function other() {
                                sequence.push( 'y' );
-                               tick( 35 );
                        }
                        mw.requestIdleCallback( other );
                } );
                mw.requestIdleCallback( function () {
                        sequence.push( 'z' );
-                       tick( 30 );
                } );
 
                sequence = [];
-               tick( 1000 );
+               this.tick();
                assert.deepEqual( sequence, [ 'x', 'z' ] );
 
                sequence = [];
-               tick( 1000 );
+               this.tick();
                assert.deepEqual( sequence, [ 'y' ] );
-
-               sequence = [];
-               tick( 1000 );
-               assert.deepEqual( sequence, [] );
        } );
 
-       // Schedule new callbacks within a callback that run quickly.
-       // Note how the newly scheduled task gets to run as part of the
-       // current idle period (budget allowing).
-       QUnit.test( 'nest-quick', 2, function ( assert ) {
+       QUnit.test( 'timeRemaining', function ( assert ) {
                var sequence,
-                       tick = this.tick;
-
-               mw.requestIdleCallback( function () {
-                       sequence.push( 'x' );
-                       mw.requestIdleCallback( function () {
-                               sequence.push( 'x-expand' );
-                       } );
-               } );
-               mw.requestIdleCallback( function () {
-                       sequence.push( 'y' );
+                       tick = this.tick,
+                       jobs = [
+                               { time: 10, key: 'a' },
+                               { time: 20, key: 'b' },
+                               { time: 10, key: 'c' },
+                               { time: 20, key: 'd' },
+                               { time: 10, key: 'e' }
+                       ];
+
+               mw.requestIdleCallback( function doWork( deadline ) {
+                       var job;
+                       while ( jobs[ 0 ] && deadline.timeRemaining() > 15 ) {
+                               job = jobs.shift();
+                               tick( job.time );
+                               sequence.push( job.key );
+                       }
+                       if ( jobs[ 0 ] ) {
+                               mw.requestIdleCallback( doWork );
+                       }
                } );
 
                sequence = [];
-               tick( 1000 );
-               assert.deepEqual( sequence, [ 'x', 'y', 'x-expand' ] );
+               tick();
+               assert.deepEqual( sequence, [ 'a', 'b', 'c' ] );
 
                sequence = [];
-               tick( 1000 );
-               assert.deepEqual( sequence, [] );
+               tick();
+               assert.deepEqual( sequence, [ 'd', 'e' ] );
        } );
 
+       if ( window.requestIdleCallback ) {
+               QUnit.test( 'native', function ( assert ) {
+                       var done = assert.async();
+                       // Remove polyfill
+                       mw.requestIdleCallback.restore();
+                       mw.requestIdleCallback( function () {
+                               assert.expect( 0 );
+                               done();
+                       } );
+               } );
+       }
+
 }( mediaWiki ) );
index 04e002d..3332c08 100644 (file)
@@ -41,6 +41,8 @@
        } );
 
        QUnit.test( 'getUserInfos', 3, function ( assert ) {
+               mw.config.set( 'wgUserGroups', [ '*', 'user' ] );
+
                mw.user.getGroups( function ( groups ) {
                        assert.deepEqual( groups, [ '*', 'user' ], 'Result' );
                } );
@@ -55,7 +57,7 @@
 
                this.server.respondWith( /meta=userinfo/, function ( request ) {
                        request.respond( 200, { 'Content-Type': 'application/json' },
-                               '{ "query": { "userinfo": { "groups": [ "*", "user" ], "rights": [ "read", "edit", "createtalk" ] } } }'
+                               '{ "query": { "userinfo": { "groups": [ "unused" ], "rights": [ "read", "edit", "createtalk" ] } } }'
                        );
                } );
 
index 5d72179..d697507 100644 (file)
                } );
        } );
 
-       QUnit.test( 'getUrl', 12, function ( assert ) {
+       QUnit.test( 'getUrl', 13, function ( assert ) {
+               var href;
                mw.config.set( {
+                       wgScript: '/w/index.php',
                        wgArticlePath: '/wiki/$1',
                        wgPageName: 'Foobar'
                } );
 
-               var href = mw.util.getUrl( 'Sandbox' );
+               href = mw.util.getUrl( 'Sandbox' );
                assert.equal( href, '/wiki/Sandbox', 'simple title' );
 
                href = mw.util.getUrl( 'Foo:Sandbox? 5+5=10! (test)/sub ' );
-               assert.equal( href, '/wiki/Foo:Sandbox%3F_5%2B5%3D10!_(test)/sub_', 'advanced title' );
+               assert.equal( href, '/wiki/Foo:Sandbox%3F_5%2B5%3D10!_(test)/sub_', 'complex title' );
 
                href = mw.util.getUrl();
                assert.equal( href, '/wiki/Foobar', 'default title' );
 
                href = mw.util.getUrl( null, { action: 'edit' } );
-               assert.equal( href, '/wiki/Foobar?action=edit', 'default title with query string' );
+               assert.equal( href, '/w/index.php?title=Foobar&action=edit', 'default title with query string' );
 
                href = mw.util.getUrl( 'Sandbox', { action: 'edit' } );
-               assert.equal( href, '/wiki/Sandbox?action=edit', 'simple title with query string' );
+               assert.equal( href, '/w/index.php?title=Sandbox&action=edit', 'simple title with query string' );
 
                // Test fragments
                href = mw.util.getUrl( 'Foo:Sandbox#Fragment', { action: 'edit' } );
-               assert.equal( href, '/wiki/Foo:Sandbox?action=edit#Fragment', 'advanced title with query string and fragment' );
+               assert.equal( href, '/w/index.php?title=Foo:Sandbox&action=edit#Fragment', 'namespaced title with query string and fragment' );
 
-               href = mw.util.getUrl( 'Foo:Sandbox#', { action: 'edit' } );
-               assert.equal( href, '/wiki/Foo:Sandbox?action=edit', 'title with query string and empty fragment' );
+               href = mw.util.getUrl( 'Sandbox#', { action: 'edit' } );
+               assert.equal( href, '/w/index.php?title=Sandbox&action=edit', 'title with query string and empty fragment' );
+
+               href = mw.util.getUrl( 'Sandbox', {} );
+               assert.equal( href, '/wiki/Sandbox', 'title with empty query string' );
 
                href = mw.util.getUrl( '#Fragment' );
-               assert.equal( href, '/wiki/#Fragment', 'epmty title with fragment' );
+               assert.equal( href, '/wiki/#Fragment', 'empty title with fragment' );
 
                href = mw.util.getUrl( '#Fragment', { action: 'edit' } );
-               assert.equal( href, '/wiki/?action=edit#Fragment', 'epmty title with query string and fragment' );
+               assert.equal( href, '/w/index.php?action=edit#Fragment', 'epmty title with query string and fragment' );
 
                href = mw.util.getUrl( 'Foo:Sandbox \xC4#Fragment \xC4', { action: 'edit' } );
-               assert.equal( href, '/wiki/Foo:Sandbox_%C3%84?action=edit#Fragment_.C3.84', 'title with query string, fragment, and special characters' );
+               assert.equal( href, '/w/index.php?title=Foo:Sandbox_%C3%84&action=edit#Fragment_.C3.84', 'title with query string, fragment, and special characters' );
 
                href = mw.util.getUrl( 'Foo:%23#Fragment', { action: 'edit' } );
-               assert.equal( href, '/wiki/Foo:%2523?action=edit#Fragment', 'title containing %23 (#), fragment, and a query string' );
+               assert.equal( href, '/w/index.php?title=Foo:%2523&action=edit#Fragment', 'title containing %23 (#), fragment, and a query string' );
 
                href = mw.util.getUrl( '#+&=:;@$-_.!*/[]<>\'§', { action: 'edit' } );
-               assert.equal( href, '/wiki/?action=edit#.2B.26.3D:.3B.40.24-_..21.2A.2F.5B.5D.3C.3E.27.C2.A7', 'fragment with various characters' );
+               assert.equal( href, '/w/index.php?action=edit#.2B.26.3D:.3B.40.24-_..21.2A.2F.5B.5D.3C.3E.27.C2.A7', 'fragment with various characters' );
        } );
 
        QUnit.test( 'wikiScript', 4, function ( assert ) {
index 61391d8..f404294 100644 (file)
                        'It should default to the window object if no viewport is given' );
        } );
 
+       QUnit.test( 'isElementInViewport with scrolled page', 1, function ( assert ) {
+               var viewport = {
+                               top: 2000,
+                               left: 0,
+                               right: 1000,
+                               bottom: 2500
+                       },
+                       el = $( '<div />' )
+                               .appendTo( '#qunit-fixture' )
+                               .width( 20 )
+                               .height( 20 )
+                               .offset( {
+                                       top: 2300,
+                                       left: 20
+                               } )
+                               .get( 0 );
+               window.scrollTo( viewport.left, viewport.top );
+               assert.ok( mw.viewport.isElementInViewport( el, viewport ),
+                       'It should return true when the element is fully enclosed in the ' +
+                       'viewport even when the page is scrolled down' );
+               window.scrollTo( 0, 0 );
+       } );
+
        QUnit.test( 'isElementCloseToViewport', 3, function ( assert ) {
                var
                        viewport = {